38

I am using a service that on boot starts up and begins to check for location updates. Once i deny location access on permission popup now thanks to Android M my service crashes once the phone boots up.

Since i have no activity in this case the call to requestPermissions() returns a ClassCastException as my service Context cannot be cast to an activity.

My method call:

ActivityCompat.requestPermissions((Activity) mContext, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_COARSE_LOCATION);

Is there any solution so far to this OR do I have to revoke the service rights to NOT run in such a state.

stud91
  • 1,854
  • 6
  • 31
  • 56
  • 1
    In service you can use **ContextCompat.checkSelfPermission()** to check permission availability before doing some work. – Dhaval Patel Nov 23 '15 at 09:13
  • 1
    @Dhaval Patel yes the problem is in request permissions inside a service. Seems there is no way to do so yet without an activity – stud91 Nov 23 '15 at 09:19
  • 3
    may be you can fire notification, to ask user to provide permission. – Dhaval Patel Nov 23 '15 at 09:21
  • may be you can try after making your service as foreground process. – siva Dec 12 '15 at 18:14
  • Possible duplicate of [How to request permissions from a Service in Android Marshmallow](http://stackoverflow.com/questions/32292675/how-to-request-permissions-from-a-service-in-android-marshmallow) – naXa stands with Ukraine Oct 02 '16 at 22:33

2 Answers2

48

You can not request permission via a service, since a service is not tied to a UI, this kind of makes sense. Since a service context is not an activity the exception you are getting makes sense.

You can check if the permission is available in a service and request the permission in an activity (yes you need an activity).

In a service:

 public static boolean checkPermission(final Context context) {
return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
        && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
 }

and in an activity:

private void showPermissionDialog() {
    if (!LocationController.checkPermission(this)) {
        ActivityCompat.requestPermissions(
            this,
            new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
            PERMISSION_LOCATION_REQUEST_CODE);
    }
}
Joakim Engstrom
  • 6,243
  • 12
  • 48
  • 67
  • 6
    @VitaliyA The service can check for permission, but not request it, because it has no UI. – geNia Dec 11 '15 at 21:18
  • 2
    if you cannot resolve Manifest.permission.ACCESS_COARSE_LOCATION or Fine location use android prefix... like this: android.Manifest.permission.ACCESS_COARSE_LOCATION – Bartando Aug 14 '16 at 12:15
  • 1
    If required so, the service can create an overlay window with some UI (sometimes very complex) and do whatever. But this will require the Overlay permission. If the application requires 'root' almost all permissions may be granted silently. – OGP Nov 20 '16 at 11:05
11

You can check permissions without Activity by using application context, but you will need Activity when requesting permitions. To get app context just call to getApplicationContext() and to check permissions use ContextCompat.checkSelfPermission() instead.

Also there is good information how to use runtime permissions in correct way:

To check if you have a permission, call the ContextCompat.checkSelfPermission() method. For example, this snippet shows how to check if the activity has permission to write to the calendar:

// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.WRITE_CALENDAR);

If the app has the permission, the method returns PackageManager.PERMISSION_GRANTED, and the app can proceed with the operation. If the app does not have the permission, the method returns PERMISSION_DENIED, and the app has to explicitly ask the user for permission.

Edit: After you check the permissions on service, you'll need the Activity to request permission:

public static void requestPermissions (Activity activity, String[] permissions, int requestCode)
ahmed hamdy
  • 5,096
  • 1
  • 47
  • 58
Vitaliy A
  • 3,651
  • 1
  • 32
  • 34
  • The explanation at https://developer.android.com/training/permissions/requesting.html#java shows how requesting permissions causes an onRequestPermissionsResult handler to fire. This is what you need to intercept completion of the permission request. – pollaris Jan 26 '18 at 15:07