Android Check Permission for Locationmanager

Checking Permissions on Android Location Manager

Starting from Android M just declaring permissions in manifest is not enough. You have to implement permission model in order to successfully get the permissions granted.

Looking at your code, you are missing the permission request. Follow this official guile and implement permission model in order to get the expected result.

    ActivityCompat.requestPermissions(thisActivity,
new String[] {Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);

Check result as follows:

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
//pare grantResults
return;
}
}
}

Android check Location permission error

use this permission check using ActivityCompat

if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}

LocationManager checkPermission

Here is some code that might help.

You will need to wrap the location request with try/catch for security exceptions.

Add to strings.xml:

<string name="location_permission_rationale">"Location permission is needed for providing nearby services."</string>

Import this:

import static android.Manifest.permission.ACCESS_FINE_LOCATION;

Needed in your activity class and LocationHandler

/**
* Id to identity LOCATION permission request.
*/
private static final int REQUEST_LOCATION = 0;

...

Override in your activity class:

/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_LOCATION) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// You can request location here and update your vars
}
}
}

Add this to your LocationHandler class and call from the constructor. If it returns true, you are gtg. If it returns false then you'll have to do your location updates in the callback.

private boolean requestLocationPermission() {

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(mContext, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
return true;
}

if (shouldShowRequestPermissionRationale((Activity)mContext, ACCESS_FINE_LOCATION)) {

Snackbar.make(((Activity)mContext).getWindow().getDecorView().findViewById(android.R.id.content),
((Activity)mContext).getResources().getString(R.string.location_permission_rationale), Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions((Activity)mContext, new String[]{ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
}
});
} else {
requestPermissions((Activity)mContext, new String[]{ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
}
return false;
}

requestLocationUpdates permission

You will have to write a method to check whether permission is given by user. If not then ask user for permission.
Constants.LOCATION_PERMISSION_REQUEST is just requestcode to match when got callback in onRequestpermission result

public static boolean checkLocationPermission(Activity activity){
if(ActivityCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){

ActivityCompat.requestPermissions(activity, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION}, Constants.LOCATION_PERMISSION_REQUEST);
return false;
}
return true;
}

As the user allows, you will get callback on overridden method "onRequestPermissionsResult()"

How to ask for location permission in Android Studio?

From API level 23 (Android 6.0 Marshmallow) we need to ask Run-time permission from the user-end. You can do this in two steps.

1) Add these two permissions in AndroidManifest.xml file.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

Example:

<manifest xlmns:android...>
...
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application ...
</manifest>

2) Put this code block inside class where you need to get current location

    if ( Build.VERSION.SDK_INT >= 23){
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED ){
requestPermissions(new String[]{
android.Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
return ;
}
}

getLocation();

}
//get access to location permission
final private int REQUEST_CODE_ASK_PERMISSIONS = 123;

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLocation();
} else {
// Permission Denied
Toast.makeText( this,"your message" , Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

//Get location
public void getLocation(){
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Location myLocation=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (myLocation == null)
{
myLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);

}
}

How to request Location Permission at runtime

You need to actually request the Location permission at runtime (notice the comments in your code stating this).

Updated with Kotlin and background location for API 31 (Android 12):

Starting with API 30 background location must be requested separately.
This example is using targetSdk 31 and compileSdk 31.
Note that it's possible to bundle the background location request along with the main location request on API 29, however to do that you would need to maintain three separate code paths.

It's easier to just break it out to separate requests for 29 and above.

Be sure to include the latest location services in the app level gradle (18.0.0 at the time of writing):

implementation "com.google.android.gms:play-services-location:18.0.0"

Include the location permissions in the manifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

This is a simplified example that does handle most cases, but in a simplified way. In the case where a user chooses "Don't ask again", on the next app launch it will open up the settings for the user to manually enable the permission.

Full activity code:

import android.Manifest
import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Looper
import android.provider.Settings
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.gms.location.*

class MainActivity : AppCompatActivity() {

private var fusedLocationProvider: FusedLocationProviderClient? = null
private val locationRequest: LocationRequest = LocationRequest.create().apply {
interval = 30
fastestInterval = 10
priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
maxWaitTime = 60
}

private var locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
val locationList = locationResult.locations
if (locationList.isNotEmpty()) {
//The last location in the list is the newest
val location = locationList.last()
Toast.makeText(
this@MainActivity,
"Got Location: " + location.toString(),
Toast.LENGTH_LONG
)
.show()
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

fusedLocationProvider = LocationServices.getFusedLocationProviderClient(this)

checkLocationPermission()
}

override fun onResume() {
super.onResume()
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
) {

fusedLocationProvider?.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
}

override fun onPause() {
super.onPause()
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
== PackageManager.PERMISSION_GRANTED
) {

fusedLocationProvider?.removeLocationUpdates(locationCallback)
}
}

private fun checkLocationPermission() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
AlertDialog.Builder(this)
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton(
"OK"
) { _, _ ->
//Prompt the user once explanation has been shown
requestLocationPermission()
}
.create()
.show()
} else {
// No explanation needed, we can request the permission.
requestLocationPermission()
}
} else {
checkBackgroundLocation()
}
}

private fun checkBackgroundLocation() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
requestBackgroundLocationPermission()
}
}

private fun requestLocationPermission() {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
),
MY_PERMISSIONS_REQUEST_LOCATION
)
}

private fun requestBackgroundLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.ACCESS_BACKGROUND_LOCATION
),
MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION
)
} else {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
MY_PERMISSIONS_REQUEST_LOCATION
)
}
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
when (requestCode) {
MY_PERMISSIONS_REQUEST_LOCATION -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
fusedLocationProvider?.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)

// Now check background location
checkBackgroundLocation()
}

} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show()

// Check if we are in a state where the user has denied the permission and
// selected Don't ask again
if (!ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
) {
startActivity(
Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", this.packageName, null),
),
)
}
}
return
}
MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
fusedLocationProvider?.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)

Toast.makeText(
this,
"Granted Background Location Permission",
Toast.LENGTH_LONG
).show()
}
} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show()
}
return

}
}
}

companion object {
private const val MY_PERMISSIONS_REQUEST_LOCATION = 99
private const val MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION = 66
}
}

On Android 10 (API 29) it will give the user the choice to grant background location after the initial location request:

Sample Image

Sample Image

On Android 12 (API 31) it will do the same, but the interface is different:

Sample Image

Sample Image

Sample Image

Original Answer in Java:

Here is tested and working code to request the Location permission.

Put this code in the Activity:

public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {

// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
new AlertDialog.Builder(this)
.setTitle(R.string.title_location_permission)
.setMessage(R.string.text_location_permission)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();

} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {

//Request location updates:
locationManager.requestLocationUpdates(provider, 400, 1, this);
}

} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.

}
return;
}

}
}

Then call the checkLocationPermission() method in onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//.........

checkLocationPermission();
}

You can then use onResume() and onPause() exactly as it is in the question.

Here is a condensed version that is a bit more clean:

@Override
protected void onResume() {
super.onResume();
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {

locationManager.requestLocationUpdates(provider, 400, 1, this);
}
}

@Override
protected void onPause() {
super.onPause();
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {

locationManager.removeUpdates(this);
}
}

How to gain permission to get GPS location in Android

Fixed by implementing LocationListener in Fragment and then adding

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 400, 1, this);

in onRequestPermissionsResult().



Related Topics



Leave a reply



Submit