How to run camera after permission accepted - java

I have fragment that contain method that running camera.
But , when user enter at the first time to the app and going to this fragment, I ask camera permission.
And after user Accept the permission to use camera, camera is not starting.
Only after he is exiting from this fragment and going back to it, the camera will run.
I need some listener for the permission accept i think.
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
cameraSource.start(surfaceView.getHolder());
} else {
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}
} catch (IOException e) {
e.printStackTrace();
}
}

You can implement a PermissionResult listener as:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
cameraSource.start(surfaceView.getHolder());
else
Toast.makeText(context,"Permission denied",Toast.LENGTH_LONG).show();
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
If you're asking for more than one permission, you can check it as:
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int grantResult = grantResults[i];
//Now check each permission as
if (permission.equals(Manifest.permission.CAMERA)) {
//do something like checking granted result
}
else if (permission.equals(Manifest.permission.LOCATION)) {
//do something
}
}

Related

App crashes when trying to set song as specific friend in android studio, app crashes at getContentresolver [duplicate]

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);
}

Android permissions UI issue with multiple dialogs

I'm trying to refactor a piece of code that deals with Android permissions. It works fine, except for one annoying UI bug that has caused me a lot of headaches. Here's the code:
private void getPermissions() {
if (Build.VERSION.SDK_INT >= 23) {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, android.Manifest.permission.ACCESS_COARSE_LOCATION))
permissionsNeeded.add(accessLocation);
if (!addPermission(permissionsList, Manifest.permission.CAMERA))
permissionsNeeded.add(accessCamera);
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
}
}
}
private void showMessageOK (int message, final String perm) {
if (shouldShowRequestPermissionRationale(perm)) {
new AlertDialog.Builder(CreateSessionActivity.this)
.setMessage(message)
.setTitle("Permission required")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
requestPermissions(new String[] {perm},
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
})
.create()
.show();
}
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
//check for rationale
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
Map<String, Integer> perms = new HashMap<>();
perms.put(android.Manifest.permission.ACCESS_COARSE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(android.Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
if (perms.get(accessLocation) != PackageManager.PERMISSION_GRANTED) {
showMessageOK(R.string.permdesc_access_location,
accessLocation);
}
if (perms.get(accessCamera) != PackageManager.PERMISSION_GRANTED) {
showMessageOK(R.string.permdesc_access_camera,
accessCamera);
}
}
It basically gets a list of permissions that are not already granted by the user, cycles through them and prompts the user to grant each. Once it's finished, it checks for any remaining permissions that have not been granted and prompts the user again with information on why that permission is required and the result of not allowing it, until he either accepts or chooses "do not ask again".
My problem occurs with the chained "if" statements in onRequestPermissionResult(). As you may guess, if multiple permission conditions are true, then each dialog opens underneath the current existing dialog. This results in a "jumping" dialog effect between one dialog closing and the next displaying. I've tried case and if/elseif statements to combat this, but it causes problems with the rest of my permission logic.
Does anyone have a clean solution for this? I would be grateful.
Well, this may not be the cleanest code but,
if (Build.VERSION.SDK_INT >= 23) {
List<String> permissionsNeeded = new ArrayList<String>();
for(int i=0; i<4;i++){
checkAndAsk(i);
}
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
}
}
//out of the get permissions method
public void checkAndAsk(int i){
switch(i){
case 0:
if (!addPermission(permissionsList, android.Manifest.permission.ACCESS_COARSE_LOCATION))
permissionsNeeded.add(accessLocation);
break;
case 1:
if (!addPermission(permissionsList, android.Manifest.permission.READ_CONTACTS))
permissionsNeeded.add(readContacts);
break;
//You get the idea
}
}
Basically you iterate through the permissions by passing a parameter of which permission you will ask for. Once a permission is granted/declined, it breaks, moving onto the second permission until all are done.
In theory this should work.
Just use this code :
private void RequestAllPermissions() {
String[] PERMISSIONS = {Manifest.permission.CAMERA, Manifest.permission.RECEIVE_SMS, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.INTERNET, Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_CONTACTS};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, REQUESTCODE_PERMISSION_ALL);
} else
}
public static boolean hasPermissions(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) {
return false;
}
}
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUESTCODE_PERMISSION_ALL: {
boolean allpermissiongranted = true;
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
allpermissiongranted = false;
break;
}
}
} else
allpermissiongranted = false;
if (allpermissiongranted) {
//do task
} else {
new SweetAlertDialog(mContext, SweetAlertDialog.WARNING_TYPE)
.setTitleText("Permission Not Granted")
.setContentText("Kindly grant all requested permission to proceed.")
.setConfirmText("Request")
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sDialog) {
sDialog.dismissWithAnimation();
RequestAllPermissions();
}
})
.setCancelText("Exit")
.setCancelClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sweetAlertDialog) {
sweetAlertDialog.dismissWithAnimation();
finish();
}
})
.show();
}
}
}
}

