You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MIUI系统特定应用权限查询及桌面快捷方式权限检测问题

MIUI系统特定应用权限查询及桌面快捷方式权限检测问题

嘿,我之前也踩过MIUI这个权限的坑!确实挺闹心的——这个“桌面快捷方式”权限是小米自己加的自定义权限,不属于Android官方的权限体系,所以系统日志里不会给出标准的权限名称,这也是你找不到它名字的原因。

下面给你说下怎么检测和处理这个问题:

一、为什么日志里没有权限名?

MIUI的这个权限开关是基于自家的AppOps机制实现的,不是通过Android标准的<uses-permission>声明的权限,所以调用requestPinShortcut()时,系统只会提示“没有权限”,但不会给出具体的权限字符串。

二、如何检测这个权限状态?

因为是MIUI自定义的控制逻辑,我们得结合标准API和MIUI的私有机制来检测:

方法1:用标准AppOpsManager检测(兼容大部分情况)

MIUI的这个权限本质上是拦截了REQUEST_PIN_SHORTCUT的操作,所以可以通过AppOpsManager来检查对应的操作状态:

import android.app.AppOpsManager;
import android.content.Context;

private boolean hasHomeShortcutPermission(Context context) {
    AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    if (appOps == null) {
        return false;
    }
    // 对应REQUEST_PIN_SHORTCUT的操作码
    int opCode = AppOpsManager.OP_REQUEST_PIN_SHORTCUT;
    int mode = appOps.checkOpNoThrow(opCode, android.os.Process.myUid(), context.getPackageName());
    return mode == AppOpsManager.MODE_ALLOWED;
}

方法2:反射调用MIUI私有API(针对特殊版本)

如果上面的方法在某些MIUI版本上不生效,可以尝试反射调用小米的私有AppOps管理类,注意这个方法可能随MIUI版本变化:

import java.lang.reflect.Method;

private boolean hasMiuiShortcutPermission(Context context) {
    try {
        // 获取MIUI的AppOps管理类
        Class<?> miuiAppOpsClass = Class.forName("android.app.MiuiAppOpsManager");
        Object miuiAppOps = context.getSystemService("miui_appops");
        // 获取检查操作的方法
        Method checkOpMethod = miuiAppOpsClass.getMethod("checkOp", int.class, int.class, String.class);
        // MIUI中对应桌面快捷方式权限的操作码(部分版本为22,可根据实际调试调整)
        int miuiOpCode = 22;
        int mode = (int) checkOpMethod.invoke(miuiAppOps, miuiOpCode, android.os.Process.myUid(), context.getPackageName());
        // MODE_ALLOWED在MIUI中对应值为0
        return mode == 0;
    } catch (Exception e) {
        // 反射失败时, fallback到标准检测方法
        return hasHomeShortcutPermission(context);
    }
}

三、权限不足时引导用户开启

如果检测到权限未开启,可以引导用户跳转到MIUI的权限设置页面:

import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.content.ActivityNotFoundException;

private void navigateToMiuiShortcutSettings(Context context) {
    Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
    intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
    intent.putExtra("extra_pkgname", context.getPackageName());
    intent.putExtra("extra_type", 1); // 1对应"其他权限"分类
    try {
        context.startActivity(intent);
    } catch (ActivityNotFoundException e) {
        // 若找不到MIUI特定页面,跳转到应用详情页
        intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", context.getPackageName(), null);
        intent.setData(uri);
        context.startActivity(intent);
    }
}

四、兜底方案:直接调用后判断

如果上面的检测方法都不放心,也可以直接调用requestPinShortcut(),根据返回值判断是否成功:

boolean isSuccess = shortcutManager.requestPinShortcut(shortcutInfo, null);
if (!isSuccess) {
    // 权限不足,引导用户开启
    navigateToMiuiShortcutSettings(context);
}

备注:内容来源于stack exchange,提问作者Suet

火山引擎 最新活动