Android runtime permissions- how to implement
What is "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in this example?
It is an int
, to tie a particular requestPermissions()
call to the corresponding onRequestPermissionsResult()
callback.
Under the covers, requestPermissions()
uses startActivityForResult()
; this int
serves the same role as it does in startActivityForResult()
.
does that mean I should make a Constants.java and declare a public static int?
I would just make it a private static final int
in the activity. But, you can declare it wherever you want.
What should the value be?
I seem to recall that it needs to be below 0x8000000, but otherwise it can be whatever you want. The value that you use for each requestPermissions()
call in an activity should get a distinct int
, but the actual numbers do not matter.
If your activity has only one requestPermissions()
call, then the int
value really does not matter. But many apps will have several requestPermissions()
calls in an activity. In that case, the developer may need to know, in onRequestPermissionsResult()
, what request this is the result for.
Requesting app runtime permissions (Android)
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
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 do I implelment Android 6.0 Runtime Permissions On Existing App
The runtime permission model for Android 6.0 is mainly divided into part
1. Checking Permission
2. Requesting Permission
you can create two method for this thing in your activity, As follow
Check Permission
private boolean checkPermission(){
int result = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
Request Permission
private void requestPermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,Manifest.permission.READ_SMS)){
Toast.makeText(context,"Read Sms Allowed.",Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.READ_SMS},PERMISSION_REQUEST_CODE);
}
}
Last but not least you need to override the onRequestPermissionsResult method
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Snackbar.make(view,"Permission Granted, Now you can access SMS.",Snackbar.LENGTH_LONG).show();
} else {
Snackbar.make(view,"Permission Denied, You cannot access SMS.",Snackbar.LENGTH_LONG).show();
}
break;
}
}
as you asked do i need to run this in thread .. answer is No Just do this in main thread
Runtime Permissions Not Working on Real Device
ActivityCompat.requestPermission dont execute and subsequently
onRequestPermissionRationale never gets called but in the device
settings for the app, it is always showing as permission granted
Since your app is old app and you have already granted the necessary permissions to the app, ActivityCompat.checkSelfPermission
will return PackageManager.PERMISSION_GRANTED
and you won't see the permission request again.
If you want to see the permission request, un-install the older app and install a new one. Another way is to just disable the permissions from the settings.
Asking for permissions at run-time, Android M+
final private int REQUEST_CODE_ASK_PERMISSIONS = 123;
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
private void requestPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat
.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE_ASK_PERMISSIONS);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission Granted
Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT)
.show();
} else {
// Permission Denied
Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Android 11 Runtime Permissions
My issue was fixed by the system reset, but according to comments and documents please follow the below guidelines for the location permission.
Thanks Pawel for comments,
Ref: https://stackoverflow.com/a/66321942/9909365
Background location permission does not work like other permissions. It's a request to elevate location permission from foreground-only to foreground & background.
User has to consciously select "Allow all the time" in order to do that and grant background location permission. Otherwise that permission is considered denied.
You cannot even request background location unless foreground location is already granted - when system permission activity shows up it should already have option 2 or 3 selected.
See https://developer.android.com/training/location/permissions#request-background-location
Note:
When your app is using this background location please be prepared with a short video that demonstrates the location-based feature in your app that requires access to location in the background (while the app is not in use).
See https://support.google.com/googleplay/android-developer/answer/9799150
How to ask runtime permissions for Camera in Android , Runtime storage permissions
Below I have written a code for granting a runtime permissions for Camera, There is an Array of String in which you can give multiple requests granting as which is needed at runtime.
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CODE = 200;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkPermission()) {
//main logic or main code
// . write your main code to execute, It will execute if the permission is already given.
} else {
requestPermission();
}
}
private boolean checkPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
return false;
}
return true;
}
private void requestPermission() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
PERMISSION_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Permission Granted", Toast.LENGTH_SHORT).show();
// main logic
} else {
Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
showMessageOKCancel("You need to allow access permissions",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermission();
}
}
});
}
}
}
break;
}
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(MainActivity.this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
}
Runtime Permission - Requesting permission for already granted permission
Since the code was written using Array, its requesting permission for all the values in the array even if it is already granted. So I have rewritten the code to use ArrayList
instead of Array
. Now its working perfectly as expected.
private boolean requestPermissionMethod() {
int permissionContacts = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (locationPermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionContacts != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_CONTACTS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
Related Topics
How to Have the Code Pause for a Couple of Seconds in Android
How to Change Size of Title's Text on Action Bar
Recyclerview Scrolled Up/Down Listener
"Hello World" Android App with as Few Files as Possible, No Ide, and Text Editor Only
How to Get Selected Xls File Path from Uri for Sdk 17 or Below for Android
How to Programmatically Add Views and Constraints to a Constraintlayout
How to Launch Home Screen Programmatically in Android
Android How to Sort JSONarray of JSONobjects
Can't Run Junit 4 Test Case in Eclipse Android Project
:App:Dexdebug Execexception Finished with Non-Zero Exit Value 2
How to Do an Https Post from Android
Android: Cannot Perform This Operation Because the Connection Pool Has Been Closed