具体参考https://www.jianshu.com/p/88e0a371161c
模板代码
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission("android.permission.READ_EXTERNAL_STORAGE") == PackageManager.PERMISSION_GRANTED) {
return false;
}
if (shouldShowRequestPermissionRationale("android.permission.READ_EXTERNAL_STORAGE")) {
Toast.makeText(this, "请一定要给与权限!再给你一次选择的机会", Toast.LENGTH_SHORT).show();
requestPermissions(new String[]{"android.permission.READ_EXTERNAL_STORAGE"}, 2);
} else {
requestPermissions(new String[]{"android.permission.READ_EXTERNAL_STORAGE"}, 2);//首次申请
}
return true;
}
return true;
循环单个申请、以此弹出申请对话框。
这个逻辑推荐在进入app的时候弄,我发现很多app懒得麻烦,一次性申请完。
private void initRequestPermissionListAndStartRequest() {
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)) {
waitRequestPermissionGroup.add(Manifest.permission.READ_PHONE_STATE);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.CAMERA)) {
waitRequestPermissionGroup.add(Manifest.permission.CAMERA);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.CALL_PHONE)) {
waitRequestPermissionGroup.add(Manifest.permission.CALL_PHONE);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
waitRequestPermissionGroup.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.READ_SMS)) {
waitRequestPermissionGroup.add(Manifest.permission.READ_SMS);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_NETWORK_STATE);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
waitRequestPermissionGroup.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.MODIFY_AUDIO_SETTINGS)) {
waitRequestPermissionGroup.add(Manifest.permission.MODIFY_AUDIO_SETTINGS);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.INSTALL_SHORTCUT)) {
waitRequestPermissionGroup.add(Manifest.permission.INSTALL_SHORTCUT);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.UNINSTALL_SHORTCUT)) {
waitRequestPermissionGroup.add(Manifest.permission.UNINSTALL_SHORTCUT);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.SEND_SMS)) {
waitRequestPermissionGroup.add(Manifest.permission.SEND_SMS);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS)) {
waitRequestPermissionGroup.add(Manifest.permission.RECEIVE_SMS);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.WAKE_LOCK)) {
waitRequestPermissionGroup.add(Manifest.permission.WAKE_LOCK);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.WRITE_CALL_LOG)) {
waitRequestPermissionGroup.add(Manifest.permission.WRITE_CALL_LOG);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.KILL_BACKGROUND_PROCESSES)) {
waitRequestPermissionGroup.add(Manifest.permission.KILL_BACKGROUND_PROCESSES);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.GET_TASKS)) {
waitRequestPermissionGroup.add(Manifest.permission.GET_TASKS);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.VIBRATE)) {
waitRequestPermissionGroup.add(Manifest.permission.VIBRATE);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_WIFI_STATE);
}
/* if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.BLUETOOTH)) {
waitRequestPermissionGroup.add(Manifest.permission.BLUETOOTH);
}
*/
if (waitRequestPermissionGroup.size() > 0) {
PermissionsUtils.requestPermission(this, waitRequestPermissionGroup.get(0), REQUEST_LOOP);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] gradResults) {
if (requestCode == REQUEST_LOOP) {
Log.w(TAG, "获取" + permissions[0] + "结果是成功:" + (gradResults.length > 0 && gradResults[0] == PackageManager.PERMISSION_GRANTED) + ",列表中共有" + waitRequestPermissionGroup.size() + "个权限等待申请!");
if (waitRequestPermissionGroup.size() > 0) {
waitRequestPermissionGroup.remove(0);
}
if (waitRequestPermissionGroup.size() > 0) {
String premissionStr = waitRequestPermissionGroup.get(0);
Log.w(TAG, "开始申请" + premissionStr + "权限!");
if (PermissionsUtils.requestPermission(this, premissionStr, requestCode)) {
onRequestPermissionsResult(REQUEST_LOOP, new String[]{premissionStr}, new int[]{});
}
} else {
if (gradResults.length > 0 && gradResults[0] != PackageManager.PERMISSION_GRANTED) {
AppContext.showToast(permissions[0] + "权限请求失败");
}else{
Log.w(TAG, "所有权限申请完毕!");
}
}
}
}
写的不太对,这是比亚迪的测试结果,比较有争议的就是shouldShowRequestPermissionRationale
实际上我测试的结果如果是第一次或者被永久拒绝就返回false, 如果没有被拒绝,再次打开app申请就返回true,返回true一定可以申请弹出,返回false,则不一定,目前没有判断永久拒绝的方法。
/MY_PERMISSION Manifest.permission.BYDAUTO_AC_COMMON
public static void verify(Activity context) {
// DeviceBaseInfoUtils.getBydVin(Activity activity)
if (context.checkSelfPermission(MY_PERMISSION)//判断是否拥有这个方法,如果 拥有则不等于 PERMISSION_GRANTED
!= PERMISSION_GRANTED) {
Log.w(TAG, "checkSelfPermission ==FALSE 上次是拒绝了此权限的");
//如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。
if (context.shouldShowRequestPermissionRationale(MY_PERMISSION)) {//如果非第一次 拒绝但是还没有设置永久拒绝会走这个逻辑, 这个时候还是可以申请权限的。
Log.w(TAG, "shouldShowRequestPermissionRationale true");
Toast.makeText(context, "为了您的安全,请一定要同意权限申请!", Toast.LENGTH_SHORT).show();
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN);
} else {
Log.w(TAG, "shouldShowRequestPermissionRationale false 第一次或者被永久拒绝"); //第一次 或者被永久拒绝走这个逻辑,
Log.w(TAG, "requestPermissions");
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN);//如果永久拒绝,
}
} else {
// 拥有权限
Log.w(TAG, "checkSelfPermission ==true");
checkLogic(context);
}
}
public static void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions, int[] grantResults) {
if (REQUEST_CODE_VIN == requestCode) {
Log.w(TAG, "onRequestPermissionsResult permissions:" + Arrays.toString(permissions) + ",grantResults:" + Arrays.toString(grantResults));
if (permissions != null && permissions.length > 0 && permissions[0].equals(MY_PERMISSION)) {
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Log.w(TAG, "onRequestPermissionsResult 获取成功");
checkLogic(activity);
} else {
Log.w(TAG, "onRequestPermissionsResult 获取失败!");
doFailLogic();
}
}
}
}
那么永久拒绝的判断
根据执行时间就可以推测了。
//MY_PERMISSION Manifest.permission.BYDAUTO_AC_COMMON
public static void verify(Activity context) {
// DeviceBaseInfoUtils.getBydVin(Activity activity)
if (context.checkSelfPermission(MY_PERMISSION)//判断是否拥有这个方法,如果 拥有则不等于 PERMISSION_GRANTED
!= PERMISSION_GRANTED) {
Log.w(TAG, "checkSelfPermission ==FALSE 上次是拒绝了此权限的");
//如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。
if (context.shouldShowRequestPermissionRationale(MY_PERMISSION)) {
Log.w(TAG, "shouldShowRequestPermissionRationale true");
Toast.makeText(context, "为了您的安全,请一定要同意权限申请!", Toast.LENGTH_SHORT).show();
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN_SECOND);
//如果非第一次 拒绝但是还没有设置永久拒绝会走这个逻辑, 这个时候还是可以申请权限的。
} else {
Log.w(TAG, "shouldShowRequestPermissionRationale false 第一次或者被永久拒绝"); //第一次 或者被永久拒绝走这个逻辑,
Log.w(TAG, "requestPermissions");
sRequestTime = new Date().getTime();
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN_FIRST_OR_LAST);//如果永久拒绝,
}
} else {
// 拥有权限
Log.w(TAG, "checkSelfPermission ==true");
checkLogic(context);
}
}
public static void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions, int[] grantResults) {
if (REQUEST_CODE_VIN_SECOND == requestCode || requestCode == REQUEST_CODE_VIN_FIRST_OR_LAST) {
Log.w(TAG, "onRequestPermissionsResult permissions:" + Arrays.toString(permissions) + ",grantResults:" + Arrays.toString(grantResults));
if (permissions != null && permissions.length > 0 && permissions[0].equals(MY_PERMISSION)) {
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Log.w(TAG, "onRequestPermissionsResult 获取成功");
checkLogic(activity);
} else {
long distance = new Date().getTime() - sRequestTime;
if (BuildConfig.DEBUG) {
Log.w(TAG, "执行回调间隔:" + distance);
}
if (distance < 800 && requestCode == REQUEST_CODE_VIN_FIRST_OR_LAST) {
Log.w(TAG, "onRequestPermissionsResult 获取失败 推测是永久拒绝!");
} else {
Log.w(TAG, "onRequestPermissionsResult 获取失败!");
}
doFailLogic();//拒绝了
}
}
}
}
至于为什么是原创,因为我发现网上似乎没有这样的方法,而且很多文章讲的乱七八糟,甚至比亚迪的sdk demo都写错了,认为第二次就应该卸载才行。。
第一 shouldShowRequestPermissionRationale
为true,表示已经申请过了,但是没有永久拒绝,,永久拒绝和第一次都会返回false,
第二个,requestPermissions
只能调用一次,也就是说权限对话框弹出来的时候,如果方法继续执行又执行了requestPermissions
那么会马上收到权限失败的回调,而且 回调中的权限数组和结果int数组 长度是0的.
偏门:在做自动化插入任何app的时候这种问题是无法避免的,无法智能
第三个/如果requestPermissions
传递了多个参数,那么回一次请求权限弹出对话框,知道所有权限的一个接一个的弹出之后,才会进行回调,这个时候可能包含多个成功结果失败与否的数组。
第四个/如果弹出的时候finish或者请求之后马上finish,前者虽然能看到,但是finish了看不到任何回调,后者则看不到弹出权限对话框,也不会回调结果
偏门:这个做自动化才会感受到这些问题