public class RationaleDialogFragment extends DialogFragment {
public static final String TAG = "RationaleDialogFragment";
private static final String ARG_POSITIVE_BUTTON = "positiveButton";
private static final String ARG_NEGATIVE_BUTTON = "negativeButton";
private static final String ARG_RATIONALE_MESSAGE = "rationaleMsg";
private static final String ARG_REQUEST_CODE = "requestCode";
private static final String ARG_PERMISSIONS = "permissions";
private int positiveButton;
private int negativeButton;
private String rationaleMsg;
private int requestCode;
private String[] permissions;
private PermissionCallbacks mPermissionCallbacks;
public RationaleDialogFragment() {
}
public static RationaleDialogFragment newInstance(
@StringRes int positiveButton, @StringRes int negativeButton,
@NonNull String rationaleMsg, int requestCode, @NonNull String[] permissions) {
RationaleDialogFragment fragment = new RationaleDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITIVE_BUTTON, positiveButton);
args.putInt(ARG_NEGATIVE_BUTTON, negativeButton);
args.putString(ARG_RATIONALE_MESSAGE, rationaleMsg);
args.putInt(ARG_REQUEST_CODE, requestCode);
args.putStringArray(ARG_PERMISSIONS, permissions);
fragment.setArguments(args);
return fragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
boolean isAtLeastJellyBeanMR1 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
if (isAtLeastJellyBeanMR1
&& getParentFragment() != null
&& getParentFragment() instanceof PermissionCallbacks) {
mPermissionCallbacks = (PermissionCallbacks) getParentFragment();
} else if (context instanceof PermissionCallbacks) {
mPermissionCallbacks = (PermissionCallbacks) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement PermissionCallbacks");
}
}
@Override
public void onDetach() {
super.onDetach();
mPermissionCallbacks = null;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
if (getArguments() != null) {
positiveButton = getArguments().getInt(ARG_POSITIVE_BUTTON);
negativeButton = getArguments().getInt(ARG_NEGATIVE_BUTTON);
rationaleMsg = getArguments().getString(ARG_RATIONALE_MESSAGE);
requestCode = getArguments().getInt(ARG_REQUEST_CODE);
permissions = getArguments().getStringArray(ARG_PERMISSIONS);
}
setCancelable(false);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setCancelable(false)
.setPositiveButton(positiveButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Object host;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
host = getParentFragment() != null ?
getParentFragment() :
getActivity();
} else {
host = getActivity();
}
if (host instanceof Fragment) {
((Fragment) host).requestPermissions(permissions, requestCode);
} else if (host instanceof FragmentActivity) {
ActivityCompat.requestPermissions(
(FragmentActivity) host, permissions, requestCode);
}
}
})
.setNegativeButton(negativeButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (mPermissionCallbacks != null) {
mPermissionCallbacks.onPermissionsDenied(requestCode,
Arrays.asList(permissions));
}
}
})
.setMessage(rationaleMsg);
return builder.create();
}
public interface PermissionCallbacks extends ActivityCompat.OnRequestPermissionsResultCallback {
void onPermissionsGranted(int requestCode, List<String> perms);
void onPermissionsDenied(int requestCode, List<String> perms);
}
}
public class MainActivity extends AppCompatActivity implements RationaleDialogFragment.PermissionCallbacks {
public static final String TAG = "MainActivity";
private static final int RC_CAMERA = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Log.i(TAG, "onRequestPermissionsResult:" + requestCode + "," + Arrays.toString(permissions) + "," + Arrays.toString(grantResults));
switch (requestCode) {
case RC_CAMERA: {
// 如果请求被取消了,那么结果数组就是空的
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 权限被授予了
showCameraPreview();
}
return;
}
}
}
public void showCamera(View view) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// 我们应该给用户个解释?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
// 向用户显示一个解释,要以异步非阻塞的方式
// 该线程将等待用户响应!等用户看完解释后再继续尝试请求权限
RationaleDialogFragment
.newInstance(android.R.string.ok, android.R.string.cancel,
getString(R.string.rationale_camera), RC_CAMERA,
new String[]{Manifest.permission.CAMERA})
.show(getSupportFragmentManager(), RationaleDialogFragment.TAG);
} else {
// 不需要向用户解释了,我们可以直接请求该权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
RC_CAMERA);
}
} else {
showCameraPreview();
}
}
private void showCameraPreview() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_fragment, CameraPreviewFragment.newInstance())
.addToBackStack("camera")
.commit();
}
@Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
Log.i(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
}
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
Log.i(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
}
}