I am currently working on an application that requires several "dangerous" permissions. So I tried adding "ask for permission" as required in Android Marshmallow(API Level 23), but couldn't find how to do it.
How can I ask for permission using new permission model in my app?
Open a Dialog using the code below:
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);
Get the Activity result as below:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// 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.
Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
More info: https://developer.android.com/training/permissions/requesting.html
This structure I am using to check if my app has permission and than request if it does not have permission. So in my main code from where i want to check write following :
int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (!checkIfAlreadyhavePermission()) {
requestForSpecificPermission();
}
}
Module checkIfAlreadyhavePermission() is implemented as :
private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
Module requestForSpecificPermission() is implemented as :
private void requestForSpecificPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.GET_ACCOUNTS, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
}
and Override in Activity :
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 101:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//granted
} else {
//not granted
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Refer this link for more details : http://revisitingandroid.blogspot.in/2017/01/how-to-check-and-request-for-run-time.html
Starting in Android Marshmallow, we need to request the user for specific permissions. We can also check through code if the permission is already given. Here is a list of commonly needed permissions:
android.permission_group.CALENDAR
android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR
android.permission_group.CAMERA
android.permission.CAMERA
android.permission_group.CONTACTS
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS
android.permission_group.LOCATION
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
android.permission_group.MICROPHONE
android.permission.RECORD_AUDIO
android.permission_group.PHONE
android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
android.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS
android.permission_group.SENSORS
android.permission.BODY_SENSORS
android.permission_group.SMS
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
android.permission.READ_CELL_BROADCASTS
android.permission_group.STORAGE
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
Here is sample code to check for permissions:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.WRITE_CALENDAR)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setMessage("Write calendar permission is necessary to write event!!!");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
});
} else {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
}
I have used this wrapper (Recommended) written by google developers. Its super easy to use.
https://github.com/googlesamples/easypermissions
Function dealing with checking and ask for permission if required
public void locationAndContactsTask() {
String[] perms = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS };
if (EasyPermissions.hasPermissions(this, perms)) {
// Have permissions, do the thing!
Toast.makeText(this, "TODO: Location and Contacts things", Toast.LENGTH_LONG).show();
} else {
// Ask for both permissions
EasyPermissions.requestPermissions(this, getString(R.string.rationale_location_contacts),
RC_LOCATION_CONTACTS_PERM, perms);
}
}
Happy coding :)
My class for request runtime permissions in Activity or Fragment
It also help you show rationale or open Setting to enable permission after user denied a permission (with/without Never ask again) option easier
class RequestPermissionHandler(private val activity: Activity? = null,
private val fragment: Fragment? = null,
private val permissions: Set<String> = hashSetOf(),
private val listener: Listener? = null
) {
private var hadShowRationale: Boolean = false
fun requestPermission() {
hadShowRationale = showRationaleIfNeed()
if (!hadShowRationale) {
doRequestPermission(permissions)
}
}
fun retryRequestDeniedPermission() {
doRequestPermission(permissions)
}
private fun showRationaleIfNeed(): Boolean {
val unGrantedPermissions = getPermission(permissions, Status.UN_GRANTED)
val permanentDeniedPermissions = getPermission(unGrantedPermissions, Status.PERMANENT_DENIED)
if (permanentDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowSettingRationale(unGrantedPermissions)
if (consume != null && consume) {
return true
}
}
val temporaryDeniedPermissions = getPermission(unGrantedPermissions, Status.TEMPORARY_DENIED)
if (temporaryDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowPermissionRationale(temporaryDeniedPermissions)
if (consume != null && consume) {
return true
}
}
return false
}
fun requestPermissionInSetting() {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val packageName = activity?.packageName ?: run {
fragment?.requireActivity()?.packageName
}
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
activity?.apply {
startActivityForResult(intent, REQUEST_CODE)
} ?: run {
fragment?.startActivityForResult(intent, REQUEST_CODE)
}
}
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_CODE) {
for (i in grantResults.indices) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
markNeverAskAgainPermission(permissions[i], false)
} else if (!shouldShowRequestPermissionRationale(permissions[i])) {
markNeverAskAgainPermission(permissions[i], true)
}
}
var hasShowRationale = false
if (!hadShowRationale) {
hasShowRationale = showRationaleIfNeed()
}
if (hadShowRationale || !hasShowRationale) {
notifyComplete()
}
}
}
fun onActivityResult(requestCode: Int) {
if (requestCode == REQUEST_CODE) {
getPermission(permissions, Status.GRANTED).forEach {
markNeverAskAgainPermission(it, false)
}
notifyComplete()
}
}
fun cancel() {
notifyComplete()
}
private fun doRequestPermission(permissions: Set<String>) {
activity?.let {
ActivityCompat.requestPermissions(it, permissions.toTypedArray(), REQUEST_CODE)
} ?: run {
fragment?.requestPermissions(permissions.toTypedArray(), REQUEST_CODE)
}
}
private fun getPermission(permissions: Set<String>, status: Status): Set<String> {
val targetPermissions = HashSet<String>()
for (p in permissions) {
when (status) {
Status.GRANTED -> {
if (isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
Status.TEMPORARY_DENIED -> {
if (shouldShowRequestPermissionRationale(p)) {
targetPermissions.add(p)
}
}
Status.PERMANENT_DENIED -> {
if (isNeverAskAgainPermission(p)) {
targetPermissions.add(p)
}
}
Status.UN_GRANTED -> {
if (!isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
}
}
return targetPermissions
}
private fun isPermissionGranted(permission: String): Boolean {
return activity?.let {
ActivityCompat.checkSelfPermission(it, permission) == PackageManager.PERMISSION_GRANTED
} ?: run {
ActivityCompat.checkSelfPermission(fragment!!.requireActivity(), permission) == PackageManager.PERMISSION_GRANTED
}
}
private fun shouldShowRequestPermissionRationale(permission: String): Boolean {
return activity?.let {
ActivityCompat.shouldShowRequestPermissionRationale(it, permission)
} ?: run {
ActivityCompat.shouldShowRequestPermissionRationale(fragment!!.requireActivity(), permission)
}
}
private fun notifyComplete() {
listener?.onComplete(getPermission(permissions, Status.GRANTED), getPermission(permissions, Status.UN_GRANTED))
}
private fun getPrefs(context: Context): SharedPreferences {
return context.getSharedPreferences("SHARED_PREFS_RUNTIME_PERMISSION", Context.MODE_PRIVATE)
}
private fun isNeverAskAgainPermission(permission: String): Boolean {
return getPrefs(requireContext()).getBoolean(permission, false)
}
private fun markNeverAskAgainPermission(permission: String, value: Boolean) {
getPrefs(requireContext()).edit().putBoolean(permission, value).apply()
}
private fun requireContext(): Context {
return fragment?.requireContext() ?: run {
activity!!
}
}
enum class Status {
GRANTED, UN_GRANTED, TEMPORARY_DENIED, PERMANENT_DENIED
}
interface Listener {
fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>)
fun onShowPermissionRationale(permissions: Set<String>): Boolean
fun onShowSettingRationale(permissions: Set<String>): Boolean
}
companion object {
const val REQUEST_CODE = 200
}
}
Using in Activity like
class MainActivity : AppCompatActivity() {
private lateinit var smsAndStoragePermissionHandler: RequestPermissionHandler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
smsAndStoragePermissionHandler = RequestPermissionHandler(this#MainActivity,
permissions = setOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_EXTERNAL_STORAGE),
listener = object : RequestPermissionHandler.Listener {
override fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>) {
Toast.makeText(this#MainActivity, "complete", Toast.LENGTH_SHORT).show()
text_granted.text = "Granted: " + grantedPermissions.toString()
text_denied.text = "Denied: " + deniedPermissions.toString()
}
override fun onShowPermissionRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this#MainActivity).setMessage("To able to Send Photo, we need SMS and" + " Storage permission")
.setPositiveButton("OK") { _, _ ->
smsAndStoragePermissionHandler.retryRequestDeniedPermission()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.dismiss()
}
.show()
return true // don't want to show any rationale, just return false here
}
override fun onShowSettingRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this#MainActivity).setMessage("Go Settings -> Permission. " + "Make SMS on and Storage on")
.setPositiveButton("Settings") { _, _ ->
smsAndStoragePermissionHandler.requestPermissionInSetting()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.cancel()
}
.show()
return true
}
})
button_request.setOnClickListener { handleRequestPermission() }
}
private fun handleRequestPermission() {
smsAndStoragePermissionHandler.requestPermission()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
smsAndStoragePermissionHandler.onRequestPermissionsResult(requestCode, permissions,
grantResults)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
smsAndStoragePermissionHandler.onActivityResult(requestCode)
}
}
Code on Github
Demo
Android-M ie, API 23 introduced Runtime Permissions for reducing security flaws in android device, where users can now directly manage app permissions at runtime.so if the user denies a particular permission of your application you have to obtain it by asking the permission dialog that you mentioned in your query.
So check before action ie, check you have permission to access the resource link and if your application doesn't have that particular permission you can request the permission link and handle the the permissions request response like below.
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// 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
}
}
So finally, It's a good practice to go through behavior changes if you are planning to work with new versions to avoid force closes :)
Permissions Best Practices.
You can go through the official sample app here.
Add the permissions to the AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application ...>
....
</application>
To check the Android version if it needs runtime permission or not.
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
}
Ask the user to grant the permission if not granted.
private void askForPermission(String permission, int requestCode) {
if (ContextCompat.checkSelfPermission(c, permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
Toast.makeText(c, "Please grant the requested permission to get your task done!", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
} else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
}
}
}
Do something if the permission was granted or not.
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission with request code 1 granted
Toast.makeText(this, "Permission Granted" , Toast.LENGTH_LONG).show();
} else {
//permission with request code 1 was not granted
Toast.makeText(this, "Permission was not Granted" , Toast.LENGTH_LONG).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
From Android Marshmallow(API 23) and above by default all dangerous permission ( as per official doc official doc) disabled. After installation when app open first time then you have to grant permission at Run Time.
I achieved this following way:
public class MarshMallowPermission {
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_GALLERY = 0;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_CAMERA = 1;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE = 2;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 3;
public static final int LOCATION_PERMISSION_REQUEST_CODE = 4;
Activity activity;
Context mContext;
public MarshMallowPermission(Activity activity) {
this.activity = activity;
this.mContext = activity;
}
public boolean checkPermissionForExternalStorage(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkPermissionForCamera(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkLocationPermission(){
int result = ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public void requestPermissionForExternalStorage(int requestCode){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(mContext.getApplicationContext(), "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
}
}
public void requestPermissionForCamera(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
Toast.makeText(mContext.getApplicationContext(), "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
}
}
public void requestPermissionForLocation(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_COARSE_LOCATION)){
Toast.makeText(mContext.getApplicationContext(), "Location permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
}
}
}
IN Your activity class:
public class MainActivity extends AppCompatActivity{
private MarshMallowPermission marshMallowPermission;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d("NavHome", "Oncreate_nav");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
marshMallowPermission = new MarshMallowPermission(MainActivity.this);
if (!marshMallowPermission.checkPermissionForExternalStorage()) {
marshMallowPermission.requestPermissionForExternalStorage(MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission granted successfully
} else {
//permission denied
}
break;
}
}
}
I'm using this as a base Fragment class. I only ask for permissions from a fragment, but you could refactor it and make a similar Activity version.
public class BaseFragment extends Fragment {
private static final int PERMISSION_REQUEST_BLOCK_INTERNAL = 555;
private static final String PERMISSION_SHARED_PREFERENCES = "permissions";
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_BLOCK_INTERNAL) {
boolean allPermissionsGranted = true;
for (int iGranting : grantResults) {
if (iGranting != PermissionChecker.PERMISSION_GRANTED) {
allPermissionsGranted = false;
break;
}
}
if (allPermissionsGranted && permissionBlock != null) {
permissionBlock.run();
}
permissionBlock = null;
}
}
public void runNowOrAskForPermissionsFirst(String permission, Runnable block) {
if (hasPermission(permission)) {
block.run();
} else if (!hasPermissionOrWillAsk(permission)) {
permissionBlock = block;
askForPermission(permission, PERMISSION_REQUEST_BLOCK_INTERNAL);
}
}
public boolean hasPermissionOrWillAsk(String permission) {
boolean hasPermission = hasPermission(permission);
boolean hasAsked = hasPreviouslyAskedForPermission(permission);
boolean shouldExplain = shouldShowRequestPermissionRationale(permission);
return hasPermission || (hasAsked && !shouldExplain);
}
private boolean hasPermission(String permission) {
return (ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED);
}
private boolean hasPreviouslyAskedForPermission(String permission) {
SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE);
return prefs.getBoolean(permission, false);
}
private void askForPermission(String permission, int requestCode) {
SharedPreferences.Editor editor = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit();
editor.putBoolean(permission, true);
editor.apply();
requestPermissions(new String[] { permission }, requestCode);
}
}
There are two key methods you should use:
hasPermissionOrWillAsk - Use this to see if a permission has been asked for and denies by a user who doesn't want to be asked again. This is useful for disabling UI when the user has given their final answer about NOT wanting a feature.
runNowOrAskForPermissionsFirst - Use this to run some code that requires permissions. If the user has already granted permission, the code will run immediately. Otherwise, the code will run later if the user grants permission. Or not at all. It's nice because you specify the code in one place.
Here's an example:
mFragment.runNowOrAskForPermissionsFirst(Manifest.permission.ACCESS_FINE_LOCATION, new Runnable() {
#Override
public void run() {
...do something if we have permission...
}
});
Happy to get feedback on this. Not that this specific example is a little simplified in that you also need to check to see if Location Services are enabled on the device. (That's different than permissions.) Also, it only supports one permission at a time, but would be simple to modify if you need it to support more than one at a time.
To handle runtime permission google has provided a library project. You can check this from here https://github.com/googlesamples/easypermissions
EasyPermissions is installed by adding the following dependency to your build.gradle file:
dependencies {
compile 'pub.devrel:easypermissions:0.3.0'
}
To begin using EasyPermissions, have your Activity (or Fragment) override the onRequestPermissionsResult method:
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Some permissions have been granted
// ...
}
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Some permissions have been denied
// ...
}
}
Here you will get a working example how this library works
https://github.com/milon87/EasyPermission
It may be a cleaner way. Add all your permissions in an array like
private static final String[] INITIAL_PERMS={
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
};
private static final int INITIAL_REQUEST=1337;
Whatever your permision is create method for each permision
#RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessFineLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
#RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessCoarseLocation() {
return(hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION));
}
#RequiresApi(api = Build.VERSION_CODES.M)
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}
Call this method in onCreate
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(!canAccessCoarseLocation() || !canAccessFineLocation()){
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}
Now override onRequestPermissionsResult
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == INITIAL_REQUEST){
if (canAccessFineLocation() && canAccessCoarseLocation()) {
//call your method
}
else {
//show Toast or alert that this permissions is neccessary
}
}
}
If you're using AndroidX Activity 1.2.0 or AndroidX Fragment 1.3.0:
There are new Activity Result APIs that you can use to ask for permissions:
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
// Permission granted. Do the tasks.
}
}
launcher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
For multiple permission at a time you can use this. This work for me.. I got another solution. if you give your targetSdkVersion bellow 22 it works for me. and it behavior as like getting permission from manifest.xml. Tested and works for me.
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
private void insertDummyContactWrapper() {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add("GPS");
if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
permissionsNeeded.add("Read Contacts");
if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
permissionsNeeded.add("Write Contacts");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "You need to grant access to " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}
insertDummyContact();
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
{
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for ACCESS_FINE_LOCATION
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
// All Permissions Granted
insertDummyContact();
} else {
// Permission Denied
Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)
.show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
For more details. Check bellow link
https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en
There is a good library that can be used in case permissions need to be asked when permission is needed by a background service. Although a limitation of library is that it can not be used to just determine whether permissions are currently given to the app or not. It always asks the user if app doesn't already have them.
Do give it a try as it makes life simpler: Android Permissions
Try this
This is the simplest way to ask for permission in Marshmallow version.
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED&&ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
//TO do here if permission is granted by user
}
else
{
//ask for permission if user didnot given
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
requestPermissions(new String[]{Manifest.permission.CAMERA,Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
}
Note:- Don't forget to add this same permission in manifest file also
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Second Method
Code for checking the permission is granted or not?
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA}, 1);
And override the method
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// grantResult[0] means it will check for the first postion permission which is READ_EXTERNAL_STORAGE
// grantResult[1] means it will check for the Second postion permission which is CAMERA
Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(this, "Permission not Granted", Toast.LENGTH_SHORT).show();
return;
}
}
}
This code below works perfectly.I am explaining with the help of an example.
In my case i placed the permission checks separately in a util class and passed the specific permissions i need to check from the appropriate classes.This enabled to reuse the permission check util file in the whole application.
The below code part shows the function call.In this case am requesting android.Manifest.permission.READ_EXTERNAL_STORAGE permission.
//the below call is from a fragment
#OnClick(R.id.button)//butterknife implementation
public void attachPressed() {
if (PermissionUtils.hasThisPermission(getContext(), android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
onAttachPressed();
} else {
PermissionUtils.isPermissionRequestNeeded(getActivity(), this, android.Manifest.permission.READ_EXTERNAL_STORAGE, PermissionUtils.REQUEST_GROUP_STORAGE);
}
}
In the above case permission is checked if it is allowed the onAttachPressed(); function is called else we check request permission.
The below is the code present in the util class in my case PermissionUtils
public final class PermissionUtils {
public static final int REQUEST_GROUP_STORAGE = 1508;
private PermissionUtils() {
}
public static boolean hasThisPermission(Context context, String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}
public static boolean isPermissionRequestNeeded(Activity activity, Fragment fragment, String permission, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasThisPermission(activity, permission)) {
final String[] permissions = new String[]{permission};
if (fragment == null) {
activity.requestPermissions(permissions, requestCode);
} else {
fragment.requestPermissions(permissions, requestCode);
}
return true;
}
return false;
}
}
And after the request if you might want to call the function from onRequestPermissionsResult or else you will need to press the button again for the function call.
So just call it from onRequestPermissionsResult
//the below call is from a fragment
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PermissionUtils.REQUEST_GROUP_STORAGE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onAttachPressed();
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
}
I use RxPermission library library for asking permission. Because it is long code which we have to write to ask permission.
RxPermissions rxPermissions = new RxPermissions(this); // where this is an Activity instance // Must be done during an initialization phase like onCreate
rxPermissions
.request(Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) { // Always true pre-M
// I can control the camera now
} else {
// Oups permission denied
}
});
Add these dependency 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'
}
I went through all answers, but doesn't satisfied my exact needed answer, so here is an example that I wrote and perfectly works, even user clicks the Don't ask again checkbox.
Create a method that will be called when you want to ask for runtime permission like readContacts() or you can also have openCamera() as shown below:
private void readContacts() {
if (!askContactsPermission()) {
return;
} else {
queryContacts();
} }
Now we need to make askContactsPermission(), you can also name it as askCameraPermission() or whatever permission you are going to ask.
private boolean askContactsPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
#Override
#TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
}
}).show();
} else if (contactPermissionNotGiven) {
openPermissionSettingDialog();
} else {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
contactPermissionNotGiven = true;
}
return false;
}
Before writing this function make sure you have defined the below instance variable as shown:
private View parentLayout;
private boolean contactPermissionNotGiven;;
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
Now final step to override the onRequestPermissionsResult method as shown below:
/**
* Callback received when a permissions request has been completed.
*/
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
queryContacts();
}
}
}
Here we are done with the RunTime permissions, the addon is the openPermissionSettingDialog() which simply open the Setting screen if user have permanently disable the permission by clicking Don't ask again checkbox. below is the method:
private void openPermissionSettingDialog() {
String message = getString(R.string.message_permission_disabled);
AlertDialog alertDialog =
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setMessage(message)
.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(true);
}
What we missed ?
1. Defining the used strings in strings.xml
<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
<string name="message_permission_disabled">You have disabled the permissions permanently,
To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
pressing OK you will be navigated to Settings screen</string>
Initializing the parentLayout variable inside onCreate method
parentLayout = findViewById(R.id.content);
Defining the required permission in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS" />
The queryContacts method, based on your need or the runtime permission you can call your method before which the permission was needed. in my case I simply use the loader to fetch the contact as shown below:
private void queryContacts() {
getLoaderManager().initLoader(0, null, this);}
This works great happy coding :)
Simple way to ask permission by avoiding writing lots of code,
https://github.com/sachinvarma/EasyPermission
How to add :
repositories {
maven { url "https://jitpack.io" }
}
implementation 'com.github.sachinvarma:EasyPermission:1.0.1'
How to ask permission:
List<String> permission = new ArrayList<>();
permission.add(EasyPermissionList.READ_EXTERNAL_STORAGE);
permission.add(EasyPermissionList.ACCESS_FINE_LOCATION);
new EasyPermissionInit(MainActivity.this, permission);
Hoping it will be helpful for someone.
I have found a solutions from my old code and it's really works good, still working on my Latest Apps.
Put it on MainActivity Class or on your Start Activity Class
private RequestPermissionHandler mRequestPermissionHandler;
On Create
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRequestPermissionHandler = new RequestPermissionHandler();
handleButtonClicked();
}
Private function handleButtonClicked()
private void handleButtonClicked() {
mRequestPermissionHandler.requestPermission(this, new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.WAKE_LOCK
}, 123, new RequestPermissionHandler.RequestPermissionListener() {
#Override
public void onSuccess() {
//Toast.makeText(MainActivity.this, "request permission success", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailed() {
Toast.makeText(MainActivity.this, "request permission failed", Toast.LENGTH_SHORT).show();
}
});
}
RequestPermissionHandler.java Class
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
public class RequestPermissionHandler {
private Activity mActivity;
private RequestPermissionListener mRequestPermissionListener;
private int mRequestCode;
public void requestPermission(Activity activity, #NonNull String[] permissions, int requestCode,
RequestPermissionListener listener) {
mActivity = activity;
mRequestCode = requestCode;
mRequestPermissionListener = listener;
if (!needRequestRuntimePermissions()) {
mRequestPermissionListener.onSuccess();
return;
}
requestUnGrantedPermissions(permissions, requestCode);
}
private boolean needRequestRuntimePermissions() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
private void requestUnGrantedPermissions(String[] permissions, int requestCode) {
String[] unGrantedPermissions = findUnGrantedPermissions(permissions);
if (unGrantedPermissions.length == 0) {
mRequestPermissionListener.onSuccess();
return;
}
ActivityCompat.requestPermissions(mActivity, unGrantedPermissions, requestCode);
}
private boolean isPermissionGranted(String permission) {
return ActivityCompat.checkSelfPermission(mActivity, permission)
== PackageManager.PERMISSION_GRANTED;
}
private String[] findUnGrantedPermissions(String[] permissions) {
List<String> unGrantedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (!isPermissionGranted(permission)) {
unGrantedPermissionList.add(permission);
}
}
return unGrantedPermissionList.toArray(new String[0]);
}
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == mRequestCode) {
if (grantResults.length > 0) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
mRequestPermissionListener.onFailed();
return;
}
}
mRequestPermissionListener.onSuccess();
} else {
mRequestPermissionListener.onFailed();
}
}
}
public interface RequestPermissionListener {
void onSuccess();
void onFailed();
}
}
if (CommonMethod.isNetworkAvailable(MainActivity.this)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.CAMERA);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
//showing dialog to select image
callFacebook();
Log.e("permission", "granted MarshMallow");
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1);
}
} else {
Log.e("permission", "Not Required Less than MarshMallow Version");
callFacebook();
}
} else {
CommonMethod.showAlert("Internet Connectivity Failure", MainActivity.this);
}
You can use my library — NoPermission (It's just one class)
compile 'ru.alexbykov:nopermission:1.1.1'
Sample
PermissionHelper permissionHelper = new PermissionHelper(this); //don't use getActivity in fragment!
permissionHelper.check(Manifest.permission.READ_CONTACTS)
.onSuccess(this::onSuccess)
.onDenied(this::onDenied)
.onNeverAskAgain(this::onNeverAskAgain)
.run();
onRequestPermissionResult:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults)
permissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
I think api more convenient than EasyPermissions by Google.
Runtime Permission AnyWhere In ApplicationHere is Example
use dependency
maven { url 'https://jitpack.io' }
dependencies {
implementation 'com.github.irshadsparky:PermissionLib:master-SNAPSHOT'
}
and call code like this :
PermissionHelper.requestCamera(new PermissionHelper.OnPermissionGrantedListener() {
#Override
public void onPermissionGranted() {
}
});
you can find more Github
Run time permission creates a lot of boilerplate code in activity which is heavily coupled. To reduce code and make the thing easy, you can use Dexter library.
RUNTIME PERMISSION IN ANDROID
private static final int PERMISSION_REQ_WRITE_EXTERNAL_STORAGE = 101;
public void onClick(View view) {
if (view.getId() == yourBtn.getId()) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
this.storageWork();
} else {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, PERMISSION_REQ_WRITE_EXTERNAL_STORAGE);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQ_WRITE_EXTERNAL_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
this.storageWork();
}
}
}
public void storageWork(){
}
OnClick method is to check runtime permission
and if Permission is restricted then it request permission
Just this will do:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_CONTACTS}, 0);
}
Related
I know that Android 6.0 has new permissions and I know I can call them with something like this
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, PERMISSION_WRITE_STORAGE);
}
Today I saw a Google app which needs 3 permissions: contacts, sms and camera. It's making a page 1-3 and calls them all together at the same time to activate.
Can anybody tell me how I can call 4 permissions to activate at the same time like sms, camera, contacts and storage?
Example (forgot the name of the google app :( )
The app needs sms,contacts and camera
the app asked me (and made a dialog page1-3) activate sms, activate contacts and then camera.
So this google app was calling all 3 required permissions together and my question is how can i achive the same ?
Just include all 4 permissions in the ActivityCompat.requestPermissions(...) call and Android will automatically page them together like you mentioned.
I have a helper method to check multiple permissions and see if any of them are not granted.
public static boolean hasPermissions(Context context, String... permissions) {
if (context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
Or in Kotlin:
fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
Then just send it all of the permissions. Android will ask only for the ones it needs.
// The request code used in ActivityCompat.requestPermissions()
// and returned in the Activity's onRequestPermissionsResult()
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {
android.Manifest.permission.READ_CONTACTS,
android.Manifest.permission.WRITE_CONTACTS,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_SMS,
android.Manifest.permission.CAMERA
};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
Here is detailed example with multiple permission requests:-
The app needs 2 permissions at startup . SEND_SMS and ACCESS_FINE_LOCATION (both are mentioned in manifest.xml).
I am using Support Library v4 which is prepared to handle Android pre-Marshmallow and so no need to check build versions.
As soon as the app starts up, it asks for multiple permissions together. If both permissions are granted the normal flow goes.
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(checkAndRequestPermissions()) {
// carry on the normal flow, as the case of permissions granted.
}
}
private boolean checkAndRequestPermissions() {
int permissionSendMessage = ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS);
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 (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
ContextCompat.checkSelfPermission(), ActivityCompat.requestPermissions(), ActivityCompat.shouldShowRequestPermissionRationale() are part of support library.
In case one or more permissions are not granted, ActivityCompat.requestPermissions() will request permissions and the control goes to onRequestPermissionsResult() callback method.
You should check the value of shouldShowRequestPermissionRationale() flag in onRequestPermissionsResult() callback method.
There are only two cases:--
Case 1:-Any time user clicks Deny permissions (including the very first time), it will return true. So when the user denies, we can show more explanation and keep asking again
Case 2:-Only if user select “never asks again” it will return false. In this case, we can continue with limited functionality and guide user to activate the permissions from settings for more functionalities, or we can finish the setup, if the permissions are trivial for the app.
CASE -1
CASE-2
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.SEND_SMS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "sms & location services permission granted");
// process the normal flow
//else any one or both the permissions are not granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// // shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
showDialogOK("SMS and Location Services Permission required for this app",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
// //proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
Small code :
public static final int MULTIPLE_PERMISSIONS = 10; // code you want.
String[] permissions= new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION};
if (checkPermissions())
// permissions granted.
}
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p:permissions) {
result = ContextCompat.checkSelfPermission(getActivity(),p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),MULTIPLE_PERMISSIONS );
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissionsList[], int[] grantResults) {
switch (requestCode) {
case MULTIPLE_PERMISSIONS:{
if (grantResults.length > 0) {
String permissionsDenied = "";
for (String per : permissionsList) {
if(grantResults[0] == PackageManager.PERMISSION_DENIED){
permissionsDenied += "\n" + per;
}
}
// Show permissionsDenied
updateViews();
}
return;
}
}
}
List of Android permissions normal permissions and dangerous permissions in API 23
In a Fragment
public class Homefragment extends Fragment {
View hfrag;
Context context;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//first we must check the permissions are already granted
hfrag = inflater.inflate(R.layout.home, container, false);
context = getActivity();
checkAndRequestPermissions();
}
}
private boolean checkAndRequestPermissions() {
int permissionSendMessage = ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_SMS);
int contactpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS);
int writepermission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int callpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE);
int receivepermission = ContextCompat.checkSelfPermission(context, Manifest.permission.RECEIVE_SMS);
int locationpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (locationpermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (contactpermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.GET_ACCOUNTS);
}
if (writepermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_SMS);
}
if (receivepermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.RECEIVE_SMS);
}
if (callpermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CALL_PHONE);
}
if (!listPermissionsNeeded.isEmpty()) {
requestPermissions(listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_ID_MULTIPLE_PERMISSIONS) {
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++) {
if (permissions[i].equals(Manifest.permission.GET_ACCOUNTS)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "accounts granted");
}
} else if (permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "storage granted");
}
} else if (permissions[i].equals(Manifest.permission.CALL_PHONE)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "call granted");
}
} else if (permissions[i].equals(Manifest.permission.RECEIVE_SMS)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "sms granted");
}
} else if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "location granted");
}
}
}
}
}
}
}
It's easy, do this way
private static final int REQUEST_READ_PHONE_STATE = 110 , REQUEST_ACCESS_FINE_LOCATION = 111, REQUEST_WRITE_STORAGE = 112;
In your onCreate
//request permission
boolean hasPermissionPhoneState = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermissionPhoneState) {
ActivityCompat.requestPermissions(LoginActivity.this,
new String[]{Manifest.permission.READ_PHONE_STATE},
REQUEST_READ_PHONE_STATE);
}
boolean hasPermissionLocation = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
if (!hasPermissionLocation) {
ActivityCompat.requestPermissions(LoginActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_ACCESS_FINE_LOCATION);
}
boolean hasPermissionWrite = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermissionWrite) {
ActivityCompat.requestPermissions(LoginActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
}
Then check result
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case REQUEST_READ_PHONE_STATE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
//reload my activity with permission granted or use the features what required the permission
finish();
startActivity(getIntent());
} else
{
Toast.makeText(LoginActivity.this, "The app was not allowed to get your phone state. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
case REQUEST_ACCESS_FINE_LOCATION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
//reload my activity with permission granted or use the features what required the permission
finish();
startActivity(getIntent());
} else
{
Toast.makeText(LoginActivity.this, "The app was not allowed to get your location. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
case REQUEST_WRITE_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
//reload my activity with permission granted or use the features what required the permission
finish();
startActivity(getIntent());
} else
{
Toast.makeText(LoginActivity.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}
My approach is based on Nicks' answer and hopefully is a bit more usable for multiple (as many as needed, not only two) permissions.
It suggests adding single-responsibility PermissionsHelper class:
import android.app.Activity;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PermissionsHelper {
private static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 100; // any code you want.
public void checkAndRequestPermissions(Activity activity, String... permissions) {
List<String> listPermissionsNeeded = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(permission);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(activity, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
}
}
public void onRequestPermissionsResult(Activity activity, int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
for (String permission : permissions) {
perms.put(permission, PackageManager.PERMISSION_GRANTED);
}
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
boolean allPermissionsGranted = true;
for (String permission1 : permissions) {
allPermissionsGranted = allPermissionsGranted && (perms.get(permission1) == PackageManager.PERMISSION_GRANTED);
}
if (allPermissionsGranted) {
Log.d(PermissionsHelper.class.getSimpleName(), "onRequestPermissionsResult: all permissions granted");
} else {
for (String permission2 : perms.keySet())
if (perms.get(permission2) == PackageManager.PERMISSION_GRANTED)
perms.remove(permission2);
StringBuilder message = new StringBuilder("The app has not been granted permissions:\n\n");
for (String permission : perms.keySet()) {
message.append(permission);
message.append("\n");
}
message.append("\nHence, it cannot function properly." +
"\nPlease consider granting it this permission in phone Settings.");
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.permission_required)
.setMessage(message)
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.cancel());
AlertDialog alert = builder.create();
alert.show();
}
}
}
}
}
}
If one or several required permissions have not been granted by user, the detailed AlertDialog message will be shown to him.
Example of usage in Activity:
private PermissionsHelper permissionsHelper;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkPermissions();
//any other code
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
permissionsHelper.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
}
private void checkPermissions() {
permissionsHelper = new PermissionsHelper();
permissionsHelper.checkAndRequestPermissions(this,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION);
}
Hope that this will be useful for someone.
My handler class for request multiple permissions. You can check the full using here
public class RequestPermissionHandler {
private Activity mActivity;
private RequestPermissionListener mRequestPermissionListener;
private int mRequestCode;
public void requestPermission(Activity activity, #NonNull String[] permissions, int requestCode,
RequestPermissionListener listener) {
mActivity = activity;
mRequestCode = requestCode;
mRequestPermissionListener = listener;
if (!needRequestRuntimePermissions()) {
mRequestPermissionListener.onSuccess();
return;
}
requestUnGrantedPermissions(permissions, requestCode);
}
private boolean needRequestRuntimePermissions() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
private void requestUnGrantedPermissions(String[] permissions, int requestCode) {
String[] unGrantedPermissions = findUnGrantedPermissions(permissions);
if (unGrantedPermissions.length == 0) {
mRequestPermissionListener.onSuccess();
return;
}
ActivityCompat.requestPermissions(mActivity, unGrantedPermissions, requestCode);
}
private boolean isPermissionGranted(String permission) {
return ActivityCompat.checkSelfPermission(mActivity, permission)
== PackageManager.PERMISSION_GRANTED;
}
private String[] findUnGrantedPermissions(String[] permissions) {
List<String> unGrantedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (!isPermissionGranted(permission)) {
unGrantedPermissionList.add(permission);
}
}
return unGrantedPermissionList.toArray(new String[0]);
}
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == mRequestCode) {
if (grantResults.length > 0) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
mRequestPermissionListener.onFailed();
return;
}
}
mRequestPermissionListener.onSuccess();
} else {
mRequestPermissionListener.onFailed();
}
}
}
public interface RequestPermissionListener {
void onSuccess();
void onFailed();
}
}
Refer this link for full understand of multiple permission, also full source code download, click Here
private boolean checkAndRequestPermissions() {
int permissionReadPhoneState = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
int permissionProcessOutGogingCalls = ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_OUTGOING_CALLS);
int permissionProcessReadContacts = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);
int permissionProcessReadCallLog = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG);
int permissionWriteStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionReadStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (permissionReadPhoneState != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
}
if (permissionProcessOutGogingCalls != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.PROCESS_OUTGOING_CALLS);
}
if (permissionProcessReadContacts != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_CONTACTS);
}
if (permissionProcessReadCallLog != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_CALL_LOG);
}
if (permissionWriteStorage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionReadStorage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length == 0 || grantResults == null) {
/*If result is null*/
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
/*If We accept permission*/
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
/*If We Decline permission*/
}
}
The following methodology is about
asking permissions dynamically ;
showing a AlertDialog if the user denies any permission
looping until the user accepts permission(s)
Create a "static" class for permissions methods
public class PermissionsUtil {
public static final int PERMISSION_ALL = 1;
public static boolean doesAppNeedPermissions(){
return android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1;
}
public static String[] getPermissions(Context context)
throws PackageManager.NameNotFoundException {
PackageInfo info = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_PERMISSIONS);
return info.requestedPermissions;
}
public static void askPermissions(Activity activity){
if(doesAppNeedPermissions()) {
try {
String[] permissions = getPermissions(activity);
if(!checkPermissions(activity, permissions)){
ActivityCompat.requestPermissions(activity, permissions,
PERMISSION_ALL);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
public static boolean checkPermissions(Context context, String... permissions){
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null &&
permissions != null) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) !=
PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
}
In MainActivity.java
private void checkPermissions(){
PermissionsUtil.askPermissions(this);
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PermissionsUtil.PERMISSION_ALL: {
if (grantResults.length > 0) {
List<Integer> indexesOfPermissionsNeededToShow = new ArrayList<>();
for(int i = 0; i < permissions.length; ++i) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
indexesOfPermissionsNeededToShow.add(i);
}
}
int size = indexesOfPermissionsNeededToShow.size();
if(size != 0) {
int i = 0;
boolean isPermissionGranted = true;
while(i < size && isPermissionGranted) {
isPermissionGranted = grantResults[indexesOfPermissionsNeededToShow.get(i)]
== PackageManager.PERMISSION_GRANTED;
i++;
}
if(!isPermissionGranted) {
showDialogNotCancelable("Permissions mandatory",
"All the permissions are required for this app",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
checkPermissions();
}
});
}
}
}
}
}
}
private void showDialogNotCancelable(String title, String message,
DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setCancelable(false)
.create()
.show();
}
🔥 NEW EASY AND CLEAN WAY OF ASKING MULTIPLE PERMISSIONS IN 2022 🔥
At the top of your activity class, write
private val multiplePermissionContract = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissionsStatusMap ->
// permissionStatusMap is of type <String, Boolean>
// if all permissions accepted
if (!permissionsStatusMap.containsValue(false)) {
// All persmissions are accepted, do here whatever you want
} else {
Toast.makeText(this, "all permissions not accepted", Toast.LENGTH_SHORT).show()
}
}
And, launch the permission asking dialogs whenever you want like below(for now, I am thinking that you need to ask the permissions when you click on xyzButton)
xyzButton.setOnClickListener {
multiplePermissionContract.launch(
arrayOf(
android.Manifest.permission.READ_CONTACTS,
android.Manifest.permission.WRITE_CONTACTS,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_SMS,
android.Manifest.permission.CAMERA
)
)
}
NOTE -
registerForActivityResult() method will always be called whenever we click on xyzButton. If all any of the all permissions is not accepted earlier, it will ask that particular permission again; else it will directly execute the if condition block.
There is nothing wrong with answers asking for multiple permissions but multiple permission result code is not implemented very elegantly and may cause checking wrong permission result.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) is terrible logic for checking multiple permissions result, i don't know why Google implemented such a terrible code.
It's a mess especially when you check multiple permissions. Let say you ask for CAMERA, ACCESS_FINE_LOCATION and ACCESS_NETWORK_STATE.
You need to check for ACCESS_FINE_LOCATION but user only granted CAMERA at first run and you check for grantResults[1] but in second run ACCESS_FINE_LOCATION becomes the permission with index 0. I got so many problems with user not granting all permissions at once and have to write so pointless permission result logic.
You should either use
int size = permissions.length;
boolean locationPermissionGranted = false;
for (int i = 0; i < size; i++) {
if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION)
&& grantResults[i] == PackageManager.PERMISSION_GRANTED) {
locationPermissionGranted = true;
}
}
Or simpler one
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
// Do something ...
}
in onPermissionRequestResult method.
Checking every situation
if denied - showing Alert dialog to user why we need permission
public static final int MULTIPLE_PERMISSIONS = 1;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 2;
public static final int STORAGE_PERMISSION_REQUEST_CODE = 3;
private void askPermissions() {
int permissionCheckStorage = ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionCheckCamera = ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA);
// we already asked for permisson & Permission granted, call camera intent
if (permissionCheckStorage == PackageManager.PERMISSION_GRANTED && permissionCheckCamera == PackageManager.PERMISSION_GRANTED) {
launchCamera();
} //asking permission for the first time
else if (permissionCheckStorage != PackageManager.PERMISSION_GRANTED && permissionCheckCamera != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
MULTIPLE_PERMISSIONS);
} else {
// Permission denied, so request permission
// if camera request is denied
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("You need to give permission to take pictures in order to work this feature.");
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.setPositiveButton("GIVE PERMISSION", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
// Show permission request popup
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
CAMERA_PERMISSION_REQUEST_CODE);
}
});
builder.show();
} // if storage request is denied
else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("You need to give permission to access storage in order to work this feature.");
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.setPositiveButton("GIVE PERMISSION", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
// Show permission request popup
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
STORAGE_PERMISSION_REQUEST_CODE);
}
});
builder.show();
}
}
}
Checking Permission Results
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case CAMERA_PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && permissions[0].equals(Manifest.permission.CAMERA)) {
// check whether camera permission granted or not.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
launchCamera();
}
}
break;
case STORAGE_PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// check whether storage permission granted or not.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
launchCamera();
}
}
break;
case MULTIPLE_PERMISSIONS:
if (grantResults.length > 0 && permissions[0].equals(Manifest.permission.CAMERA) && permissions[1].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// check whether All permission granted or not.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
launchCamera();
}
}
break;
default:
break;
}
}
you can just copy and paste this code, it works fine. change context(this) & permissions according to you.
Short and sweet :). what I believe in.
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}; // List of permissions required
public void askPermission()
{
for (String permission : PERMISSIONS) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(PERMISSIONS, PERMISSION_ALL);
return;
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case 1:{
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
//Do your work.
} else {
Toast.makeText(this, "Until you grant the permission, we cannot proceed further", Toast.LENGTH_SHORT).show();
}
return;
}
}
After seeing all the long and complex answers. I want post this answer.
RxPermission is widely used library now for asking permission in one line code.
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.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?
I have successfully implemented simple code for Multiple permission at Once.
Follow the below steps
1:Make Utility.java class like below
public class Utility {
public static final int MY_PERMISSIONS_REQUEST = 123;
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static boolean checkPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, permission)) {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CALL_PHONE,Manifest.permission.GET_ACCOUNTS}, MY_PERMISSIONS_REQUEST);
} else {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CALL_PHONE,Manifest.permission.GET_ACCOUNTS}, MY_PERMISSIONS_REQUEST);
}
return false;
}
}
}
return true;
}
}
2: Now call
boolean permissionCheck = Utility.checkPermissions(this, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CALL_PHONE, Manifest.permission.GET_ACCOUNTS);
in your Activity onCreate() or according to your logic.
3:Now check permission before performing operation for particular task
if (permissionCheck) {
performTaskOperation();//this method what you need to perform
} else {
Toast.makeText(this, "Need permission ON.", Toast.LENGTH_SHORT).show();
}
4: Now implement onRequestPermissionsResult() method in your Activity as below
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case Utility.MY_PERMISSIONS_REQUEST:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (userChoosenTask.equals("STORAGE"))
performTaskOperation();//this method what you need to perform
}
break;
}
}
I just use an array to achieved multiple requests, hope it helps someone. (Kotlin)
// got all permission
private fun requestPermission(){
var mIndex: Int = -1
var requestList: Array<String> = Array(10, { "" } )
// phone call Permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.CALL_PHONE
}
// SMS Permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.SEND_SMS
}
// Access photos Permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.READ_EXTERNAL_STORAGE
}
// Location Permission
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
mIndex ++
requestList[mIndex] = Manifest.permission.ACCESS_FINE_LOCATION
}
if(mIndex != -1){
ActivityCompat.requestPermissions(this, requestList, PERMISSIONS_REQUEST_ALL)
}
}
// permission response
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
PERMISSIONS_REQUEST_ALL -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Phone Call permission accept.")
}
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "SMS permission accept.")
}
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "SMS permission accept.")
}
// permission accept location
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Location permission accept.")
}
} else {
Toast.makeText(mContext, "Permission Failed!", Toast.LENGTH_LONG).show()
}
return
}
}
}
I found this is in the runtime permissions example from Google's github.
private static String[] PERMISSIONS_CONTACT = {Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS};
private static final int REQUEST_CONTACTS = 1;
ActivityCompat.requestPermissions(this, PERMISSIONS_CONTACT, REQUEST_CONTACTS);
Check the "Asking for multiple permissions at a time" section in this article:
Things you need to know about Android M permissions
It's very well explained, and may also touch other related topics you haven't think about.
Use helper like this (permissions names do not matter).
public class MyPermission {
private static final int PERMISSION_REQUEST_ALL = 127;
private MainActivity mMainActivity;
MyPermission(MainActivity mainActivity) {
mMainActivity = mainActivity;
}
public static boolean hasPermission(String permission, Context context) {
if (isNewPermissionModel()) {
return (ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
}
return true;
}
private static boolean hasPermissions(Context context, String... permissions) {
if (isNewPermissionModel() && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
private static boolean shouldShowRationale(Activity activity, String permission) {
return isNewPermissionModel() && ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
private static boolean isNewPermissionModel() {
return VERSION.SDK_INT > VERSION_CODES.LOLLIPOP_MR1;
}
/**
* check all permissions
*/
void checkAll() {
//check dangerous permissions, make request if need (Android will ask only for the ones it needs)
String[] PERMISSIONS = {
permission.READ_CALENDAR,
permission.ACCESS_COARSE_LOCATION
};
if (!hasPermissions(mMainActivity, PERMISSIONS)) {
ActivityCompat.requestPermissions(mMainActivity, PERMISSIONS, PERMISSION_REQUEST_ALL);
}
}
void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_ALL) {
if (grantResults.length > 0) {
//for not granted
for (int i = 0; i < permissions.length; i++) {
if (permissions[i].equals(permission.READ_CALENDAR)) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
smartRequestPermissions(permission.READ_CALENDAR, R.string.permission_required_dialog_read_calendar);
}
} else if (permissions[i].equals(permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
smartRequestPermissions(permission.ACCESS_COARSE_LOCATION, R.string.permission_required_dialog_access_coarse_location);
}
}
}
}
}
}
private void smartRequestPermissions(final String permissionName, int permissionRequiredDialog) {
if (shouldShowRationale(mMainActivity, permissionName)) {// If the user turned down the permission request in the past and chose the Don't ask again option in the permission request system dialog, this method returns false.
//Show an explanation to the user with action
mMainActivity.mSnackProgressBarManager.show(
new SnackProgressBar(
SnackProgressBar.TYPE_ACTION, mMainActivity.getString(permissionRequiredDialog)
)
.setAction("OK", new OnActionClickListener() {
#Override
public void onActionClick() {
checkAll();
}
})
.setSwipeToDismiss(true).setAllowUserInput(true)
, MainActivity.SNACKBAR_WARNING_DURATION
);
} // else do nothing
}
}
Simple way to ask multiple permission,
https://github.com/sachinvarma/EasyPermission
How to add :
repositories {
maven { url "https://jitpack.io" }
}
implementation 'com.github.sachinvarma:EasyPermission:1.0.1'
How to ask permission:
List<String> permission = new ArrayList<>();
permission.add(EasyPermissionList.READ_EXTERNAL_STORAGE);
permission.add(EasyPermissionList.ACCESS_FINE_LOCATION);
new EasyPermissionInit(MainActivity.this, permission);
For more Details - >
https://github.com/sachinvarma/EasyPermission/blob/master/app/src/main/java/com/sachinvarma/easypermissionsample/MainActivity.java
It may help someone in future.
In Kotlin:
private val id = 1
private val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.ACCESS_FINE_LOCATION)
fun hasPermissions(): Boolean {
for (perm in permissions) {
if (ActivityCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
return false
}
}
return true
}
if(! hasPermissions()){
requestPermissions(this, permissions, id)
}
This is what I have done in my activity. Hoping will be helpful. I am asking for camera and microphone permissions.
public class ActiveCallActivity extends AppCompatActivity {
.....
private static final String cameraPermissionKey = "cameraPermission";
private static final String microphonePermissionkey = "microphonePermission";
private static ArrayList<String> permissionsQueue = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
.....
// in ValidationCheckersAndValidators simply checking if have permission or not.
if(ValidationCheckersAndValidators.haveCameraPermission(this)) performHaveCameraPermissionLayout(); else performHaveNoCameraPermissionLayout();
if(ValidationCheckersAndValidators.haveMicrophonePermission(this)) performHaveMicrophonePermissionLayout(); else performHaveNoMicrophonePermissionLayout();
}
private void performHaveNoCameraPermissionLayout() {
.....
permissionsQueue.add(cameraPermissionKey);
}
private void performHaveNoMicrophonePermissionLayout() {
.....
permissionsQueue.add(microphonePermissionkey);
}
#Override
protected void onResume() {
super.onResume();
.....
passThroughPermissionsQueue();
}
private void passThroughPermissionsQueue() {
if(!permissionsQueue.isEmpty()) {
String permissionKey = permissionsQueue.remove(0);
switch (permissionKey) {
case cameraPermissionKey: {
ValidationCheckersAndValidators.requestForCameraPermission(this);
return;
}
case microphonePermissionkey: {
ValidationCheckersAndValidators.requestForMicrophonePermission(this);
return;
}
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch(requestCode) {
case cameraPermissionRequestCode: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
performHaveCameraPermissionLayout();
}
break;
}
case microphonePermissionRequestCode: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
performHaveMicrophonePermissionLayout();
}
break;
}
}
passThroughPermissionsQueue();
}
}
You can use Dexter
In build.gradle add:
implementation 'com.karumi:dexter:5.0.0'
And use it in your activity as:
val requiredPermissions = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> listOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION)
else -> listOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION)
}
Dexter.withActivity(this)
.withPermissions(
requiredPermissions
)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
/* ... */
}
override fun onPermissionsChecked(report: MultiplePermissionsReport) =
if (report.isAnyPermissionPermanentlyDenied) {
toast("You should grant all permissions")
} else {
toast("All permissions granted")
// continue here if permission is a must
}).check()
// continue here if permission is not a must
I want to use the
android.permission.CAMERA
android.permission.WRITE_EXTERNAL_STORAGE
in single request using
ActivityCompat.requestPermissions(Activity activity,new String permisionList[],int permissionRequestcode);
But my problem is at time I request only one permission,
I read about group-permission,But it's work for only Same group which one decided by Developer, Like CONTACT_GROUP : read_contact,write_contact etc.
I want create the custom group permission which ask me only one request & provide me only one response.
Thanks
You can ask multiple permissions (from different groups) in a single request. For that, you need to add all the permissions to the string array that you supply as the first parameter to the requestPermissions API like this:
requestPermissions(new String[]{
Manifest.permission.READ_CONTACTS,
Manifest.permission.ACCESS_FINE_LOCATION},
ASK_MULTIPLE_PERMISSION_REQUEST_CODE);
On doing this, you will see the permission popup as a stack of multiple permission popups. Ofcourse you need to handle the acceptance and rejection (including the "Never Ask Again") options of each permissions. The same has been beautifully explained over here.
First initialize permission request code
public static final int PERMISSIONS_MULTIPLE_REQUEST = 123;
Check android version
private void checkAndroidVersion() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermission();
} else {
// write your logic here
}
}
check multiple permission code
private void checkPermission() {
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.READ_EXTERNAL_STORAGE) + ContextCompat
.checkSelfPermission(getActivity(),
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale
(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) ||
ActivityCompat.shouldShowRequestPermissionRationale
(getActivity(), Manifest.permission.CAMERA)) {
Snackbar.make(getActivity().findViewById(android.R.id.content),
"Please Grant Permissions to upload profile photo",
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
requestPermissions(
new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
PERMISSIONS_MULTIPLE_REQUEST);
}
}).show();
} else {
requestPermissions(
new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
PERMISSIONS_MULTIPLE_REQUEST);
}
} else {
// write your logic code if permission already granted
}
}
call back method after grant permission by user
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_MULTIPLE_REQUEST:
if (grantResults.length > 0) {
boolean cameraPermission = grantResults[1] == PackageManager.PERMISSION_GRANTED;
boolean readExternalFile = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if(cameraPermission && readExternalFile)
{
// write your logic here
} else {
Snackbar.make(getActivity().findViewById(android.R.id.content),
"Please Grant Permissions to upload profile photo",
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
requestPermissions(
new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
PERMISSIONS_MULTIPLE_REQUEST);
}
}).show();
}
}
break;
}
}
There is no hack available at this stage to circumvent asking for permissions from different groups together. That is the nature of how android has developed runtime permissions, to give users a choice of which permissions to accept. Of course not accepting all permissions required by an app, may make the app fail to work properly.
CAMERA and WRITE_EXTERNAL_STORAGE are both regarded as dangerous permissions, and in separate groups, thus both requiring a runtime permission request.
Once permission is granted for a particular group, it does not need to be requested again for the lifetime of the app run, or until it is revoked if given as a default setting.
The only thing you can do is ask the user to accept the decisions as default, which can be revoked, by using "never ask again"
I had the same issue and stumbled on this library.
Basically you can ask for multiple permissions sequentially, plus you can add listeners to popup a snackbar if the user denies your permission.
For multiple permission you can use this code :
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
private void insertDummyContactWrapper() {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add("GPS");
if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
permissionsNeeded.add("Read Contacts");
if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
permissionsNeeded.add("Write Contacts");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "You need to grant access to " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}
insertDummyContact();
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
Here i have a simple solution, - (Multiple permission checking)
String[] permissions = new String[]{
Manifest.permission.WRITE_CALL_LOG,
Manifest.permission.READ_CALL_LOG,
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS}; // Here i used multiple permission check
Then call it in Oncreate
if (checkPermissions()) { // permissions granted.
getCallDetails();
}
Finally, copy the below code
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(getApplicationContext(), p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MULTIPLE_PERMISSIONS: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permissions granted.
getCallDetails(); // Now you call here what ever you want :)
} else {
String perStr = "";
for (String per : permissions) {
perStr += "\n" + per;
} // permissions list of don't granted permission
}
return;
}
}
}
As said earlier, currently every permission group has own permission dialog which must be called separately.
You will have different dialog boxes for each permission group but you can surely check the result together in onRequestPermissionsResult() callback method.
Here is a working example link, may be useful for someone.
I faced the same problem and below is the workaround I came up with:
public boolean checkForPermission(final String[] permissions, final int permRequestCode, int msgResourceId) {
final List<String> permissionsNeeded = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
final String perm = permissions[i];
if (ContextCompat.checkSelfPermission(getActivity(), permissions[i]) != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(permissions[i])) {
final AlertDialog dialog = AlertDialog.newInstance( getResources().getString(R.string.permission_title), getResources().getString(msgResourceId) );
dialog.setPositiveButton("OK", new View.OnClickListener() {
#Override
public void onClick(View view) {
// add the request.
permissionsNeeded.add(perm);
dialog.dismiss();
}
});
dialog.show( getActivity().getSupportFragmentManager(), "HCFAlertDialog" );
} else {
// add the request.
permissionsNeeded.add(perm);
}
}
}
if (permissionsNeeded.size() > 0) {
// go ahead and request permissions
requestPermissions(permissionsNeeded.toArray(new String[permissionsNeeded.size()]), permRequestCode);
return false;
} else {
// no permission need to be asked so all good...we have them all.
return true;
}
}
And you call the above method like this:
if ( checkForPermission( new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA}, REQUEST_PERMISSION_EXTERNAL_STORAGE_RESULT, R.string.permission_image) ) {
// DO YOUR STUFF
}
check More than one Permission and Request if Not Granted
public void checkPermissions(){
if(ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.CAMERA)==PackageManager.PERMISSION_GRANTED){
//Do_SOme_Operation();
}else{
requestStoragePermission();
}
}
public void requestStoragePermission(){
ActivityCompat.requestPermissions(this
,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA},1234);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case 1234:if(grantResults[0]==PackageManager.PERMISSION_GRANTED && grantResults[1]==PackageManager.PERMISSION_GRANTED){
// Do_SOme_Operation();
}
default:super.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
}
// **For multiple permission you can use this code :**
// **First:**
//Write down in onCreate method.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST);
}
//**Second:**
//Write down in a activity.
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
progressBar.setVisibility(View.GONE);
Intent i = new Intent(SplashActivity.this,
HomeActivity.class);
startActivity(i);
finish();
}
}, SPLASH_DISPLAY_LENGTH);
} else {
finish();
}
return;
}
}
Based on what i've searched, i think this is the best answers that i've found out Android 6.0 multiple permissions
Adding generic code for different types of permissions. Copy-paste with minor changes. Read the "TODO" comments in the code below.
Make the following Activity your Launcher Activity:
public class PermissionReqActivity extends AppCompatActivity {
private static final int CODE_WRITE_SETTINGS_PERMISSION = 332;
private static String[] PERMISSIONS_ALL = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; //TODO You can Add multiple permissions here.
private static final int PERMISSION_REQUEST_CODE = 223;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_permission_req);
context = this;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean allPermissionsGranted = true;
ArrayList<String> toReqPermissions = new ArrayList<>();
for (String permission : PERMISSIONS_ALL) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
toReqPermissions.add(permission);
allPermissionsGranted = false;
}
}
if (allPermissionsGranted)
//TODO Now some permissions are very special and require Settings Activity to launch, as u might have seen in some apps. handleWriteSettingsPermission() is an example for WRITE_SETTINGS permission. If u don't need very special permission(s), replace handleWriteSettingsPermission() with initActivity().
handleWriteSettingsPermission();
else
ActivityCompat.requestPermissions(this,
toReqPermissions.toArray(new String[toReqPermissions.size()]), PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
boolean allPermGranted = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permissions not granted: " + permissions[i], Toast.LENGTH_LONG).show();
allPermGranted = false;
finish();
break;
}
}
if (allPermGranted)
handleWriteSettingsPermission();//TODO As mentioned above, use initActivity() here if u dont need very special permission WRITE_SETTINGS
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private void handleWriteSettingsPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.System.canWrite(context)) {
initActivity();
} else {
Toast.makeText(this, "Please Enable this permission for " +
getApplicationInfo().loadLabel(getPackageManager()).toString(), Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + context.getPackageName()));
startActivityForResult(intent, CODE_WRITE_SETTINGS_PERMISSION);
}
}
}
//TODO You don't need the following onActivityResult() function if u dont need very special permissions.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && requestCode == CODE_WRITE_SETTINGS_PERMISSION) {
if (Settings.System.canWrite(this))
initActivity();
else {
Toast.makeText(this, "Permissions not granted: " + Manifest.permission.WRITE_SETTINGS, Toast.LENGTH_LONG).show();
finish();
}
}
}
private void initActivity() {
startActivity(new Intent(this, MainActivity.class));
}
}
Based on vedval i have this solution.
public boolean checkForPermission(final String[] permissions, final int permRequestCode) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
final List<String> permissionsNeeded = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
final String perm = permissions[i];
if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(permissions[i])) {
Snackbar.make(phrase, R.string.permission_location, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
#Override
#TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
permissionsNeeded.add(perm);
}
});
} else {
// add the request.
permissionsNeeded.add(perm);
}
}
}
if (permissionsNeeded.size() > 0) {
// go ahead and request permissions
requestPermissions(permissionsNeeded.toArray(new String[permissionsNeeded.size()]), permRequestCode);
return false;
} else {
// no permission need to be asked so all good...we have them all.
return true;
}
}
/**
* Callback received when a permissions request has been completed.
*/
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_LOCATION) {
int i = 0;
for (String permission : permissions ){
if ( permission.equals(Manifest.permission.ACCESS_FINE_LOCATION) && grantResults.length > 0 && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
initLocationManager();
}
i++;
}
}
}
I am late, but i want tell the library which i have ended with.
RxPermission is best library with reactive code, which makes permission code unexpected just 1 line.
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.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'
}
you should use the dependency named dexter as given below:
https://github.com/Karumi/Dexter
by this you can get one or many permission easily:
this is the given code
Dexter.withContext(this).
withPermissions(Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport
multiplePermissionsReport) {
displaySong();
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> list,
PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).check();
For Asking Multiple Permission At Once You Can Use this Method link
compile 'com.kishan.askpermission:askpermission:1.0.3'
If you got conflicting in support library then
compile('com.kishan.askpermission:askpermission:1.0.3', {
exclude group: 'com.android.support'
})
Now ask for Permission
new AskPermission.Builder(this)
.setPermissions(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.setCallback(/* PermissionCallback */)
.setErrorCallback(/* ErrorCallback */)
.request(/* Request Code */);
permission granted callback
public void onPermissionsGranted(int requestCode) {
// your code }
permission denied callback
public void onPermissionsDenied(int requestCode) {
// your code}
ErrorCallbacks
public void onShowRationalDialog(PermissionInterface permissionInterface, int requestCode) {
// Alert user by Dialog or any other layout that you want.
// When user press OK you must need to call below method.
permissionInterface.onDialogShown();
}
public void onShowSettings(PermissionInterface permissionInterface, int requestCode) {
// Alert user by Dialog or any other layout that you want.
// When user press OK you must need to call below method.
// It will open setting screen.
permissionInterface.onSettingsShown();
}
I want to use the
android.permission.CAMERA
android.permission.WRITE_EXTERNAL_STORAGE
in single request using
ActivityCompat.requestPermissions(Activity activity,new String permisionList[],int permissionRequestcode);
But my problem is at time I request only one permission,
I read about group-permission,But it's work for only Same group which one decided by Developer, Like CONTACT_GROUP : read_contact,write_contact etc.
I want create the custom group permission which ask me only one request & provide me only one response.
Thanks
You can ask multiple permissions (from different groups) in a single request. For that, you need to add all the permissions to the string array that you supply as the first parameter to the requestPermissions API like this:
requestPermissions(new String[]{
Manifest.permission.READ_CONTACTS,
Manifest.permission.ACCESS_FINE_LOCATION},
ASK_MULTIPLE_PERMISSION_REQUEST_CODE);
On doing this, you will see the permission popup as a stack of multiple permission popups. Ofcourse you need to handle the acceptance and rejection (including the "Never Ask Again") options of each permissions. The same has been beautifully explained over here.
First initialize permission request code
public static final int PERMISSIONS_MULTIPLE_REQUEST = 123;
Check android version
private void checkAndroidVersion() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermission();
} else {
// write your logic here
}
}
check multiple permission code
private void checkPermission() {
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.READ_EXTERNAL_STORAGE) + ContextCompat
.checkSelfPermission(getActivity(),
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale
(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) ||
ActivityCompat.shouldShowRequestPermissionRationale
(getActivity(), Manifest.permission.CAMERA)) {
Snackbar.make(getActivity().findViewById(android.R.id.content),
"Please Grant Permissions to upload profile photo",
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
requestPermissions(
new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
PERMISSIONS_MULTIPLE_REQUEST);
}
}).show();
} else {
requestPermissions(
new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
PERMISSIONS_MULTIPLE_REQUEST);
}
} else {
// write your logic code if permission already granted
}
}
call back method after grant permission by user
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_MULTIPLE_REQUEST:
if (grantResults.length > 0) {
boolean cameraPermission = grantResults[1] == PackageManager.PERMISSION_GRANTED;
boolean readExternalFile = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if(cameraPermission && readExternalFile)
{
// write your logic here
} else {
Snackbar.make(getActivity().findViewById(android.R.id.content),
"Please Grant Permissions to upload profile photo",
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
requestPermissions(
new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
PERMISSIONS_MULTIPLE_REQUEST);
}
}).show();
}
}
break;
}
}
There is no hack available at this stage to circumvent asking for permissions from different groups together. That is the nature of how android has developed runtime permissions, to give users a choice of which permissions to accept. Of course not accepting all permissions required by an app, may make the app fail to work properly.
CAMERA and WRITE_EXTERNAL_STORAGE are both regarded as dangerous permissions, and in separate groups, thus both requiring a runtime permission request.
Once permission is granted for a particular group, it does not need to be requested again for the lifetime of the app run, or until it is revoked if given as a default setting.
The only thing you can do is ask the user to accept the decisions as default, which can be revoked, by using "never ask again"
I had the same issue and stumbled on this library.
Basically you can ask for multiple permissions sequentially, plus you can add listeners to popup a snackbar if the user denies your permission.
For multiple permission you can use this code :
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
private void insertDummyContactWrapper() {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add("GPS");
if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
permissionsNeeded.add("Read Contacts");
if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
permissionsNeeded.add("Write Contacts");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "You need to grant access to " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}
insertDummyContact();
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
Here i have a simple solution, - (Multiple permission checking)
String[] permissions = new String[]{
Manifest.permission.WRITE_CALL_LOG,
Manifest.permission.READ_CALL_LOG,
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS}; // Here i used multiple permission check
Then call it in Oncreate
if (checkPermissions()) { // permissions granted.
getCallDetails();
}
Finally, copy the below code
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(getApplicationContext(), p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MULTIPLE_PERMISSIONS: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permissions granted.
getCallDetails(); // Now you call here what ever you want :)
} else {
String perStr = "";
for (String per : permissions) {
perStr += "\n" + per;
} // permissions list of don't granted permission
}
return;
}
}
}
As said earlier, currently every permission group has own permission dialog which must be called separately.
You will have different dialog boxes for each permission group but you can surely check the result together in onRequestPermissionsResult() callback method.
Here is a working example link, may be useful for someone.
I faced the same problem and below is the workaround I came up with:
public boolean checkForPermission(final String[] permissions, final int permRequestCode, int msgResourceId) {
final List<String> permissionsNeeded = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
final String perm = permissions[i];
if (ContextCompat.checkSelfPermission(getActivity(), permissions[i]) != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(permissions[i])) {
final AlertDialog dialog = AlertDialog.newInstance( getResources().getString(R.string.permission_title), getResources().getString(msgResourceId) );
dialog.setPositiveButton("OK", new View.OnClickListener() {
#Override
public void onClick(View view) {
// add the request.
permissionsNeeded.add(perm);
dialog.dismiss();
}
});
dialog.show( getActivity().getSupportFragmentManager(), "HCFAlertDialog" );
} else {
// add the request.
permissionsNeeded.add(perm);
}
}
}
if (permissionsNeeded.size() > 0) {
// go ahead and request permissions
requestPermissions(permissionsNeeded.toArray(new String[permissionsNeeded.size()]), permRequestCode);
return false;
} else {
// no permission need to be asked so all good...we have them all.
return true;
}
}
And you call the above method like this:
if ( checkForPermission( new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA}, REQUEST_PERMISSION_EXTERNAL_STORAGE_RESULT, R.string.permission_image) ) {
// DO YOUR STUFF
}
check More than one Permission and Request if Not Granted
public void checkPermissions(){
if(ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.CAMERA)==PackageManager.PERMISSION_GRANTED){
//Do_SOme_Operation();
}else{
requestStoragePermission();
}
}
public void requestStoragePermission(){
ActivityCompat.requestPermissions(this
,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA},1234);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case 1234:if(grantResults[0]==PackageManager.PERMISSION_GRANTED && grantResults[1]==PackageManager.PERMISSION_GRANTED){
// Do_SOme_Operation();
}
default:super.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
}
// **For multiple permission you can use this code :**
// **First:**
//Write down in onCreate method.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST);
}
//**Second:**
//Write down in a activity.
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
progressBar.setVisibility(View.GONE);
Intent i = new Intent(SplashActivity.this,
HomeActivity.class);
startActivity(i);
finish();
}
}, SPLASH_DISPLAY_LENGTH);
} else {
finish();
}
return;
}
}
Based on what i've searched, i think this is the best answers that i've found out Android 6.0 multiple permissions
Adding generic code for different types of permissions. Copy-paste with minor changes. Read the "TODO" comments in the code below.
Make the following Activity your Launcher Activity:
public class PermissionReqActivity extends AppCompatActivity {
private static final int CODE_WRITE_SETTINGS_PERMISSION = 332;
private static String[] PERMISSIONS_ALL = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; //TODO You can Add multiple permissions here.
private static final int PERMISSION_REQUEST_CODE = 223;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_permission_req);
context = this;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean allPermissionsGranted = true;
ArrayList<String> toReqPermissions = new ArrayList<>();
for (String permission : PERMISSIONS_ALL) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
toReqPermissions.add(permission);
allPermissionsGranted = false;
}
}
if (allPermissionsGranted)
//TODO Now some permissions are very special and require Settings Activity to launch, as u might have seen in some apps. handleWriteSettingsPermission() is an example for WRITE_SETTINGS permission. If u don't need very special permission(s), replace handleWriteSettingsPermission() with initActivity().
handleWriteSettingsPermission();
else
ActivityCompat.requestPermissions(this,
toReqPermissions.toArray(new String[toReqPermissions.size()]), PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
boolean allPermGranted = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permissions not granted: " + permissions[i], Toast.LENGTH_LONG).show();
allPermGranted = false;
finish();
break;
}
}
if (allPermGranted)
handleWriteSettingsPermission();//TODO As mentioned above, use initActivity() here if u dont need very special permission WRITE_SETTINGS
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private void handleWriteSettingsPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.System.canWrite(context)) {
initActivity();
} else {
Toast.makeText(this, "Please Enable this permission for " +
getApplicationInfo().loadLabel(getPackageManager()).toString(), Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + context.getPackageName()));
startActivityForResult(intent, CODE_WRITE_SETTINGS_PERMISSION);
}
}
}
//TODO You don't need the following onActivityResult() function if u dont need very special permissions.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && requestCode == CODE_WRITE_SETTINGS_PERMISSION) {
if (Settings.System.canWrite(this))
initActivity();
else {
Toast.makeText(this, "Permissions not granted: " + Manifest.permission.WRITE_SETTINGS, Toast.LENGTH_LONG).show();
finish();
}
}
}
private void initActivity() {
startActivity(new Intent(this, MainActivity.class));
}
}
Based on vedval i have this solution.
public boolean checkForPermission(final String[] permissions, final int permRequestCode) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
final List<String> permissionsNeeded = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
final String perm = permissions[i];
if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(permissions[i])) {
Snackbar.make(phrase, R.string.permission_location, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
#Override
#TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
permissionsNeeded.add(perm);
}
});
} else {
// add the request.
permissionsNeeded.add(perm);
}
}
}
if (permissionsNeeded.size() > 0) {
// go ahead and request permissions
requestPermissions(permissionsNeeded.toArray(new String[permissionsNeeded.size()]), permRequestCode);
return false;
} else {
// no permission need to be asked so all good...we have them all.
return true;
}
}
/**
* Callback received when a permissions request has been completed.
*/
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_LOCATION) {
int i = 0;
for (String permission : permissions ){
if ( permission.equals(Manifest.permission.ACCESS_FINE_LOCATION) && grantResults.length > 0 && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
initLocationManager();
}
i++;
}
}
}
I am late, but i want tell the library which i have ended with.
RxPermission is best library with reactive code, which makes permission code unexpected just 1 line.
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.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'
}
you should use the dependency named dexter as given below:
https://github.com/Karumi/Dexter
by this you can get one or many permission easily:
this is the given code
Dexter.withContext(this).
withPermissions(Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport
multiplePermissionsReport) {
displaySong();
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> list,
PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).check();
For Asking Multiple Permission At Once You Can Use this Method link
compile 'com.kishan.askpermission:askpermission:1.0.3'
If you got conflicting in support library then
compile('com.kishan.askpermission:askpermission:1.0.3', {
exclude group: 'com.android.support'
})
Now ask for Permission
new AskPermission.Builder(this)
.setPermissions(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.setCallback(/* PermissionCallback */)
.setErrorCallback(/* ErrorCallback */)
.request(/* Request Code */);
permission granted callback
public void onPermissionsGranted(int requestCode) {
// your code }
permission denied callback
public void onPermissionsDenied(int requestCode) {
// your code}
ErrorCallbacks
public void onShowRationalDialog(PermissionInterface permissionInterface, int requestCode) {
// Alert user by Dialog or any other layout that you want.
// When user press OK you must need to call below method.
permissionInterface.onDialogShown();
}
public void onShowSettings(PermissionInterface permissionInterface, int requestCode) {
// Alert user by Dialog or any other layout that you want.
// When user press OK you must need to call below method.
// It will open setting screen.
permissionInterface.onSettingsShown();
}
I am currently working on an application that requires several "dangerous" permissions. So I tried adding "ask for permission" as required in Android Marshmallow(API Level 23), but couldn't find how to do it.
How can I ask for permission using new permission model in my app?
Open a Dialog using the code below:
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);
Get the Activity result as below:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// 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.
Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
More info: https://developer.android.com/training/permissions/requesting.html
This structure I am using to check if my app has permission and than request if it does not have permission. So in my main code from where i want to check write following :
int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (!checkIfAlreadyhavePermission()) {
requestForSpecificPermission();
}
}
Module checkIfAlreadyhavePermission() is implemented as :
private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
Module requestForSpecificPermission() is implemented as :
private void requestForSpecificPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.GET_ACCOUNTS, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
}
and Override in Activity :
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 101:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//granted
} else {
//not granted
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Refer this link for more details : http://revisitingandroid.blogspot.in/2017/01/how-to-check-and-request-for-run-time.html
Starting in Android Marshmallow, we need to request the user for specific permissions. We can also check through code if the permission is already given. Here is a list of commonly needed permissions:
android.permission_group.CALENDAR
android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR
android.permission_group.CAMERA
android.permission.CAMERA
android.permission_group.CONTACTS
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS
android.permission_group.LOCATION
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
android.permission_group.MICROPHONE
android.permission.RECORD_AUDIO
android.permission_group.PHONE
android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
android.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS
android.permission_group.SENSORS
android.permission.BODY_SENSORS
android.permission_group.SMS
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
android.permission.READ_CELL_BROADCASTS
android.permission_group.STORAGE
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
Here is sample code to check for permissions:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.WRITE_CALENDAR)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setMessage("Write calendar permission is necessary to write event!!!");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
});
} else {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
}
I have used this wrapper (Recommended) written by google developers. Its super easy to use.
https://github.com/googlesamples/easypermissions
Function dealing with checking and ask for permission if required
public void locationAndContactsTask() {
String[] perms = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS };
if (EasyPermissions.hasPermissions(this, perms)) {
// Have permissions, do the thing!
Toast.makeText(this, "TODO: Location and Contacts things", Toast.LENGTH_LONG).show();
} else {
// Ask for both permissions
EasyPermissions.requestPermissions(this, getString(R.string.rationale_location_contacts),
RC_LOCATION_CONTACTS_PERM, perms);
}
}
Happy coding :)
My class for request runtime permissions in Activity or Fragment
It also help you show rationale or open Setting to enable permission after user denied a permission (with/without Never ask again) option easier
class RequestPermissionHandler(private val activity: Activity? = null,
private val fragment: Fragment? = null,
private val permissions: Set<String> = hashSetOf(),
private val listener: Listener? = null
) {
private var hadShowRationale: Boolean = false
fun requestPermission() {
hadShowRationale = showRationaleIfNeed()
if (!hadShowRationale) {
doRequestPermission(permissions)
}
}
fun retryRequestDeniedPermission() {
doRequestPermission(permissions)
}
private fun showRationaleIfNeed(): Boolean {
val unGrantedPermissions = getPermission(permissions, Status.UN_GRANTED)
val permanentDeniedPermissions = getPermission(unGrantedPermissions, Status.PERMANENT_DENIED)
if (permanentDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowSettingRationale(unGrantedPermissions)
if (consume != null && consume) {
return true
}
}
val temporaryDeniedPermissions = getPermission(unGrantedPermissions, Status.TEMPORARY_DENIED)
if (temporaryDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowPermissionRationale(temporaryDeniedPermissions)
if (consume != null && consume) {
return true
}
}
return false
}
fun requestPermissionInSetting() {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val packageName = activity?.packageName ?: run {
fragment?.requireActivity()?.packageName
}
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
activity?.apply {
startActivityForResult(intent, REQUEST_CODE)
} ?: run {
fragment?.startActivityForResult(intent, REQUEST_CODE)
}
}
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_CODE) {
for (i in grantResults.indices) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
markNeverAskAgainPermission(permissions[i], false)
} else if (!shouldShowRequestPermissionRationale(permissions[i])) {
markNeverAskAgainPermission(permissions[i], true)
}
}
var hasShowRationale = false
if (!hadShowRationale) {
hasShowRationale = showRationaleIfNeed()
}
if (hadShowRationale || !hasShowRationale) {
notifyComplete()
}
}
}
fun onActivityResult(requestCode: Int) {
if (requestCode == REQUEST_CODE) {
getPermission(permissions, Status.GRANTED).forEach {
markNeverAskAgainPermission(it, false)
}
notifyComplete()
}
}
fun cancel() {
notifyComplete()
}
private fun doRequestPermission(permissions: Set<String>) {
activity?.let {
ActivityCompat.requestPermissions(it, permissions.toTypedArray(), REQUEST_CODE)
} ?: run {
fragment?.requestPermissions(permissions.toTypedArray(), REQUEST_CODE)
}
}
private fun getPermission(permissions: Set<String>, status: Status): Set<String> {
val targetPermissions = HashSet<String>()
for (p in permissions) {
when (status) {
Status.GRANTED -> {
if (isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
Status.TEMPORARY_DENIED -> {
if (shouldShowRequestPermissionRationale(p)) {
targetPermissions.add(p)
}
}
Status.PERMANENT_DENIED -> {
if (isNeverAskAgainPermission(p)) {
targetPermissions.add(p)
}
}
Status.UN_GRANTED -> {
if (!isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
}
}
return targetPermissions
}
private fun isPermissionGranted(permission: String): Boolean {
return activity?.let {
ActivityCompat.checkSelfPermission(it, permission) == PackageManager.PERMISSION_GRANTED
} ?: run {
ActivityCompat.checkSelfPermission(fragment!!.requireActivity(), permission) == PackageManager.PERMISSION_GRANTED
}
}
private fun shouldShowRequestPermissionRationale(permission: String): Boolean {
return activity?.let {
ActivityCompat.shouldShowRequestPermissionRationale(it, permission)
} ?: run {
ActivityCompat.shouldShowRequestPermissionRationale(fragment!!.requireActivity(), permission)
}
}
private fun notifyComplete() {
listener?.onComplete(getPermission(permissions, Status.GRANTED), getPermission(permissions, Status.UN_GRANTED))
}
private fun getPrefs(context: Context): SharedPreferences {
return context.getSharedPreferences("SHARED_PREFS_RUNTIME_PERMISSION", Context.MODE_PRIVATE)
}
private fun isNeverAskAgainPermission(permission: String): Boolean {
return getPrefs(requireContext()).getBoolean(permission, false)
}
private fun markNeverAskAgainPermission(permission: String, value: Boolean) {
getPrefs(requireContext()).edit().putBoolean(permission, value).apply()
}
private fun requireContext(): Context {
return fragment?.requireContext() ?: run {
activity!!
}
}
enum class Status {
GRANTED, UN_GRANTED, TEMPORARY_DENIED, PERMANENT_DENIED
}
interface Listener {
fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>)
fun onShowPermissionRationale(permissions: Set<String>): Boolean
fun onShowSettingRationale(permissions: Set<String>): Boolean
}
companion object {
const val REQUEST_CODE = 200
}
}
Using in Activity like
class MainActivity : AppCompatActivity() {
private lateinit var smsAndStoragePermissionHandler: RequestPermissionHandler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
smsAndStoragePermissionHandler = RequestPermissionHandler(this#MainActivity,
permissions = setOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_EXTERNAL_STORAGE),
listener = object : RequestPermissionHandler.Listener {
override fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>) {
Toast.makeText(this#MainActivity, "complete", Toast.LENGTH_SHORT).show()
text_granted.text = "Granted: " + grantedPermissions.toString()
text_denied.text = "Denied: " + deniedPermissions.toString()
}
override fun onShowPermissionRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this#MainActivity).setMessage("To able to Send Photo, we need SMS and" + " Storage permission")
.setPositiveButton("OK") { _, _ ->
smsAndStoragePermissionHandler.retryRequestDeniedPermission()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.dismiss()
}
.show()
return true // don't want to show any rationale, just return false here
}
override fun onShowSettingRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this#MainActivity).setMessage("Go Settings -> Permission. " + "Make SMS on and Storage on")
.setPositiveButton("Settings") { _, _ ->
smsAndStoragePermissionHandler.requestPermissionInSetting()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.cancel()
}
.show()
return true
}
})
button_request.setOnClickListener { handleRequestPermission() }
}
private fun handleRequestPermission() {
smsAndStoragePermissionHandler.requestPermission()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
smsAndStoragePermissionHandler.onRequestPermissionsResult(requestCode, permissions,
grantResults)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
smsAndStoragePermissionHandler.onActivityResult(requestCode)
}
}
Code on Github
Demo
Android-M ie, API 23 introduced Runtime Permissions for reducing security flaws in android device, where users can now directly manage app permissions at runtime.so if the user denies a particular permission of your application you have to obtain it by asking the permission dialog that you mentioned in your query.
So check before action ie, check you have permission to access the resource link and if your application doesn't have that particular permission you can request the permission link and handle the the permissions request response like below.
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// 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
}
}
So finally, It's a good practice to go through behavior changes if you are planning to work with new versions to avoid force closes :)
Permissions Best Practices.
You can go through the official sample app here.
Add the permissions to the AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application ...>
....
</application>
To check the Android version if it needs runtime permission or not.
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
}
Ask the user to grant the permission if not granted.
private void askForPermission(String permission, int requestCode) {
if (ContextCompat.checkSelfPermission(c, permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
Toast.makeText(c, "Please grant the requested permission to get your task done!", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
} else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
}
}
}
Do something if the permission was granted or not.
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission with request code 1 granted
Toast.makeText(this, "Permission Granted" , Toast.LENGTH_LONG).show();
} else {
//permission with request code 1 was not granted
Toast.makeText(this, "Permission was not Granted" , Toast.LENGTH_LONG).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
From Android Marshmallow(API 23) and above by default all dangerous permission ( as per official doc official doc) disabled. After installation when app open first time then you have to grant permission at Run Time.
I achieved this following way:
public class MarshMallowPermission {
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_GALLERY = 0;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_CAMERA = 1;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE = 2;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 3;
public static final int LOCATION_PERMISSION_REQUEST_CODE = 4;
Activity activity;
Context mContext;
public MarshMallowPermission(Activity activity) {
this.activity = activity;
this.mContext = activity;
}
public boolean checkPermissionForExternalStorage(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkPermissionForCamera(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkLocationPermission(){
int result = ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public void requestPermissionForExternalStorage(int requestCode){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(mContext.getApplicationContext(), "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
}
}
public void requestPermissionForCamera(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
Toast.makeText(mContext.getApplicationContext(), "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
}
}
public void requestPermissionForLocation(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_COARSE_LOCATION)){
Toast.makeText(mContext.getApplicationContext(), "Location permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
}
}
}
IN Your activity class:
public class MainActivity extends AppCompatActivity{
private MarshMallowPermission marshMallowPermission;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d("NavHome", "Oncreate_nav");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
marshMallowPermission = new MarshMallowPermission(MainActivity.this);
if (!marshMallowPermission.checkPermissionForExternalStorage()) {
marshMallowPermission.requestPermissionForExternalStorage(MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission granted successfully
} else {
//permission denied
}
break;
}
}
}
I'm using this as a base Fragment class. I only ask for permissions from a fragment, but you could refactor it and make a similar Activity version.
public class BaseFragment extends Fragment {
private static final int PERMISSION_REQUEST_BLOCK_INTERNAL = 555;
private static final String PERMISSION_SHARED_PREFERENCES = "permissions";
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_BLOCK_INTERNAL) {
boolean allPermissionsGranted = true;
for (int iGranting : grantResults) {
if (iGranting != PermissionChecker.PERMISSION_GRANTED) {
allPermissionsGranted = false;
break;
}
}
if (allPermissionsGranted && permissionBlock != null) {
permissionBlock.run();
}
permissionBlock = null;
}
}
public void runNowOrAskForPermissionsFirst(String permission, Runnable block) {
if (hasPermission(permission)) {
block.run();
} else if (!hasPermissionOrWillAsk(permission)) {
permissionBlock = block;
askForPermission(permission, PERMISSION_REQUEST_BLOCK_INTERNAL);
}
}
public boolean hasPermissionOrWillAsk(String permission) {
boolean hasPermission = hasPermission(permission);
boolean hasAsked = hasPreviouslyAskedForPermission(permission);
boolean shouldExplain = shouldShowRequestPermissionRationale(permission);
return hasPermission || (hasAsked && !shouldExplain);
}
private boolean hasPermission(String permission) {
return (ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED);
}
private boolean hasPreviouslyAskedForPermission(String permission) {
SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE);
return prefs.getBoolean(permission, false);
}
private void askForPermission(String permission, int requestCode) {
SharedPreferences.Editor editor = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit();
editor.putBoolean(permission, true);
editor.apply();
requestPermissions(new String[] { permission }, requestCode);
}
}
There are two key methods you should use:
hasPermissionOrWillAsk - Use this to see if a permission has been asked for and denies by a user who doesn't want to be asked again. This is useful for disabling UI when the user has given their final answer about NOT wanting a feature.
runNowOrAskForPermissionsFirst - Use this to run some code that requires permissions. If the user has already granted permission, the code will run immediately. Otherwise, the code will run later if the user grants permission. Or not at all. It's nice because you specify the code in one place.
Here's an example:
mFragment.runNowOrAskForPermissionsFirst(Manifest.permission.ACCESS_FINE_LOCATION, new Runnable() {
#Override
public void run() {
...do something if we have permission...
}
});
Happy to get feedback on this. Not that this specific example is a little simplified in that you also need to check to see if Location Services are enabled on the device. (That's different than permissions.) Also, it only supports one permission at a time, but would be simple to modify if you need it to support more than one at a time.
To handle runtime permission google has provided a library project. You can check this from here https://github.com/googlesamples/easypermissions
EasyPermissions is installed by adding the following dependency to your build.gradle file:
dependencies {
compile 'pub.devrel:easypermissions:0.3.0'
}
To begin using EasyPermissions, have your Activity (or Fragment) override the onRequestPermissionsResult method:
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Some permissions have been granted
// ...
}
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Some permissions have been denied
// ...
}
}
Here you will get a working example how this library works
https://github.com/milon87/EasyPermission
It may be a cleaner way. Add all your permissions in an array like
private static final String[] INITIAL_PERMS={
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
};
private static final int INITIAL_REQUEST=1337;
Whatever your permision is create method for each permision
#RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessFineLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
#RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessCoarseLocation() {
return(hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION));
}
#RequiresApi(api = Build.VERSION_CODES.M)
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}
Call this method in onCreate
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(!canAccessCoarseLocation() || !canAccessFineLocation()){
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}
Now override onRequestPermissionsResult
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == INITIAL_REQUEST){
if (canAccessFineLocation() && canAccessCoarseLocation()) {
//call your method
}
else {
//show Toast or alert that this permissions is neccessary
}
}
}
If you're using AndroidX Activity 1.2.0 or AndroidX Fragment 1.3.0:
There are new Activity Result APIs that you can use to ask for permissions:
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
// Permission granted. Do the tasks.
}
}
launcher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
For multiple permission at a time you can use this. This work for me.. I got another solution. if you give your targetSdkVersion bellow 22 it works for me. and it behavior as like getting permission from manifest.xml. Tested and works for me.
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
private void insertDummyContactWrapper() {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add("GPS");
if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
permissionsNeeded.add("Read Contacts");
if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
permissionsNeeded.add("Write Contacts");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "You need to grant access to " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}
insertDummyContact();
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
{
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for ACCESS_FINE_LOCATION
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
// All Permissions Granted
insertDummyContact();
} else {
// Permission Denied
Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)
.show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
For more details. Check bellow link
https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en
There is a good library that can be used in case permissions need to be asked when permission is needed by a background service. Although a limitation of library is that it can not be used to just determine whether permissions are currently given to the app or not. It always asks the user if app doesn't already have them.
Do give it a try as it makes life simpler: Android Permissions
Try this
This is the simplest way to ask for permission in Marshmallow version.
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED&&ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
//TO do here if permission is granted by user
}
else
{
//ask for permission if user didnot given
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
requestPermissions(new String[]{Manifest.permission.CAMERA,Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
}
Note:- Don't forget to add this same permission in manifest file also
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Second Method
Code for checking the permission is granted or not?
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA}, 1);
And override the method
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// grantResult[0] means it will check for the first postion permission which is READ_EXTERNAL_STORAGE
// grantResult[1] means it will check for the Second postion permission which is CAMERA
Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(this, "Permission not Granted", Toast.LENGTH_SHORT).show();
return;
}
}
}
This code below works perfectly.I am explaining with the help of an example.
In my case i placed the permission checks separately in a util class and passed the specific permissions i need to check from the appropriate classes.This enabled to reuse the permission check util file in the whole application.
The below code part shows the function call.In this case am requesting android.Manifest.permission.READ_EXTERNAL_STORAGE permission.
//the below call is from a fragment
#OnClick(R.id.button)//butterknife implementation
public void attachPressed() {
if (PermissionUtils.hasThisPermission(getContext(), android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
onAttachPressed();
} else {
PermissionUtils.isPermissionRequestNeeded(getActivity(), this, android.Manifest.permission.READ_EXTERNAL_STORAGE, PermissionUtils.REQUEST_GROUP_STORAGE);
}
}
In the above case permission is checked if it is allowed the onAttachPressed(); function is called else we check request permission.
The below is the code present in the util class in my case PermissionUtils
public final class PermissionUtils {
public static final int REQUEST_GROUP_STORAGE = 1508;
private PermissionUtils() {
}
public static boolean hasThisPermission(Context context, String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}
public static boolean isPermissionRequestNeeded(Activity activity, Fragment fragment, String permission, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasThisPermission(activity, permission)) {
final String[] permissions = new String[]{permission};
if (fragment == null) {
activity.requestPermissions(permissions, requestCode);
} else {
fragment.requestPermissions(permissions, requestCode);
}
return true;
}
return false;
}
}
And after the request if you might want to call the function from onRequestPermissionsResult or else you will need to press the button again for the function call.
So just call it from onRequestPermissionsResult
//the below call is from a fragment
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PermissionUtils.REQUEST_GROUP_STORAGE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onAttachPressed();
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
}
I use RxPermission library library for asking permission. Because it is long code which we have to write to ask permission.
RxPermissions rxPermissions = new RxPermissions(this); // where this is an Activity instance // Must be done during an initialization phase like onCreate
rxPermissions
.request(Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) { // Always true pre-M
// I can control the camera now
} else {
// Oups permission denied
}
});
Add these dependency 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'
}
I went through all answers, but doesn't satisfied my exact needed answer, so here is an example that I wrote and perfectly works, even user clicks the Don't ask again checkbox.
Create a method that will be called when you want to ask for runtime permission like readContacts() or you can also have openCamera() as shown below:
private void readContacts() {
if (!askContactsPermission()) {
return;
} else {
queryContacts();
} }
Now we need to make askContactsPermission(), you can also name it as askCameraPermission() or whatever permission you are going to ask.
private boolean askContactsPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
#Override
#TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
}
}).show();
} else if (contactPermissionNotGiven) {
openPermissionSettingDialog();
} else {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
contactPermissionNotGiven = true;
}
return false;
}
Before writing this function make sure you have defined the below instance variable as shown:
private View parentLayout;
private boolean contactPermissionNotGiven;;
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
Now final step to override the onRequestPermissionsResult method as shown below:
/**
* Callback received when a permissions request has been completed.
*/
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
queryContacts();
}
}
}
Here we are done with the RunTime permissions, the addon is the openPermissionSettingDialog() which simply open the Setting screen if user have permanently disable the permission by clicking Don't ask again checkbox. below is the method:
private void openPermissionSettingDialog() {
String message = getString(R.string.message_permission_disabled);
AlertDialog alertDialog =
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setMessage(message)
.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(true);
}
What we missed ?
1. Defining the used strings in strings.xml
<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
<string name="message_permission_disabled">You have disabled the permissions permanently,
To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
pressing OK you will be navigated to Settings screen</string>
Initializing the parentLayout variable inside onCreate method
parentLayout = findViewById(R.id.content);
Defining the required permission in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS" />
The queryContacts method, based on your need or the runtime permission you can call your method before which the permission was needed. in my case I simply use the loader to fetch the contact as shown below:
private void queryContacts() {
getLoaderManager().initLoader(0, null, this);}
This works great happy coding :)
Simple way to ask permission by avoiding writing lots of code,
https://github.com/sachinvarma/EasyPermission
How to add :
repositories {
maven { url "https://jitpack.io" }
}
implementation 'com.github.sachinvarma:EasyPermission:1.0.1'
How to ask permission:
List<String> permission = new ArrayList<>();
permission.add(EasyPermissionList.READ_EXTERNAL_STORAGE);
permission.add(EasyPermissionList.ACCESS_FINE_LOCATION);
new EasyPermissionInit(MainActivity.this, permission);
Hoping it will be helpful for someone.
I have found a solutions from my old code and it's really works good, still working on my Latest Apps.
Put it on MainActivity Class or on your Start Activity Class
private RequestPermissionHandler mRequestPermissionHandler;
On Create
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRequestPermissionHandler = new RequestPermissionHandler();
handleButtonClicked();
}
Private function handleButtonClicked()
private void handleButtonClicked() {
mRequestPermissionHandler.requestPermission(this, new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.WAKE_LOCK
}, 123, new RequestPermissionHandler.RequestPermissionListener() {
#Override
public void onSuccess() {
//Toast.makeText(MainActivity.this, "request permission success", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailed() {
Toast.makeText(MainActivity.this, "request permission failed", Toast.LENGTH_SHORT).show();
}
});
}
RequestPermissionHandler.java Class
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
public class RequestPermissionHandler {
private Activity mActivity;
private RequestPermissionListener mRequestPermissionListener;
private int mRequestCode;
public void requestPermission(Activity activity, #NonNull String[] permissions, int requestCode,
RequestPermissionListener listener) {
mActivity = activity;
mRequestCode = requestCode;
mRequestPermissionListener = listener;
if (!needRequestRuntimePermissions()) {
mRequestPermissionListener.onSuccess();
return;
}
requestUnGrantedPermissions(permissions, requestCode);
}
private boolean needRequestRuntimePermissions() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
private void requestUnGrantedPermissions(String[] permissions, int requestCode) {
String[] unGrantedPermissions = findUnGrantedPermissions(permissions);
if (unGrantedPermissions.length == 0) {
mRequestPermissionListener.onSuccess();
return;
}
ActivityCompat.requestPermissions(mActivity, unGrantedPermissions, requestCode);
}
private boolean isPermissionGranted(String permission) {
return ActivityCompat.checkSelfPermission(mActivity, permission)
== PackageManager.PERMISSION_GRANTED;
}
private String[] findUnGrantedPermissions(String[] permissions) {
List<String> unGrantedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (!isPermissionGranted(permission)) {
unGrantedPermissionList.add(permission);
}
}
return unGrantedPermissionList.toArray(new String[0]);
}
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == mRequestCode) {
if (grantResults.length > 0) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
mRequestPermissionListener.onFailed();
return;
}
}
mRequestPermissionListener.onSuccess();
} else {
mRequestPermissionListener.onFailed();
}
}
}
public interface RequestPermissionListener {
void onSuccess();
void onFailed();
}
}
if (CommonMethod.isNetworkAvailable(MainActivity.this)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.CAMERA);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
//showing dialog to select image
callFacebook();
Log.e("permission", "granted MarshMallow");
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1);
}
} else {
Log.e("permission", "Not Required Less than MarshMallow Version");
callFacebook();
}
} else {
CommonMethod.showAlert("Internet Connectivity Failure", MainActivity.this);
}
You can use my library — NoPermission (It's just one class)
compile 'ru.alexbykov:nopermission:1.1.1'
Sample
PermissionHelper permissionHelper = new PermissionHelper(this); //don't use getActivity in fragment!
permissionHelper.check(Manifest.permission.READ_CONTACTS)
.onSuccess(this::onSuccess)
.onDenied(this::onDenied)
.onNeverAskAgain(this::onNeverAskAgain)
.run();
onRequestPermissionResult:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults)
permissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
I think api more convenient than EasyPermissions by Google.
Runtime Permission AnyWhere In ApplicationHere is Example
use dependency
maven { url 'https://jitpack.io' }
dependencies {
implementation 'com.github.irshadsparky:PermissionLib:master-SNAPSHOT'
}
and call code like this :
PermissionHelper.requestCamera(new PermissionHelper.OnPermissionGrantedListener() {
#Override
public void onPermissionGranted() {
}
});
you can find more Github
Run time permission creates a lot of boilerplate code in activity which is heavily coupled. To reduce code and make the thing easy, you can use Dexter library.
RUNTIME PERMISSION IN ANDROID
private static final int PERMISSION_REQ_WRITE_EXTERNAL_STORAGE = 101;
public void onClick(View view) {
if (view.getId() == yourBtn.getId()) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
this.storageWork();
} else {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, PERMISSION_REQ_WRITE_EXTERNAL_STORAGE);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQ_WRITE_EXTERNAL_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
this.storageWork();
}
}
}
public void storageWork(){
}
OnClick method is to check runtime permission
and if Permission is restricted then it request permission
Just this will do:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_CONTACTS}, 0);
}
In Android M (Preview) the user can choose a specific app and retreive specific permission.
So I am asking How to check Grants Permissions at Run-Time?
Nice !!
I just found my need we can check if the permission is granted by :
checkSelfPermission(Manifest.permission.READ_CONTACTS)
Request permissions if necessary
if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant
return;
}
Handle the permissions request response
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! do the
// calendar task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'switch' lines to check for other
// permissions this app might request
}
}
Try this instead simple request code
https://www.learn2crack.com/2015/10/android-marshmallow-permissions.html
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
private boolean checkAndRequestPermissions() {
int camera = ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA);
int storage = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
int loc = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION);
int loc2 = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (camera != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.CAMERA);
}
if (storage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (loc2 != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
}
if (loc != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (!listPermissionsNeeded.isEmpty())
{
ActivityCompat.requestPermissions(this,listPermissionsNeeded.toArray
(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
Try this for Check Run-Time Permission:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkRunTimePermission();
}
Check run time permission:
private void checkRunTimePermission() {
String[] permissionArrays = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissionArrays, 11111);
} else {
// if already permition granted
// PUT YOUR ACTION (Like Open cemara etc..)
}
}
Handle Permission result:
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
boolean openActivityOnce = true;
boolean openDialogOnce = true;
if (requestCode == 11111) {
for (int i = 0; i < grantResults.length; i++) {
String permission = permissions[i];
isPermitted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
// user rejected the permission
boolean showRationale = shouldShowRequestPermissionRationale(permission);
if (!showRationale) {
//execute when 'never Ask Again' tick and permission dialog not show
} else {
if (openDialogOnce) {
alertView();
}
}
}
}
if (isPermitted)
if (isPermissionFromGallery)
openGalleryFragment();
}
}
Set custom alert:
private void alertView() {
AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity(), R.style.MyAlertDialogStyle);
dialog.setTitle("Permission Denied")
.setInverseBackgroundForced(true)
//.setIcon(R.drawable.ic_info_black_24dp)
.setMessage("Without those permission the app is unable to save your profile. App needs to save profile image in your external storage and also need to get profile image from camera or external storage.Are you sure you want to deny this permission?")
.setNegativeButton("I'M SURE", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
dialoginterface.dismiss();
}
})
.setPositiveButton("RE-TRY", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
dialoginterface.dismiss();
checkRunTimePermission();
}
}).show();
}
use Dexter library
Include the library in your build.gradle
dependencies{
implementation 'com.karumi:dexter:4.2.0'
}
this example requests WRITE_EXTERNAL_STORAGE.
Dexter.withActivity(this)
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse response) {
// permission is granted, open the camera
}
#Override
public void onPermissionDenied(PermissionDeniedResponse response) {
// check for permanent denial of permission
if (response.isPermanentlyDenied()) {
// navigate user to app settings
}
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
}
}).check();
check this answer here
fun hasPermission(permission: String): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true // must be granted after installed.
return mAppSet.appContext.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
}
You can also query by following code snippet as backward compatible;
int hasPermission = ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_CONTACTS);
if (hasPermission == PackageManager.PERMISSION_GRANTED) {
//Do smthng
}
For Location runtime Permission
ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, 1);
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("yes","yes");
} else {
Log.d("yes","no");
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
original (not mine) post here
For special permissions, such as android.Manifest.permission.PACKAGE_USAGE_STATS used AppOpsManager:
Kotlin
private fun hasPermission(permission:String, permissionAppOpsManager:String): Boolean {
var granted = false
if (VERSION.SDK_INT >= VERSION_CODES.M) {
// requires kitkat
val appOps = applicationContext!!.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
// requires lollipop
val mode = appOps.checkOpNoThrow(permissionAppOpsManager,
android.os.Process.myUid(), applicationContext!!.packageName)
if (mode == AppOpsManager.MODE_DEFAULT) {
granted = applicationContext!!.checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
} else {
granted = mode == AppOpsManager.MODE_ALLOWED
}
}
return granted
}
and anywhere in code:
val permissionAppOpsManager = AppOpsManager.OPSTR_GET_USAGE_STATS
val permission = android.Manifest.permission.PACKAGE_USAGE_STATS
val permissionActivity = Settings.ACTION_USAGE_ACCESS_SETTINGS
if (hasPermission(permission, permissionAppOpsManager)) {
Timber.i("has permission: $permission")
// do here what needs permission
} else {
Timber.e("has no permission: $permission")
// start activity to get permission
startActivity(Intent(permissionActivity))
}
Other permissions you can get with TedPermission library
Check out the below library in git :
RuntimePermission
Implementation :
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.manoj140220:RuntimePermission:1.0.3'
}
new RuntimePermission({Current Class Object}, String[] , {ActvityContext});
String[] : permission array.
example : String[] permissionArray = {Manifest.permission.CAMERA, Manifest.permission.BODY_SENSORS,...}
Implement : {PermissionNotify}
interface notifier methods.
#Override
public void notifyPermissionGrant() {
}
#Override
public void notifyPermissionDeny() {
}