Java Android requestPermissions after click button

This is how I request permissions :
private boolean checkAndRequestPermissions() {
int permissionSendMessage = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
int phoneStatePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
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.READ_EXTERNAL_STORAGE);
}
if (cameraPermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CAMERA);
}
if (phoneStatePermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
I call this method after click button :
#OnClick(R.id.email_sign_in_button)
void loginButton() {
if(checkAndRequestPermissions()) {
attemptLogin();
}
}
But when a user confirm all permissions have to click one more time button. What I have to do that user do not click a button ?
You need to override the activity's onRequestPermissionsResult method, it will be called when the user accepts/rejects permissions. You can find more details HERE
Here is an example specific to your case:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if(requestCode == REQUEST_ID_MULTIPLE_PERMISSIONS && grantResults.length == listPermissionsNeeded.size()){
boolean allGranted = true;
for(int grantedResult : grantedResults){
if(grantedResult != PackageManager.PERMISSION_GRANTED){
allGranted = false;
}
}
if(allGranted){
attemptLogin();
}
}
}
Use RxPermissions: No need to again click on button after allow permissions
gradle
compile 'com.tbruyelle.rxpermissions:rxpermissions:0.7.0#aar'
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
code
RxPermissions.getInstance(this)
.request(REQUEST_PERMISSIONS)
.subscribe(new Action1<Boolean>() {
#Override
public void call(Boolean granted) {
if (granted) {
attemptLogin();
}
}
});
You can listen for the onRequestPermissionsResult in your Activity/Fragment.
As statet in the Documentation, you can implement this to check if the user has granted the requested permissions:
#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
}
}
Remember to alter the switch/case according to your needs. If the user has granted all permissions, just call attemptLogin() once again.

Android: Can't open existing file? [duplicate]

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);
}

Ask for runtime permission only for Android Marshmallow?

I want to add run time permission only for marshmallow because it crashes my application in Android marshmallow devices otherwise its working properly. Is it possible to add multiple permissions at a single time? I have written code for camera permission, but
I have written code for single permission and that is working fine.
private void requestpermissioncamera()
{
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_CAMERA)) permissionsNeeded.add("Camera");
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),PERMISSION_REQUEST_CODE);
return;
}
this function is used to check weather permission is granted or not.
private boolean checkPermission(){
int result = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
Of course it is. You can see an example of how it's implemented below:
public String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public boolean verifyStoragePermissions(Activity activity, int REQUEST_EXTERNAL_STORAGE) {
initialize(activity);
// Check if we have write permission
int permission =
ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
return false;
} else {
return true;
}
}
for my project i made Utils class with this method:
public static boolean checkAllAndRequestPermisions(Activity activity, int requestCode, LinkedList<String> permissionsList) {
LinkedList<String> needPermissions = new LinkedList<>();
for(String permission : permissionsList){
if (ContextCompat.checkSelfPermission(activity, permission) != activity.getPackageManager().PERMISSION_GRANTED){
needPermissions.add(permission);
}
}
if (!needPermissions.isEmpty()){
ActivityCompat.requestPermissions(activity, needPermissions.toArray(new String[needPermissions.size()]), requestCode);
}
return true;
}
And implement onRequestPermissinsResult interface like this:
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case Consts.SOME_PERMISSIONS_REQUEST_CODE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
Toast.makeText(getApplicationContext(), "Need permissions", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Its not perfect solution, but ok for first time, i hope its help.
Also dont forget, you can set in gradle targetSdkVersion less then 23 to have time for implement all requests permissions functionality.
It is easy to get multiple permissions at a single shot.
I hope below code can help you out for granting multiple permissions.
private void requestpermissioncamera()
{
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(!addPermission(permissionsList,Manifest.permission.CAMERA))
permissionsNeeded.add("Camera");
if(!addPermission(permissionsList, Manifest.permission.ACCESS_NOTIFICATION_POLICY))
permissionsNeeded.add("push Notification");
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;
}
#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);
perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_NOTIFICATION_POLICY, 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);
}

Categories

Resources