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).
Related
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.
Before I begin explaining my question, I have to mention that I am new to Android development.
I am trying to write a program for Android which uses OpenCV's Java API for some data processing. I am developing unit tests for classes that implement algorithms and these classes are not related to any activity yet. In other words, I just want to test the functionality of methods before dealing with activities.
Because I need to have access to OpenCV libraries, I have written my unit test under androidTest in Android Studio. The files that contain data and need to be read in the program are copied to /sdcard/DIR and /storage/emulated/0/DIR. I have added the following permission to AndroidManifest.xml to grant access to external storage.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
However, when I try to read files from external storage I get
open failed: EACCES (Permission denied). Note that I concatenate the path returned by Environment.getExternalStorageDirectory().getAbsolutePath() with the name of data files and use a FileInputStream later on to read contents of the files.
I have seen similar questions and answers that mention access should be granted at runtime for APIs above 23. But because I don't have any activities for my methods, I guess I can't request permission at runtime.
Are there any other directories I can use to place my data files that do not require these permissions? I thought of assets as an option, but I am assuming that assets are put in the final apk and if I need to change files for a different data, I have to create a new apk every time.
How should I grant access to /sdcard without having any activity that asks user for a permission at runtime?
Can I do local testing instead of androidTest by installing OpenCV libraries on my linux machine?
Sorry but android doesn't provide that type of access
you will need to create a activity to launch the application
I think if you are using marshmallow device then you will be needing to ask the permission to read and write external storage at runtime
you can refer at the following liink
https://developer.android.com/training/permissions/requesting.html
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)==
PackageManager.PERMISSION_GRANTED) {
//do the things} else {
requestPermissions(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
AnyNumber);
Later catch those requests in
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == AnyNumber) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
}
}
}
I found a temporary workaround for this issue. I designed a button in MainActivity that when pressed, asks user for permission to access the directory where my files are located at. Afterwards, I could run the androidTest unit tests without facing the exception because this permission needs to be granted only once.
I am working with Android API 25 and need to make permissions requests in the app.
There are a ton of code samples on how to make a request as well as how to show the rationale. This link here shows a simple methodology as do these: Android M Request Multiple permission at a single time , Android M request permission non activity
The problem I am having is I am requesting multiple permissions at once (Location, Write storage access, and Contacts) and the ActivityCompatApi23.shouldShowRequestPermissionRationale source code only takes in a String for a single permission and not an array for multiple permissions. (source: android.support.v4.app.ActivityCompat)
So in my code, I can do this:
ActivityCompat.requestPermissions(activity, permissionsStringArray, 123);
And try to request multiple at once, but I can't then show the explanation for the ones needed if they return true from:
ActivityCompat.shouldShowRequestPermissionRationale(activity,
currentPerm.getPermissionManifestName()
Does anyone have any recommendations on how I can show a dialog that includes multiple rationales in it as opposed to one at a time?
I recommend this open source.
https://github.com/ParkSangGwon/TedPermission
You can use simply. for example
private void CheckPermission() {
new TedPermission(this)
.setPermissionListener(permissionlistener)
.setDeniedMessage(getString(R.string.str_permission1))
.setPermissions(Manifest.permission.CAMERA, android.Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.check();
}
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