Facebook, Evernote, Pocket - all apps get this permission on Android 6.0 automatically, even though they are targeting 23 (targetSdkVersion=23).
There has been a lot of documentation regarding the new Marshmallow permission model. One of them is SYSTEM_ALERT_WINDOW been 'promoted' to 'above dangerous' permission class thus requiring a special user intervention in order for apps to be granted with those. If the app has targetSdkVersion 22 or lower, app gets this permission automatically (if requested in the manifest).
However, I've noticed some apps that get this permission, without needing to send the user to the setting special page of Draw over other apps permission. I saw Facebook, Evernote, Pocket - and perhaps there are more.
Anyone knows how an app can be granted this permission without the user go through Settings -> Apps -> Draw over other apps?
Thanks
It is a new behaviour introduced in Marshmallow 6.0.1.
Every app that requests the SYSTEM_ALERT_WINDOW permission and that is installed through the Play Store (version 6.0.5 or higher is required), will have granted the permission automatically.
If instead the app is sideloaded, the permission is not automatically granted. You can try to download and install the Evernote APK from apkmirror.com. As you can see you need to manually grant the permission in Settings -> Apps -> Draw over other apps.
These are the commits [1] [2] that allow the Play Store to give the automatic grant of the SYSTEM_ALERT_WINDOW permission.
Yeh After Marshmallow come Android make security level more stick, But For SYSTEM_ALERT_WINDOW you can show floating action and anything You can Force user to give permission for it By Following Codes in your onCreate() method.
Put this code after setContentView:
// Check if Android M or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(myIntent);
}
The action ACTION_MANAGE_OVERLAY_PERMISSION directly launches the 'Draw over other apps' permission screen.
Edit:
My Above Code works 100% Correct
But I just found that many guys are still searching that how can allow ACTION_MANAGE_OVERLAY_PERMISSION permanently like If user has allow Permission Once then don't ask it every time he open application so here is a solution for you:
Check if device has API 23+
if 23+ API then check if user has permit or not
if had permit once don't drive him to Settings.ACTION_MANAGE_OVERLAY_PERMISSION and if has not permit yet then ask for runtime permission check
Put below line in your onCreate() method. Put this after setContentView:
checkPermission();
Now put below code in onActivityResult:
#TargetApi(Build.VERSION_CODES.M)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (!Settings.canDrawOverlays(this)) {
// You don't have permission
checkPermission();
} else {
// Do as per your logic
}
}
}
Now finally the checkPermission method code:
public void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
}
And don't forget to declare this public variable in your class:
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;
Now(2019) that Google offers an alternative API to SYSTEM_ALERT_WINDOW in the form of Bubbles in Android Q, Google has decided to eventually deprecate SYSTEM_ALERT_WINDOW in a future Android release.
And Android Go devices will no longer grant this permission
i.e Settings.canDrawOverlays() == false
For those who want to get this permission automatically when the app is downloaded from the Play Store, besides the SYSTEM_ALERT_WINDOW in the Manifest, you should go to this link and request this from Google.
You have to provide some additional information why you need this permission and Google will review and give you the automatically permission.
Bear in mind that before you ask for this, you have to:
Have the SYSTEM_ALERT_WINDOW permission in the Manifest
Prompt the user to grant the SYSTEM_ALERT_WINDOW permission within your app, when not already granted
If I miss something feel free to update the answer
If the app targets API 22 or lower, then Play Store will give the SYSTEM_ALERT_WINDOW permission and others when the user clicks to install (showing an alert) even if its device is Android 6.0
Otherwise, if the app targets API 23 or above, so that permission will be request to grant in run time.
Related
Sorry, this question has probably been asked multiple times already, but I am struggling with different SDK versions. My app is used as a research instrument and solely installed per .apk directly on tablets, thus no app store. I need to record the answers from users and write them into a text file. And I am having a hard time requesting the permission from users to store the data on the external storage.
I added the following line to AndroidManifest.xml:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
In the MainActivity, I call askForPermissions in the onCreate function:
public void askForPermissions() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result != PackageManager.PERMISSION_GRANTED){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) {
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}else{
//TODO no clue, what to do here
}
}else{
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(this, "Permission needed to store the data. Please allow storage functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},2);
}
}
}
createDir();
}
In API version 30, I use the "Intend" and accordingly the settings screen with the permissions shows up and I can grant writing permissions manually - and this works (directory is generated, data stored ...). First questions: In which cases can it happen that there is no external storage manager (hence the TODO)?
What I am struggling with is SDK < 30. This does not seem to work. I do not get permissions and in the app info, I cannot give the app writing permissions manually. The permissions option is disabled. What is the correct way to request permissions in that case (most preferably directly in the app)?
Sorry for the possible double post. Newbie here.
Try this in manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I want to write a simple app which accesses the device's location. Only I will ever use the app. This is my first attempt in about 10 years to write an Android app, so it is the first time I've had to deal with runtime permissions.
My first question is, given that the app is solely for my use, is it possible to by-pass the need for runtime permission code?
Failing that, is there any simple example code that fills in the numerous gaps in the Android documentation?
To take one example: the doc includes the following:
when {
ContextCompat.checkSelfPermission(
CONTEXT,
Manifest.permission.REQUESTED_PERMISSION
) == PackageManager.PERMISSION_GRANTED -> {
// You can use the API that requires the permission.
performAction(...)
What does this mean? What "API that requires the permission"? What replaces the "..."?
There are several other similar gaps on the page.
You have mentioned that app is solely for your use then you don't have to write the code for the runtime permission you can skip it...
How to do this... ?
Step 1 : Just put all the permission you need inside the app manifest file and install the app
Step 2 : Go to the app settings or app info in the phone and check for app permissions all the permission that you mentioned will be displayed there just toogle them manually
That's it now write code to access the things which you supposed to write after getting permission
If you want to avoid run time permission request you can build your app with Android SDK version below 23 (Android 6 Marshmellow)
For Android API Level 23 or above (after adding permission in your manifest file):
First, add your permission to AndroidManifest.xml file:
<uses-permission android:name="android.permission.THE_PERMISSION" />
Then in your Activity:
Check Permission:
fun checkPermission(permission: String): Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
Get Permission:
fun getPermission(permission: String) {
ActivityCompat.requestPermissions(this, arrayOf(permission), REQ_CODE_PERMISSION)
}
Get Permission Result:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == REQ_CODE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
...
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
If you are using Fragments:
A fragment contains a method for requesting permission and getting the result back to its onRequestPermissionsResult:
fun getPermission(permission: String) {
requestPermissions(arrayOf(permission), REQ_CODE_PERMISSION)
}
REQ_CODE_PERMISSION: is some random number like 123 you use to identify your request with.
is it possible to by-pass the need for runtime permission code?
You still need the <uses-permission> element. But you could manually grant the permission to your app via the Settings app.
The point of runtime permission code is to request the permission from the user and defend against cases where that permission has not been granted. In your case, if your app crashes because you revoked the permission, you can yell the developer. You, as the developer, in turn, can yell at you, as the user, for failing to manually grant the permission. Since you will be yelling at yourself, it is recommended to do this in a private location, or perhaps have a Bluetooth headset in your ear as cover. :-)
What does this mean?
We request runtime permissions because we want to use some Android API that is defended by such a permission. We usually do not request runtime permissions because we woke up one morning and decided that requesting runtime permissions sounds like a really fun thing to do.
What "API that requires the permission"? What replaces the "..."?
In your case, it would appear to be either methods on LocationManager or stuff using the fused location API from Google Play Services.
is there any simple example code that fills in the numerous gaps in the Android documentation?
The problem is that "example code" is 5% permission-related and 95% whatever it is that you are using that requires the permission. Any sample code that only shows permissions is going to have the same hand-wavy stuff that you don't like from the documentation. In your case, any up-to-date examples of using location APIs should also show the runtime permission elements.
FWIW, this directory contains several sample projects from this book that show getting the location. They are a bit old but do show requesting runtime permissions (mostly contained in an AbstractPermissionActivity). This sample is newer and in Kotlin, but it is for file-access permissions, not for locations (and is covered in this other book).
Facebook, Evernote, Pocket - all apps get this permission on Android 6.0 automatically, even though they are targeting 23 (targetSdkVersion=23).
There has been a lot of documentation regarding the new Marshmallow permission model. One of them is SYSTEM_ALERT_WINDOW been 'promoted' to 'above dangerous' permission class thus requiring a special user intervention in order for apps to be granted with those. If the app has targetSdkVersion 22 or lower, app gets this permission automatically (if requested in the manifest).
However, I've noticed some apps that get this permission, without needing to send the user to the setting special page of Draw over other apps permission. I saw Facebook, Evernote, Pocket - and perhaps there are more.
Anyone knows how an app can be granted this permission without the user go through Settings -> Apps -> Draw over other apps?
Thanks
It is a new behaviour introduced in Marshmallow 6.0.1.
Every app that requests the SYSTEM_ALERT_WINDOW permission and that is installed through the Play Store (version 6.0.5 or higher is required), will have granted the permission automatically.
If instead the app is sideloaded, the permission is not automatically granted. You can try to download and install the Evernote APK from apkmirror.com. As you can see you need to manually grant the permission in Settings -> Apps -> Draw over other apps.
These are the commits [1] [2] that allow the Play Store to give the automatic grant of the SYSTEM_ALERT_WINDOW permission.
Yeh After Marshmallow come Android make security level more stick, But For SYSTEM_ALERT_WINDOW you can show floating action and anything You can Force user to give permission for it By Following Codes in your onCreate() method.
Put this code after setContentView:
// Check if Android M or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(myIntent);
}
The action ACTION_MANAGE_OVERLAY_PERMISSION directly launches the 'Draw over other apps' permission screen.
Edit:
My Above Code works 100% Correct
But I just found that many guys are still searching that how can allow ACTION_MANAGE_OVERLAY_PERMISSION permanently like If user has allow Permission Once then don't ask it every time he open application so here is a solution for you:
Check if device has API 23+
if 23+ API then check if user has permit or not
if had permit once don't drive him to Settings.ACTION_MANAGE_OVERLAY_PERMISSION and if has not permit yet then ask for runtime permission check
Put below line in your onCreate() method. Put this after setContentView:
checkPermission();
Now put below code in onActivityResult:
#TargetApi(Build.VERSION_CODES.M)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (!Settings.canDrawOverlays(this)) {
// You don't have permission
checkPermission();
} else {
// Do as per your logic
}
}
}
Now finally the checkPermission method code:
public void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
}
And don't forget to declare this public variable in your class:
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;
Now(2019) that Google offers an alternative API to SYSTEM_ALERT_WINDOW in the form of Bubbles in Android Q, Google has decided to eventually deprecate SYSTEM_ALERT_WINDOW in a future Android release.
And Android Go devices will no longer grant this permission
i.e Settings.canDrawOverlays() == false
For those who want to get this permission automatically when the app is downloaded from the Play Store, besides the SYSTEM_ALERT_WINDOW in the Manifest, you should go to this link and request this from Google.
You have to provide some additional information why you need this permission and Google will review and give you the automatically permission.
Bear in mind that before you ask for this, you have to:
Have the SYSTEM_ALERT_WINDOW permission in the Manifest
Prompt the user to grant the SYSTEM_ALERT_WINDOW permission within your app, when not already granted
If I miss something feel free to update the answer
If the app targets API 22 or lower, then Play Store will give the SYSTEM_ALERT_WINDOW permission and others when the user clicks to install (showing an alert) even if its device is Android 6.0
Otherwise, if the app targets API 23 or above, so that permission will be request to grant in run time.
I am trying to implement the Google's Fingerprint API in my app (in my Fragment specifically). Google has given an example but it's implemented inside an Activity here.
My specific question is that the code below to check if there are enrolled fingerprints already, it is giving me an error (screenshot below):
Question --> What change do I need to do to make it work in my Fragment (as opposed to an activity like Google has)?
if (!mFingerprintManager.hasEnrolledFingerprints()) {
purchaseButton.setEnabled(false);
// This happens when no fingerprints are registered.
Toast.makeText(getActivity(),
"Go to 'Settings -> Security -> Fingerprint' and register at least one fingerprint",
Toast.LENGTH_LONG).show();
return;
}
Android 6.0 must 'ask' for permission at run time. https://developer.android.com/training/permissions/requesting.html
Dangerous permissions can give the app access to the user's
confidential data. If your app lists a normal permission in its
manifest, the system grants the permission automatically. If you list
a dangerous permission, the user has to explicitly give approval to
your app.
Even if you have <uses-permission android:name="android.permission.USE_FINGERPRINT"/> in your manifest, My understanding is that you must ask for the permission. So it looks like the error is because your app doesn't have -run time- permission to use the fingerprint manager.
(only like 90% sure of this, since I'm sticking with 5.0 for now, sorry)
Update: http://developer.android.com/reference/android/Manifest.permission.html#USE_FINGERPRINT
public static final String USE_FINGERPRINT ---------- Added in API level 23
Allows an app to use fingerprint hardware.
Protection level: normal
So it appears you shouldn't need this permission at run time.
1) Do you have the permission in your manifest?
2) You should put the following code in yours to check to see if permission is revoked/not given for some reason.
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.USE_FINGERPRINT) // this might need massaged to 'android.permission.USE_FINGERPRINT'
!= PackageManager.PERMISSION_GRANTED) {
Log.d ("TEST", "You don't have permission");
}
(or something close to this) like the example from https://developer.android.com/training/permissions/requesting.html
I'm using this to get permission:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(context, Manifest.permission.GET_ACCOUNTS)) {
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.GET_ACCOUNTS}, PERMISSIONS_REQUEST_GET_ACCOUNTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
But the pop up dialog for permission asks user for access Contacts!?!?
In pre 6.0 in Play Store with
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
request is named Identity and explains I need it to get device account.
That is because of Permission Groups. Basically, permissions are placed under different groups and all permissions from that group would be granted if one of them is granted.
Eg. Under "Contacts" , there is write/read contacts and get accounts, so when you ask for any of those, the popup asks for Contacts permissions.
Read through: Everything every Android Developer must know about new Android's Runtime Permission
EDIT 1
Just thought i'l add the related(not to get accounts but permissions and groups) Oreo update info:
source: https://developer.android.com/about/versions/oreo/android-8.0-changes.html#rmp
Prior to Android 8.0 (API level 26), if an app requested a permission
at runtime and the permission was granted, the system also incorrectly
granted the app the rest of the permissions that belonged to the same
permission group, and that were registered in the manifest.
For apps targeting Android 8.0, this behavior has been corrected. The
app is granted only the permissions it has explicitly requested.
However, once the user grants a permission to the app, all subsequent
requests for permissions in that permission group are automatically
granted.
GET_ACCOUNTS was moved into the CONTACTS permission group in Android 6.0. While the API has us provide permissions, the user (for Android 6.0 at least) is prompted for permission groups. Hence, the user will be given the same prompt for GET_ACCOUNTS as the user would get for READ_CONTACTS or WRITE_CONTACTS.
Fortunately this will change in Android N
http://developer.android.com/preview/behavior-changes.html#perm
The GET_ACCOUNTS permission is now deprecated. The system ignores this
permission for apps that target Android N.
In Marshmallow all dangerous permissions belong to permission groups.
The permission android.permission.GET_ACCOUNTS belongs to CONTACTS group
You can find more information about dangerous permission and their groups here:
https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
I got your question wrong first. On this page http://developer.android.com/guide/topics/security/permissions.html#perm-groups, your can see that GET_ACCOUNTS refers to the permission group contacts. Because of that your are prompted for contact permission.
If your using the GET_ACCOUNTS permission to ask the user to select a particular account type on the device(Google in my case), you can use the AccountPicker class which doesn't require any special permissions
Intent intent = AccountPicker.newChooseAccountIntent(null, null,
new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE},
false, null, null, null, null);
try {
startActivityForResult(intent, REQUEST_ACCOUNT_PICKER);
} catch (ActivityNotFoundException e) {
// This device may not have Google Play Services installed.
}
You'll need Google Play services auth in your gradle dependencies
implementation com.google.android.gms:play-services-auth:16.0.1
This avoids the Contacts permission popup for me