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:
Raise a
Notification
, to let the user know that the service cannot do its work without this permission.Have the
Notification
trigger anActivity
that can callrequestPermissions()
. Optionally, this activity can haveTheme.Translucent.NoTitleBar
, so the only visible UI is the permission dialog.If
onRequestPermissionResult()
indicates that you have the permission, the activity can tell the service to go ahead (e.g., via a call tostartService()
), thenfinish()
itself. IfonRequestPermissionResult()
indicates that the user denied the permission, do whatever makes sense (e.g., show theNotification
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
Jelly Bean Datepickerdialog --- How to Cancel
Hide/Show Bottomnavigationview on Scroll
Android - Open Resource from @Drawable String
What Is "Android.R.Layout.Simple_List_Item_1"
Android Webview Not Loading an Https Url
How to Disable the Clear Data Button in Application Info of Manage Application
Android Create Folders in Internal Memory
Display the Current Time and Date in an Android Application
How to Tell If Android App Is Running in the Foreground
How to Get Access to Raw Resources That I Put in Res Folder
Android Set Up Volley to Use from Cache
Android Emulator Not Able to Access the Internet
How to Programmatically Turn Off Wifi on Android Device
Selecting Multiple Items in Listview
How to Set the Edittext Keyboard to Only Consist of Numbers on Android
Java.Lang.Illegalargumentexception: View Not Attached to Window Manager