Skip to content

Instantly share code, notes, and snippets.

@crysxd
Last active February 8, 2019 13:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save crysxd/385b57d74045a8bd67c4110c34ab74aa to your computer and use it in GitHub Desktop.
Save crysxd/385b57d74045a8bd67c4110c34ab74aa to your computer and use it in GitHub Desktop.
Requesting Android M 6.0 permission with couple of lines
...
public class ExampleActivity extends AppCompatActivity {
public void onClick(View v) {
// This example shows how to request CALL_PHONE and READ_CALENDAR and do some stuff with the permissions
// The user will only be prompted for the permissions he not yet has granted
new PermissionRequestManager()
// We need a AppCompatActivity here, if you are not using support libraries you will have to slightly change
// the PermissionReuqestManager class
.withActivity(this)
// List all permissions you need
.withPermissions(android.Manifest.permission.CALL_PHONE, android.Manifest.permission.READ_CALENDAR)
// This Runnable is called whenever the request was successfull
.withSuccessHandler(new Runnable() {
@Override
public void run() {
// Do something with your permissions!
// This is called after the user has granted all permissions
}
})
// Optional, called when the user did not grant all permissions
.withFailureHandler(new Runnable() {
@Override
public void run() {
// This is called if the user has rejected one or all of the requested permissions
L.e(this.getClass().getSimpleName(), "Unable to request permission");
}
})
// After calling this, the user is prompted to grant the rights
.request();
}
}
package de.crys.example;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* A special fragment which coordinates the request of a permission.
*/
public class PermissionRequestManager extends Fragment {
/**
* The success handler called on success
*/
private Runnable mSuccessHandler = new Runnable() {
@Override
public void run() {
// Nothing to do
}
};
/**
* The failure handler called on failure
*/
private Runnable mFailureHandler = new Runnable() {
@Override
public void run() {
// Nothing to do
}
};
/**
* The permissions which need to be requested
*/
private String[] mPermissions = new String[0];
/**
* The request code of the request
*/
private int mRequestCode;
/**
* Flag inidcating if the request was performed before the fragment was ready
*/
private boolean mRequestRequired = false;
/**
* Sets the {@link SdActivity} which is hosting this fragment
* @param a the {@link SdActivity}
* @return this instance
*/
public SdPermissionRequestManager withActivity(@NonNull AppCompatActivity a) {
a.getSupportFragmentManager().beginTransaction().add(this, UUID.randomUUID().toString()).commit();
return this;
}
/**
* Sets the required permissions
* @param permission the required permissions
* @return this instance
*/
public SdPermissionRequestManager withPermissions(@NonNull String... permission) {
this.mPermissions = permission;
return this;
}
/**
* The {@link Runnable} which is run after the permissions where successfully requested
* @param runnable the {@link Runnable}
* @return this instance
*/
public SdPermissionRequestManager withSuccessHandler(@NonNull Runnable runnable) {
this.mSuccessHandler = runnable;
return this;
}
/**
* The {@link Runnable} which is run if the permissions could not be requested
* @param runnable the {@link Runnable}
* @return this instance
*/
public SdPermissionRequestManager withFailureHandler(@NonNull Runnable runnable) {
this.mFailureHandler = runnable;
return this;
}
/**
* Starts the request process for the permissions
* @return this instance
*/
public SdPermissionRequestManager request() {
// If we are attached to activity
if(this.getActivity() != null) {
// Clear flag
this.mRequestRequired = false;
// If we are on M or above
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Iterate over all required permissions and sort those out we already have
List<String> neededPermissions = new ArrayList<>();
for(String permission : this.mPermissions) {
if(ContextCompat.checkSelfPermission(this.getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
neededPermissions.add(permission);
}
}
// If there are some permissions we need but which are not granted, request those
if(neededPermissions.size() > 0) {
this.mRequestCode = (int) (Math.random() * 32000);
this.requestPermissions(neededPermissions.toArray(this.mPermissions), this.mRequestCode);
}
// If we have all needed permissions, run the success handler
else {
this.runSuccessHandler();
}
}
// If we are on Lollipop or below, just run the success handler, no pemrission
// request needed
else {
this.runSuccessHandler();
}
}
// If we are not attached, set flag so this method will be called as soon as we are attached
else {
this.mRequestRequired = true;
}
return this;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(this.mRequestRequired) {
this.request();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// If the correct request is completed
if(this.mRequestCode == requestCode) {
// Check if all where granted
boolean allGranted = this.mPermissions.length == permissions.length;
for(int result : grantResults) {
allGranted &= result == PackageManager.PERMISSION_GRANTED;
}
// Run success or failure handler
if (allGranted) {
this.runSuccessHandler();
} else {
this.runFailureHandler();
}
// Remove fragment
new Handler().post(new Runnable() {
@Override
public void run() {
getActivity()
.getSupportFragmentManager()
.beginTransaction()
.remove(PermissionRequestManager.this)
.commitAllowingStateLoss();
}
});
}
}
/**
* Runs the success handler
*/
private void runSuccessHandler() {
try {
this.mSuccessHandler.run();
} catch(Exception e) {
Log.e(this.getClass().getSimpleName(), "Unable to run success handler", e);
}
}
/**
* Runs the failure handler
*/
private void runFailureHandler() {
try {
this.mFailureHandler.run();
} catch(Exception e) {
Log.e(this.getClass().getSimpleName(), "Unable to run success handler", e);
}
}
}
@crysxd
Copy link
Author

crysxd commented Jul 24, 2016

A simple class wrapping up the code you need to request permissions with android Marshmallow (6.0) and above. The code is backward compatible to Lollipop (5.0) and below.

Have fun!

@hartviqb
Copy link

Hi cryxsd, i like you code, is very helpfully for me.
But i have a problem with your code. The first time popup permission it's OK, but if i choose button Deny on popup, and then i reload myActivity, myActivity be crash. that is the problem.
Solution:
I think the problem there is on your PermissionRequestManager class Line 129

this.requestPermissions(neededPermissions.toArray(this.mPermissions), this.mRequestCode);

Just change to

this.requestPermissions(neededPermissions.toArray(new String[0]), this.mRequestCode);

I had been implement in my code, and it work. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment