gyamana gyamana - 1 month ago 13
Android Question

ACCESS_FINE_LOCATION SecurityException despite specifying the permission in the manifest file

My app is attempting to access the device's location and I have included the following in the

AndroidManifest.xml
:

<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<application>
<meta-data android:name="com.google.android.gms.version" />
</application>

</manifest>


I have implemented the
GoogleApiClient.ConnectionCallbacks
as follows to access the location service:

public class BackgroundLocationService implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {

private static final String TAG = BackgroundLocationService.class.getSimpleName();

private static GoogleApiClient googleApiClient;
private static PendingIntent locationCallback;

public static int LOCATION_INTERVAL = 10000;
public static int FAST_INTERVAL = 5000;

@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to Google API");

LocationRequest request = new LocationRequest();
request.setInterval(LOCATION_INTERVAL);
request.setFastestInterval(FAST_INTERVAL);
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, request, locationCallback);
}

@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, Integer.toString(i));
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, connectionResult.toString());
}
}


When I trigger the location service call, the following exception is thrown:

java.lang.SecurityException: Client must have ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations.
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at com.google.android.gms.location.internal.zzi$zza$zza.zza(Unknown Source)
at com.google.android.gms.location.internal.zzk.zza(Unknown Source)
at com.google.android.gms.location.internal.zzl.zza(Unknown Source)
at com.google.android.gms.location.internal.zzd$7.zza(Unknown Source)
at com.google.android.gms.location.internal.zzd$7.zza(Unknown Source)
at com.google.android.gms.internal.zzlb$zza.zzb(Unknown Source)
at com.google.android.gms.internal.zzlf.zza(Unknown Source)
at com.google.android.gms.internal.zzlf.zzb(Unknown Source)
at com.google.android.gms.internal.zzli.zzb(Unknown Source)
at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
at com.localz.spotzpush.sdk.service.BackgroundLocationService.onConnected(BackgroundLocationService.java:45)
at com.google.android.gms.common.internal.zzk.zzh(Unknown Source)
at com.google.android.gms.internal.zzlg.zznU(Unknown Source)
at com.google.android.gms.internal.zzlg.onConnected(Unknown Source)
at com.google.android.gms.internal.zzli$2.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzj$zzg.zzpf(Unknown Source)
at com.google.android.gms.common.internal.zzj$zza.zzc(Unknown Source)
at com.google.android.gms.common.internal.zzj$zza.zzt(Unknown Source)
at com.google.android.gms.common.internal.zzj$zzc.zzph(Unknown Source)
at com.google.android.gms.common.internal.zzj$zzb.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)


I am using an actual device to produce this issue and have been scratching my head on why the exception is thrown.

Answer

The issue was caused by a new feature for Android 6.0.

Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.

http://developer.android.com/training/permissions/requesting.html

To get around the issue when the permission is not explicitly granted, I had put in a check to wrap location service calls (as per the Google Documentation, slightly modified).

int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);

if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
    //Execute location service call if user has explicitly granted ACCESS_FINE_LOCATION..
}

The Google Documentation also steps through how to request for the permissions that are needed.

Comments