How to Request Permissions from a Service in Android Marshmallow

How to ask permissions from a Service


How can I activate permissions in a Service?

You don't. You activate (i.e., request) permissions from an activity. That is not negotiable.

Ideally, you request permissions before the activity starts the service or does something that will eventually cause the service to start (e.g., schedules the job with JobScheduler).

If you determine that your service no longer has the necessary permissions — perhaps the user revoked them from Settings — you could raise a Notification that leads the user to an activity where you re-request the permissions.

It is technically possible for a service to start an activity which requests the permissions. Usually, this is not a good idea, as you may not know what the user is doing at that moment, and the user may be unhappy to have you interrupt them with this permission request.

Can a service request for permission in Android M?


I have an app that has no UI screen.

Then it will never run, unless it is preinstalled on an Android device or custom ROM, or it is a plugin to some other app. Otherwise, your app will remain in the stopped state forever. Pretty much every app distributed through normal channels, including the Play Store, needs an activity.

Does this mean that I have to put a spinner screen if checkSelfPermissions returns denied?

I do not know what "a spinner screen" is. AFAIK, the recommended pattern for a service needing a runtime permission that it does not have is to:

  1. Raise a Notification, to let the user know that the service cannot do its work without this permission.

  2. Have the Notification trigger an Activity that can call requestPermissions(). Optionally, this activity can have Theme.Translucent.NoTitleBar, so the only visible UI is the permission dialog.

  3. If onRequestPermissionResult() indicates that you have the permission, the activity can tell the service to go ahead (e.g., via a call to startService()), then finish() itself. If onRequestPermissionResult() indicates that the user denied the permission, do whatever makes sense (e.g., show the Notification again, gracefully shut down, suggest to the user that the user uninstall the app).

Android marshmallow request permission?

Open a Dialog using the code below:

 ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);

Get the Activity result as below:

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {

// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}

// other 'case' lines to check for other
// permissions this app might request
}
}

More info: https://developer.android.com/training/permissions/requesting.html

Android Marshmallow: How to allow Runtime Permissions programatically?

For Marshmallow or later permissions are not granted at install time and must be requested when required at runtime (if not granted previously.)

To do this, you need to run ActivityCompat.requestPermissions() to pop up the systems permissions dialog in your Activity, at the time when the user is undertaking an action that requires additional system permissions.

An example of this for the WRITE_EXTERNAL_STORAGE permission would be:

ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_EXTERNAL_STORAGE_REQUEST_CODE
);

Note: WRITE_EXTERNAL_STORAGE_REQUEST_CODE is an arbitrary integer constant you should define elsewhere.

The permissions you request should also be declared in your AndroidManifest.xml. In this example the declaration would be:

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

In order to handle the system permissions dialog response you will also need to implement onRequestPermissionsResult() in your Activity. For this example the code would be similar to

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
if (grantResults.length == 0 || grantResults[0] == PackageManager.PERMISSION_DENIED) {
return; //permission not granted, could also optionally log an error
}
if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) {
//Do whatever you needed the write permissions for
}
}

If you are automating your app through Espresso, UIAutomator and/or some other UI testing framework you will need to anticipate and click the system dialog during your test, which can be accomplished with the following test code:

private void allowPermissionsIfNeeded()  {
if (Build.VERSION.SDK_INT >= 23) {
UiObject allowPermissions = mDevice.findObject(new UiSelector().text("Allow"));
if (allowPermissions.exists()) {
try {
allowPermissions.click();
} catch (UiObjectNotFoundException e) {
Timber.e(e, "There is no permissions dialog to interact with ");
}
}
}
}

A more comprehensive explanation of testing System UI Permissions is available here.

How to check new android 6.0 Permissions from service

Yes you can accept the permissions once in activity and use it in service , if you grant the permission , then it will never ask again. Following is the code for showing dialog for ACCESS_FINE_LOCATION ,You can also refer Requesting Permissions at Run Time

private void showPermissionDialog() {
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(mActivity,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

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

// Show an expanation 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.

} else {

// No explanation needed, we can request the permission.

ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_FOR_LOCATION);

// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
if (mGoogleApiClient != null)
mGoogleApiClient.connect();
}
}


Related Topics



Leave a reply



Submit