permissions with Rx 1
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import com.ntrlab.velocityvue.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
public class PermissionRetriever {
private final static String LOG_TAG = LogUtils.makeLogTag(PermissionRetriever.class);
private final static int REQUEST_PERMISSIONS_CODE = 999;
private Runnable mPendingIfGrantedAction;
private Runnable mPendingIfUnacceptedAction;
private Fragment mFragment;
private Activity mActivity;
private final Map<String, String> mPermissionsRationalesMap = new HashMap<>();
@Inject
public PermissionRetriever() {
}
public static boolean hasPermission(Activity activity, String permission) {
return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
}
public static boolean hasPermissions(Activity activity, String... permissions) {
boolean granted = true;
for (String permission : permissions) {
granted &= hasPermission(activity, permission);
}
return granted;
}
public static boolean hasPermission(Fragment fragment, String permission) {
return hasPermission(fragment.getActivity(), permission);
}
public static boolean hasPermissions(Fragment fragment, String... permissions) {
return hasPermissions(fragment.getActivity(), permissions);
}
public PermissionRetriever withPermission(String permission) {
mPermissionsRationalesMap.put(permission, "");
return this;
}
public PermissionRetriever withPermission(String permission, String explanation) {
mPermissionsRationalesMap.put(permission, explanation);
return this;
}
public void runIfGranted(Activity activity, Runnable runnable) {
runIfGrantedAndIfUnaccepted(activity, runnable, null);
}
public void runIfGranted(Fragment fragment, Runnable runnable) {
runIfGrantedAndIfUnaccepted(fragment, runnable, null);
}
public void grant(Activity activity) {
runIfGrantedAndIfUnaccepted(activity, null, null);
}
public void grant(Fragment fragment) {
runIfGrantedAndIfUnaccepted(fragment, null, null);
}
public void runIfGrantedAndIfUnaccepted(Activity activity, Runnable ifGranted, Runnable ifUnaccepted) {
mActivity = activity;
mPendingIfGrantedAction = ifGranted;
mPendingIfUnacceptedAction = ifUnaccepted;
checkAndRun();
}
public void runIfGrantedAndIfUnaccepted(Fragment fragment, Runnable ifGranted, Runnable ifUnaccepted) {
mFragment = fragment;
mPendingIfGrantedAction = ifGranted;
mPendingIfUnacceptedAction = ifUnaccepted;
checkAndRun();
}
public void onPermissionResult(int requestCode) {
if (getContext() != null && requestCode == REQUEST_PERMISSIONS_CODE) {
if (isAllGranted()) {
runGranted();
} else {
if (shouldShowRationale()) {
showRationaleToRequest();
} else {
showRationaleToSettings();
}
}
}
}
private void checkAndRun() {
if (getContext() != null) {
if (isAllGranted()) {
runGranted();
} else {
request();
}
} else {
LogUtils.e(LOG_TAG, "Context is null. I'm gonna do nothing!!!");
}
}
private boolean isAllGranted() {
boolean allGranted = true;
if (!mPermissionsRationalesMap.isEmpty()) {
List<Map.Entry<String, String>> granted = new ArrayList<>();
for (Map.Entry<String, String> entry : mPermissionsRationalesMap.entrySet()) {
if (permissionGranted(entry.getKey())) {
granted.add(entry);
} else {
allGranted = false;
}
}
mPermissionsRationalesMap.entrySet().removeAll(granted);
}
return allGranted;
}
private boolean permissionGranted(String permission) {
return ActivityCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED;
}
private void runGranted() {
if (mPendingIfGrantedAction != null) {
mPendingIfGrantedAction.run();
}
}
private void runUnaccepted() {
mPermissionsRationalesMap.clear();
if (mPendingIfUnacceptedAction != null) {
mPendingIfUnacceptedAction.run();
}
}
private void request() {
Set<String> permissionsSet = mPermissionsRationalesMap.keySet();
requestPermissions(permissionsSet.toArray(new String[permissionsSet.size()]));
}
private void requestPermissions(@NonNull String[] permissions) {
if (mFragment != null) {
mFragment.requestPermissions(permissions, REQUEST_PERMISSIONS_CODE);
} else {
ActivityCompat.requestPermissions(mActivity, permissions, REQUEST_PERMISSIONS_CODE);
}
}
private boolean shouldShowRationale() {
boolean should = true;
for (String permission : mPermissionsRationalesMap.keySet()) {
should &= shouldShowRequestPermissionRationale(permission);
}
return should;
}
private boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
if (mFragment != null) {
return mFragment.shouldShowRequestPermissionRationale(permission);
} else {
return ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission);
}
}
private void showRationaleToRequest() {
prepareDialog()
.setPositiveButton("Ask again", (d, i) -> request())
.show();
}
private void showRationaleToSettings() {
prepareDialog()
.setPositiveButton("Settings", (d, i) -> getContext().startActivity(intentToSettings()))
.show();
}
private AlertDialog.Builder prepareDialog() {
StringBuilder message = new StringBuilder("For using some app features we need to you grant this permissions list:\n");
for (Map.Entry<String, String> entry : mPermissionsRationalesMap.entrySet()) {
message.append("\n").append(cutPermissionName(entry.getKey()));
if (!TextUtils.isEmpty(entry.getValue())) {
message.append(" - ").append(entry.getValue());
}
}
return new AlertDialog.Builder(getContext())
.setTitle("You have denied permissions")
.setMessage(message)
.setOnCancelListener((d) -> runUnaccepted())
.setNegativeButton(R.string.cancel, (d, w) -> runUnaccepted());
}
private String cutPermissionName(String permission) {
int lastDotIndex = permission.lastIndexOf('.') + 1;
return permission.substring(lastDotIndex).replaceAll("_", " ");
}
private Intent intentToSettings() {
return new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", getContext().getPackageName(), null));
}
private Context getContext() {
if (mFragment != null) {
return mFragment.getActivity();
} else {
return mActivity;
}
}
}