最近公司开发一个项目,需要用到短信的功能,适配华为手机一切都正常,适配小米手机,遇到了两个棘手问题:
1.小米MIUI有个通知类短信权限,这个权限不知道如何申请,不知道如何判断是否具有该权限;
2.业务要求在引导页弹短信读取权限的弹窗让用户授权(这个是其他手机正常的流程),小米MIUI读取短信权限READ_SMS,动态申请后不弹窗,但是会走onRequestPermissionsResult的回调,而且回调值是PERMISSION_GRANTED,去权限设置页面查看该权限其实是询问状态;
第一个问题:解决办法是手动引导用户去设置页面开启,一般引导页只会走一次,这个权限是否开启目前没法判断,看过其他的例如来电类app, 有些权限也无法判断是否开启了,做法是弹窗让用户选择是否已开启。
小米跳权限设置页代码如下:
public static void goPermissionSettings(Activity activity) {
if (isMIUI()) {
Intent intent;
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
intent.putExtra("extra_pkgname", activity.getPackageName());
if (PhoneUtil.isIntentAvailable(intent, activity)) {
activity.startActivityForResult(intent, REQUEST_CODE_SERVICE_SMS);
} else {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", activity.getPackageName());
if (PhoneUtil.isIntentAvailable(intent, activity)) {
activity.startActivityForResult(intent, REQUEST_CODE_SERVICE_SMS);
} else {
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivityForResult(intent, REQUEST_CODE_SERVICE_SMS);
}
}
}
}
/**
* 判断是否是小米机型
* @return
*/
public static boolean isMIUI() {
if (isMiui == null) {
isMiui = !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
}
return isMiui;
}
public static String getSystemProperty(String propName) {
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
Log.e(TAG, "Unable to read sysprop " + propName, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
Log.e(TAG, "Exception while closing InputStream", e);
}
}
}
return line;
}
/**
* 判断是否存在可用的跳转意图
*/
public static boolean isIntentAvailable(Intent intent, Context context) {
if (intent == null || context == null || context.getPackageManager() == null) {
return false;
}
return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
第二个问题:小米MIUI其实有一套自己的权限管理,叫AppOpsManager,Google把它隐藏了没有开放出来,这个权限管理比现有的权限优先级更高。AppOpsManager可以跳过一些流氓软件的限制。比如应用需要开启某一个敏感权限,如果你拒绝了,应用就会不让你进去或者一直弹窗提醒。 利用AppOpsManager可以判断读取短信的权限是开启还是拒绝还是询问。不过最坑的是就是虽然你判断出它是具体是什么状态了,你还是没法让它弹窗授权。
不过我发现了一个问题,小米MIUI弹出短信读读取的时机是当应用真正去读短信的时候触发。Ps:前提是你申请了读取短信权限。 所以我们可以这样做:在第一次申请读取短信权限的回调里去真正读一次短信操作,这个时候你会发现读取短信的弹窗弹起来了,后面就是正常流程了。补充一点,小米的读取短信权限如果手动拒绝了,下次再用这种方式也是不弹窗的,只能手动引导用户打开读取短信的权限了。
总结:小米MIUI真是太坑了!