I have an Android app that requires permission to read/write from/to external storage. When the app starts, it prompts the user to allow permission for external storage (and a bunch of other services - location, camera, etc).
Here's how we do it:
ActivityCompat.requestPermissions(this, new String[]{WRITE_EXTERNAL_STORAGE, CAMERA,ACCESS_FINE_LOCATION,INTERNET,WRITE_SETTINGS,ACCESS_WIFI_STATE,READ_PHONE_STATE}, PERMISSION_REQUEST_CODE)
Now, there is also an authentication service for which we need to read from external storage. We call this authentication service during startup.
Now, problem is: When you run the app for the 1st time after install, this call to authentication service may happen often before the permission to external storage is given. Because the authentication service has no permission to external storage, it fails authentication.
Workaround we do now: manually enable permission after install and then run the app. Not a long term solution though.
I did some reading and it seems in older API's we can force the permissions to be done during apk install itself. I am on API 29. Is it possible here to prompt the user to give permissions during install itself?
I also understand that this is considered a critical service and we can't bypass permissions. Rather we cannot force permissions to be default.
What I've done for now:
Initialized the authentication service later in the code so it runs only after permissions are done.
Is there a better solution available? Like some way to either force permissions for external storage by default or some other way? From what I have read, it doesnt look possible for the latest Android version. However, if there is a way to do this, pls let me know.
Thanks,
Anand
In order to know if the user has allowed or not the application with your requested permissions, you should override onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray).
This way, you can do something like this :
if (requestCode == PERMISSION_REQUEST_CODE) {
for (elem in grantResults) {
if (elem != PackageManager.PERMISSION_GRANTED)
// Abort your feature here
}
// Do your feature here
}
If every permission has been passed you can then do what you want.
The Android Developer Documentation has a nice tutorial, more complete than I've done above, but you get the idea.
Not possible to force permission at installation time, you would need to target API level < 23 but now you need to use 28/29 to create/update apps on PlayStore. You could consider to use an alternative storage location like getCacheDir() moving files where you need later when your app has permission or just getExternalFilesDir() path where you can read/write without additional permissions.
Is it possible here to prompt the user to give permissions during install itself?
From official doc:
If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the user isn't notified of any app permissions at install time.
Also:
If the device is running Android 5.1.1 (API level 22) or lower, or the app's targetSdkVersion is 22 or lower while running on any version of Android, the system automatically asks the user to grant all dangerous permissions for your app at install-time (see figure 2).
In any case pay attention to this point:
Beginning with Android 6.0 (API level 23), users can revoke permissions from any app at any time, even if the app targets a lower API level.
In other word it means that today you have to check for and request permissions in your code.
Initialized the authentication service later in the code so it runs only after permissions are done.
You can use the ContextCompat.checkSelfPermission also in a Service.
When you start the service you can check if the permission is granted and avoid to fail.
You can use ActivityCompat.requestPermissions only in an Activity, but you can use the callback onRequestPermissionsResult to start your service.
Is there a better solution available?
You can't force the permission but for example your Service can check for permissions it needs and if it hasn't been granted yet, you can create a friendly notification to inform user.
Critical permissions like read/write external storage, camera, SMS, contacts, and a few others cannot be forcefully asked for prior to installation. So, they've to be asked for at runtime. The best practice is to ask for them just when they're actually needed instead of asking for them all at a time in the beginning.
If your service uses one of those permissions, you've to check for that permission every time before starting the service and then start the service only if the permission is granted. Otherwise, ask for permission, override onActivityResult and then start service only if the permission is granted.
Also, keep in mind to handle the scenario when the user marks the checkbox "Don't ask again" and denies permission. In that case, the user won't see the prompt again. So, you'll have to open permission settings using intent.
I'm trying to open recent apps but I have a permission problem.
This feature works on Android 4, but seemingly from 6/7 is displaying the following error:
java.lang.SecurityException: Permission Denial: starting Intent { flg=0x800000 cmp=com.android.systemui/.recents.RecentsActivity }
val intent = Intent()
intent.component = ComponentName("com.android.systemui", "com.android.systemui.recents.RecentsActivity")
if (null != intent.resolveActivityInfo(context.packageManager, 0)) {
startActivity(intent)
}
Looks like its because new permissions system in android 6
Every Android app runs in a limited-access sandbox. If an app needs to
use resources or information outside of its own sandbox, the app has
to request the appropriate permission. You declare that your app needs
a permission by listing the permission in the app manifest and then
requesting that the user approve each permission at runtime (on
Android 6.0 and higher).
If your app needs a dangerous permission, you must check whether you
have that permission every time you perform an operation that requires
that permission. Beginning with Android 6.0 (API level 23), users can
revoke permissions from any app at any time, even if the app targets a
lower API level. So even if the app used the camera yesterday, it
can't assume it still has that permission today
check the documentation for more informations
I'm trying to write to a value on AT. I've already declared required permission as follow in manifest,
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
And try to request permission at run-time, AT shows windows regarding permission setup. However the switch is not clickable. Regarding AT document
Requesting Permissions at Runtime is not supported because embedded
devices aren't guaranteed to have a UI to accept the runtime dialog.
Declare permissions that you need in your app's manifest file. All
normal and dangerous permissions declared in your app's manifest are
granted at install time.
However Settings.System.canWrite() always returns false.
Are there any special methods to enable permission WRITE_SETTINGS?
Like you said, the documents say:
Declare permissions that you need in your app's manifest file. All normal and dangerous permissions declared in your app's manifest are granted at install time.
Therefore you don't see the normal Android permissions UI.
From the release notes:
Dangerous permissions requested by apps are not granted until the next device reboot. This includes new app installs and new elements in existing apps.
So try powering off and on your Android Things device
After install application with the statement on AndroidManifest.xml as follow
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
It needs to be also run Settings as follow via adb
adb shell am start -S com.android.settings/.Settings
Then click APPS>YOUR_APP, then click permission.
Now the switch is clickable. So AT not granted to permission. It needs to be granted manually.
This permission is having Protection level: signature.Which means this permission is only granted to system apps.
Please find the below screenshot for your reference :
From app I gave the required permission for my app. While my app is running, I went to system settings page and revoked the permission. The app is crashing. Will we be able to handle this?.
Android 6.0 (Marshmallow, API 23) switched from an install-time permission model to a runtime permission model. Now instead of the user granting all permissions at runtime, you the developer are responsible for requesting permissions at runtime and responding appropriately.
You should begin by reading the Requesting Permissions at Run Time documentation. So that you can properly request permissions on devices running Marshmallow.
To prevent your app from crashing, you need to call ContextCompat.checkSelfPermission() to see if you have a permission before attempting to call a method that requires a permission. However, this is only half the equation since you still need to request the permission if you don't already have it.
My application is targeted to Android Marshmallow (API level 23) and implemented Run-time Permissions by following the developer guide in the below link.
https://developer.android.com/training/permissions/requesting.html.
This requesting Permission model is working fine.
When there is a permission request popup on the screen, If user revoke the permissions which are already granted by accessing Settings -> Apps -> My Application name -> permission and switch to my application, Application is getting restarted.
But that permission Request dialog which is already opened still persist.
So, Please suggest some solution to close that permission request dialog which is already there in the screen, when it is getting restarted.