I am testing my app on Marshmallow 6.0
and it\'s getting force closed for the android.permission.READ_EXTERNAL_STORAGE
, even if it is defined in th
In my opinion, there is no one correct answer to your question. I strongly suggest you to look at this official permissions patterns page.
Couple of things suggested by Google :
"Your permissions strategy depends on the clarity and importance of the permission type you are requesting. These patterns offer different ways of introducing permissions to the user."
"Critical permissions should be requested up-front. Secondary permissions may be requested in-context."
"Permissions that are less clear should provide education about what the permission involves, whether done up-front or in context."
This illustration might give you better understanding.
Maybe the most crucial thing here is that whether you ask the permission up-front or in the context, you should always keep in mind that these permissions can be revoked anytime by the user (e.g. your app is still running, in background).
You should make sure that your app doesn't crash just because you asked the permission on the very beginning of the app and assumed that user didn't change his/her preference about that permission.
This is worked for me !!! In Your Splash Activity of your application do the following,
1) Declare an int variable for request code,
private static final int REQUEST_CODE_PERMISSION = 2;
2) Declare a string array with the number of permissions you need,
String[] mPermission = {Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
3) Next Check the condition for runtime permission on your onCreate method,
try {
if (ActivityCompat.checkSelfPermission(this, mPermission[0])
!= MockPackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(this, mPermission[1])
!= MockPackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(this, mPermission[2])
!= MockPackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(this, mPermission[3])
!= MockPackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
mPermission, REQUEST_CODE_PERMISSION);
// If any permission aboe not allowed by user, this condition will execute every tim, else your else part will work
}
} catch (Exception e) {
e.printStackTrace();
}
4) Now Declare onRequestPermissionsResult method to check the request code,
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Log.e("Req Code", "" + requestCode);
if (requestCode == REQUEST_CODE_PERMISSION) {
if (grantResults.length == 4 &&
grantResults[0] == MockPackageManager.PERMISSION_GRANTED &&
grantResults[1] == MockPackageManager.PERMISSION_GRANTED &&
grantResults[2] == MockPackageManager.PERMISSION_GRANTED &&
grantResults[3] == MockPackageManager.PERMISSION_GRANTED) {
// Success Stuff here
}
}
}
I like short code. I use RxPermission for permissions.
RxPermission is best library, which makes permission code unexpected just 1 line.
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE) // ask single or multiple permission once
.subscribe(granted -> {
if (granted) {
// All requested permissions are granted
} else {
// At least one permission is denied
}
});
add in your build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}
Isn't this easy?
calling this function we can allow user to open dialog for asking permission to allow camera and record Audio.
if ( ActivityCompat.shouldShowRequestPermissionRationale (this, Manifest.permission.CAMERA) ||
ActivityCompat.shouldShowRequestPermissionRationale (this,
Manifest.permission.RECORD_AUDIO) ) {
Toast.makeText (this,
R.string.permissions_needed,
Toast.LENGTH_LONG).show ();
} else {
ActivityCompat.requestPermissions (
this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
CAMERA_MIC_PERMISSION_REQUEST_CODE);
}
A good explanation and HowTo can be found here:
https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en
I wrote this code to check and request the permissions at runtime in a BaseActivity.class which is parent of every other Activity.class I implemented:
public static final int PERMISSION_REQUEST = 42;
public static final int MULTIPLE_PERMISSION_REQUEST = 43;
//Marshmallow Permission Model
public boolean requestPermission(String permission /* Manifest.permission...*/) {
if (ContextCompat.checkSelfPermission(this,
permission) != PackageManager.PERMISSION_GRANTED) {
if (Utils.hasMarshmallow())
ActivityCompat.requestPermissions(this,
new String[]{permission}, PERMISSION_REQUEST
);
else {
requestPermissions(new String[]{permission},
PERMISSION_REQUEST);
}
return false;
} else {
return true;
}
}
public boolean requestPermission(String... permissions) {
final List<String> permissionsList = new ArrayList<String>();
for (String perm : permissions) {
addPermission(permissionsList, perm);
}
if (permissionsList.size() > 0) {
if (Utils.hasMarshmallow())
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
MULTIPLE_PERMISSION_REQUEST);
else
ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[permissionsList.size()]),
MULTIPLE_PERMISSION_REQUEST);
return false;
} else
return true;
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (Utils.hasMarshmallow())
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST:
case MULTIPLE_PERMISSION_REQUEST: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Simply example call:
activity.requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE);
Return result will let you know if the permission is already granted or not.