Last active
January 11, 2022 08:01
-
-
Save techyourchance/18f84ec1a04c82c32007b2b231277ca7 to your computer and use it in GitHub Desktop.
Abstraction for clean management of runtime permissions in Android applications
This file contains 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 enum MyPermission { | |
// declare runtime permissions specific to your app here (don't keep unused ones) | |
READ_PHONE_STATE(Manifest.permission.READ_PHONE_STATE), | |
FINE_LOCATION(Manifest.permission.ACCESS_FINE_LOCATION); | |
public static MyPermission fromAndroidPermission(String androidPermission) { | |
for (MyPermission permission : MyPermission.values()) { | |
if (permission.getAndroidPermission().equals(androidPermission)) { | |
return permission; | |
} | |
} | |
throw new RuntimeException("Android permission not supported yet: " + androidPermission); | |
} | |
private final String mAndroidPermission; | |
private MyPermission(String androidPermission) { | |
mAndroidPermission = androidPermission; | |
} | |
public String getAndroidPermission() { | |
return mAndroidPermission; | |
} | |
} |
This file contains 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
/** | |
* Instances of this class must be Activity-scoped. In other words, a single instance of | |
* this class MUST be shared among all the clients within the hierarchy of a single Activity. | |
* Read more here: https://www.techyourchance.com/runtime-permissions-android | |
*/ | |
@UiThread | |
public class PermissionsHelper extends Observable<PermissionsHelper.Listener> { | |
public interface Listener { | |
void onRequestPermissionsResult(int requestCode, PermissionsResult result); | |
void onPermissionsRequestCancelled(int requestCode); | |
} | |
public static class PermissionsResult { | |
public final List<MyPermission> granted; | |
public final List<MyPermission> denied; | |
public final List<MyPermission> deniedDoNotAskAgain; | |
public PermissionsResult(List<MyPermission> granted, List<MyPermission> denied, List<MyPermission> deniedDoNotAskAgain) { | |
this.granted = granted; | |
this.denied = denied; | |
this.deniedDoNotAskAgain = deniedDoNotAskAgain; | |
} | |
} | |
private final Activity mActivity; | |
public PermissionsHelper(Activity activity) { | |
mActivity = activity; | |
} | |
public boolean hasPermission(MyPermission permission) { | |
return ContextCompat.checkSelfPermission(mActivity, permission.getAndroidPermission()) == PackageManager.PERMISSION_GRANTED; | |
} | |
public boolean hasAllPermissions(MyPermission[] permissions) { | |
for (MyPermission permission : permissions) { | |
if (ContextCompat.checkSelfPermission(mActivity, permission.getAndroidPermission()) != PackageManager.PERMISSION_GRANTED) { | |
return false; | |
} | |
} | |
return true; | |
} | |
public void requestPermission(MyPermission permission, int requestCode) { | |
ActivityCompat.requestPermissions(mActivity, new String[] { permission.getAndroidPermission() }, requestCode); | |
} | |
public void requestAllPermissions(MyPermission[] permissions, int requestCode) { | |
String[] androidPermissions = new String[permissions.length]; | |
for (int i = 0; i < permissions.length; i++) { | |
androidPermissions[i] = permissions[i].getAndroidPermission(); | |
} | |
ActivityCompat.requestPermissions(mActivity, androidPermissions, requestCode); | |
} | |
public void onRequestPermissionsResult(int requestCode, @NonNull String[] androidPermissions, @NonNull int[] grantResults) { | |
if (androidPermissions.length == 0 || grantResults.length == 0) { | |
notifyPermissionsRequestCancelled(requestCode); | |
} | |
List<MyPermission> grantedPermissions = new LinkedList<>(); | |
List<MyPermission> deniedPermissions = new LinkedList<>(); | |
List<MyPermission> deniedAndDoNotAskAgainPermissions = new LinkedList<>(); | |
String androidPermission; | |
MyPermission permission; | |
for (int i = 0; i < androidPermissions.length; i++) { | |
androidPermission = androidPermissions[i]; | |
permission = MyPermission.fromAndroidPermission(androidPermission); | |
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { | |
grantedPermissions.add(permission); | |
} else if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, androidPermission)) { | |
deniedPermissions.add(permission); | |
} else { | |
deniedAndDoNotAskAgainPermissions.add(permission); | |
} | |
} | |
PermissionsResult result = new PermissionsResult(grantedPermissions, deniedPermissions, deniedAndDoNotAskAgainPermissions); | |
notifyPermissionsResult(requestCode, result); | |
} | |
private void notifyPermissionsResult(int requestCode, PermissionsResult permissionsResult) { | |
for (Listener listener : getListeners()) { | |
listener.onRequestPermissionsResult(requestCode, permissionsResult); | |
} | |
} | |
private void notifyPermissionsRequestCancelled(int requestCode) { | |
for (Listener listener : getListeners()) { | |
listener.onPermissionsRequestCancelled(requestCode); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment