Last active
February 8, 2019 13:13
-
-
Save crysxd/385b57d74045a8bd67c4110c34ab74aa to your computer and use it in GitHub Desktop.
Requesting Android M 6.0 permission with couple of lines
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
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
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!