I have the app that uses
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
It's automatically granted on Android 6.0, but I can revoke it in the settings.
Wanted to check if it's granted in case user revokes it, so I do this:
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
//OK permission granted, let's do stuff
} else {
//I'll better ask for permission
}
Funny thing is that the condition is ALWAYS fulfilled, even the permission was revoked manually. And the the app fails... It looks like a bug to me, is it or am I missing something?
You are missing something: a targetSdkVersion of 23 or higher.
If your targetSdkVersion is 22 or lower, you have no ability to determine whether a permission was granted or revoked by the user from Settings.
Related
I'd like to grant android.permission.READ_PRIVILEGED_PHONE_STATE permission to my app, but even though it's a system app (in system-priv folder on a rooted device for tests) it's not granted.
ADB shows request for this permission, but it's not granted.
In the Manifest I have
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" tools:ignore="ProtectedPermissions" />
When I try to check it in the runtime
if (ActivityCompat.checkSelfPermission(context.getApplicationContext(), Manifest.permission.READ_PRIVILEGED_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)
the AS gives "Cannot resolve symbol 'READ_PRIVILEGED_PHONE_STATE'" and the app won't compile.
Why READ_PRIVILEGED_PHONE_STATE is visible in the Manifest, but not visible in the java code (also missing in Manifest.class) ?
How can I grant this permission?
I tested it on rooted Android Oreo.
Edit: This answers a part of my question: Permission is not a changeable permission type
The permission was granted on Lollipop, but not on Oreo.
But the question remains: Why READ_PRIVILEGED_PHONE_STATE is visible in the Manifest, but not visible in the java code (also missing in Manifest.class) ?
What I think might be happening is that Drobinsky did not call:
String[] permissions = {"android.permission.READ_PHONE_STATE"};
int requestCode = 5;
ActivityCompat.requestPermissions(this,permissions, requestCode);
prior to calling "ActivityCompat.checkSelfPermission(…"
In the activity you can also add a permissions notififcation handler which looks like this:
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 5: //REQUEST_READ_PHONE_STATE:
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// Do what you want to do with the granted permission
Even though you've got the permission added in the manifest, the user must also grant this permission at runtime. What happens is that a popup will occur asking the user to grant this permission, and if the user grants it, the "checkSelfPermission" method will then work correctly. The popup block is automatic; i.e. no code needs to be added to the app. I think you can add a text message that displays the reason the permission is required. Certain permission requests need to be handled in this manner, whereas some permission requests are granted without user intervention required. I think the Android model is that if a request is deemed "dangerous" it requires the user give their permission to grant the app access to these so called dangerous privileges.
In my android application (minSdkVersion 15), i have to create directory and write files into it. In my AppManifest i am using :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Before creating directory or file, i am checking if permission is allowed or deny, as
boolean isAllow = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
But it is always returning true or PERMISSION_GRANTED, even when someone set deny permission from Settings -> Apps -> Permissions
Why checkSelfPermission is always returning PERMISSION_GRANTED ? Is there any way to check if permission is denied ?
To invoke permission i have used :
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
But its not showing permission Dialogue??
In the new permission model permissions with protection level dangerous are runtime permissions. For apps targeting M and above the user may not grant such permissions or revoke them at any time. For apps targeting API lower than Marshmallow(<23) these permissions are always granted as such apps do not expect permission revocations and would crash. Therefore, when the user disables a permission for a legacy app in the UI the platform disables the APIs guarded by this permission making them a no-op which is doing nothing or returning an empty result or default error.
for more information visit PermissionChecker
For those who develop with Xamarin make sure that you explicitly set the targetSDK version >= 23 in your manifest.
Don't use automatic for your targetSDK!!!
if your targetSdkVersion is minimum 23 then your problem can be solved by code as below:
int permissionCheck = PermissionChecker.checkSelfPermission(getReactApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
Android Things only support limited number of API such Cast, Drive, and Location APIs. I'm trying to work with one API and I want to map between the API methods and its required permission. I'm not sure what is the best approach to do such a task. I'm working with Intel Edison board. Basically, I need to do something like this:
====== Method ============= Required Android Permission =============
=====getLocation()====>===== android.permission.ACCESS_FINE_LOCATION
=====getBeaconState()===>===== android.permission.ACCESS_FINE_LOCATION
Also, I need to see what happens if the permission required is missing? I'm just looking for thoughts on how to do these tasks.
I'm not sure what you are trying to achieve, if it is documentation or something in code, but fwiw AndroidThings act's differently for permissions, so you don't have to do anything in your codebase.
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.
This is from the Android Things docs https://developer.android.com/things/sdk/index.html
As you can see it says
All normal and dangerous permissions declared in your app's manifest are granted at install time.
Therefore if you use maps that requires ACCESS_FINE_LOCATION you will be granted the permission at install time and will not need to code anything for "runtime permissions" as they do not exist.
Try this for location runtime permission
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
//Do your work if permission already granted
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
and override onRequestPermissionResult
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Do your Work
}
}
}
Declare this in AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Install the apk on device, and then reboot the device, it fixed my issue.
Use ActivityCompat.checkSelfPermission for check permission.
Use ActivityCompat.requestPermissions for request permission.
Use interface ActivityCompat.OnRequestPermissionsResultCallback for callback.
I stucked on new permission model in the Android 6.
I defined following permissions in the manifest:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application...
But if i launched the app in the emulator and opened the app detail i saw the following :
It says that app does not require any permission.
How can i solve it please?
Many thanks for any advice.
It says that app does not require any permission.
That is correct. That portion of your app's page lists dangerous permissions. None of yours have a protectionLevel of dangerous.
How can i solve it please?
There is nothing wrong, and so there is nothing to solve.
Until Android 6.0, There are some permissions that will be automatically granted at install time and will not be able to revoke. We call it Normal Permission (PROTECTION_NORMAL). Here is the full list of them:
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_NOTIFICATION_POLICY
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.CHANGE_WIMAX_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.REQUEST_INSTALL_PACKAGES
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.USE_FINGERPRINT
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SYNC_SETTINGS
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT
com.android.launcher.permission.UNINSTALL_SHORTCUT
Just simply declare those permissions in AndroidManifest.xml and it will work just fine. No need to check for the permission listed above since it couldn't be revoked.
as #Saini said, Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
But if you choose targetSdkVersion lower than 23, your application will be treated like before and will ask user to grant permission to the app when they want to install application. you could read more from here
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality; for example, a user could choose to give a camera app access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the app's Settings screen.
For more info: https://developer.android.com/training/permissions/requesting.html
https://developer.android.com/training/permissions/declaring.html
https://developer.android.com/training/permissions/best-practices.html
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// 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(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
In addition to https://stackoverflow.com/a/42697645/984471
Here is the protection_normal permissions link:
https://developer.android.com/guide/topics/permissions/overview#normal_permissions
And the comparison between old and new, normals
I am trying to use GPS in android but it gives me this error:
I put in manifest these permission
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
can anyone help me please
As the hint suggests : The user may deny permission. In that case this call will throw error...
Right now, android asks for the user to accept all the permissions an app asks for in the manifest on installation. In the upcoming M release, android will switch over to the iOS style of permissions with an "on needed" basis.
Call this method to see if permission is granted or not. If not, you need to handle that situation.
context.checkCallingPermission(permission)
Declaring permission in manifest only means that you are requesting permission. In new releases it will not guarantee that user will give you that permission.
In older releases the user has to accept all or reject all permissions
This is not an error actually but a heads-up by the Lint and which may cause an issue!
Hope you are aware about the new permission model is introduced in Android 6.0 (Marshmallow), through which user may not permit to use GPS or Network or anything else and so it may cause an issue in your application!
Now, as per the lint analysis, so before implementing particular functionality, you should check whether permission for the same is available or not!
Since SDK 23, you should/need to check the permission using checkSelfPermission
http://developer.android.com/reference/android/support/v4/content/ContextCompat.html
for example
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
This condition checks user allowed to access the permission to read the location
if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED||checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,meter,mill,new locationlist(this));
}