没啥技术含量,代码可以直接粘走使用
从安卓6.0(api23)开始,权限声明不仅需要在manifest中添加权限声明,还需要在JAVA代码中再次申请一遍,但是权限申请的结果是在onRequestPermissionsResult中回调的,当拿到回调结果后,还需要再判断用户是否勾选了“不再提示”选项,如果再次申请,会出现很多重复代码,因此,把权限申请放在baseActivity里面,我们在使用的时候,一个方法即可搞定,具体代码如下:
public class BaseActivity extends AppCompatActivity {
private String mReason;
private int mPermissionCode;
private String mPermission;
private PermissionCallback mCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
// 提供给子类调用的权限申请接口
@TargetApi(23)
protected void requestPermissionWithReason(String permission, String reason,
int permissionCode, PermissionCallback callback) {
mReason = reason;
mCallback = callback;
mPermission = permission;
mPermissionCode = permissionCode;
// 检查自身是否有此权限
if (PackageManager.PERMISSION_DENIED == checkSelfPermission(permission)) {
// 如果没有,就去申请权限
requestPermissions(new String[]{permission}, mPermissionCode);
} else {
// 如果有,则调用callback
callback.onPermissionResult(true, mPermissionCode);
}
}
// 系统回调的permission结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == mPermissionCode
&& grantResults[0] != PackageManager.PERMISSION_DENIED) {
// 权限申请成功
mCallback.onPermissionResult(true, mPermissionCode);
} else {
// 权限申请失败时,判断是否需要告诉用户原因
if (shouldShowRequestPermissionRationale(permissions[0])) {
// 如果需要解释原因,则弹窗告诉用户
showReasonDialog();
} else {
// 如果不需要,则返回权限申请失败
mCallback.onPermissionResult(false, mPermissionCode);
}
}
}
// 弹窗展示权限申请原因,设定为protected是为了方便修改其它权限解释方式
protected void showReasonDialog() {
new AlertDialog.Builder(this)
.setMessage(mReason)
.setNegativeButton("取消", (dialog, which) -> {
// 用户点击取消时,返回权限被拒绝
dialog.dismiss();
mCallback.onPermissionResult(false, mPermissionCode);
})
.setPositiveButton("确定", ((dialog, which) -> {
// 用户点击确定时,继续申请
dialog.dismiss();
requestPermissions(new String[]{mPermission}, mPermissionCode);
}))
.create().show();
}
// 权限申请回调的接口类
public interface PermissionCallback {
void onPermissionResult(boolean result, int permissionCode);
}
}
这样写的好处是,在申请权限的时候,只需要调用父类的requestPermissionWithReason()方法即可得到最终结果;另外,不建议在APP启动的时候就进行全部权限的申请,我们可以在当运行到某个需要权限的代码时再去申请,试想一下,用户第一次打开APP,啥也没做呢,遇到一大堆权限要求,估计很多人都直接拒绝了吧?
同样的,此代码也可以封装在baseFragment中,逻辑完全一致
下面列一下需要在代码中申请的权限,共计9组,只要其中一个权限申请成功了,该组中其它权限也都可以被使用:
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS