MIUI 判断悬浮窗权限

/**
* Created by chenzy on 2015/3/31.
*
* MIUI 悬浮窗判断工具类
*/
public class AlterWindowUtil {
    public static final String TAG ="AlterWindowUtil";

    /**
     * 4.4 以上可以直接判断准确
     *
     * 4.4 以下非MIUI直接返回true
     *
     * 4.4 以下MIUI 可 判断 上一次打开app 时 是否开启了悬浮窗权限
     *
     * @param context
     * @return
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static boolean isFloatWindowOpAllowed(Context context) {
        final int version = Build.VERSION.SDK_INT;

        if(!DeviceUtil.isFlyme4() && !DeviceUtil.isMiui(context)){
            return true;
        }

        if (version >= 19) {
            return checkOp(context, 24);  //自己写就是24 为什么是24?看AppOpsManager //AppOpsManager.OP_SYSTEM_ALERT_WINDOW
        } else {
            if(DeviceUtil.isMiui(context)){
                if ((context.getApplicationInfo().flags & 1 << 27) == 1 <<27 ) {
                    return true;
                } else {
                    return false;
                }
            }else{
                return true;
            }
        }

    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static boolean checkOp(Context context, int op) {
        final int version = Build.VERSION.SDK_INT;

        if (version >= 19) {
            AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
            try {
                Class managerClass = manager.getClass();
                Method method = managerClass.getDeclaredMethod("checkOp", int.class, int.class, String.class);
                int isAllowNum = (Integer) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());

                if (AppOpsManager.MODE_ALLOWED == isAllowNum) {
                    return true;
                } else {
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

}

Android 系统中,申请和适配悬浮窗权限(`SYSTEM_ALERT_WINDOW`)是一个较为复杂的问题,因为不同厂商的系统定制化程度较高,导致权限管理机制存在较大差异。以下是针对悬浮窗权限申请和适配的专业方法: ### 悬浮窗权限的基本申请流程 在标准 Android 系统中,从 Android 6.0(API 23)开始,应用需要显式请求用户授权才能弹出悬浮窗。开发者可以通过以下方式请求权限: ```java Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, REQUEST_CODE); ``` 在 `onActivityResult` 中判断用户是否授予了该权限: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Settings.canDrawOverlays(this)) { // 已获得权限,可以启动悬浮窗服务 } else { // 用户未授权,提示信息或再次请求 } } ``` 这种方法适用于大多数原生 Android 设备以及部分厂商设备,但并不适用于所有定制系统[^1]。 ### 针对不同厂商的适配方案 由于各大厂商如小米、华为、OPPO、Vivo 等均对悬浮窗权限进行了独立的管理,开发者需要根据不同的品牌跳转到对应的设置页面进行手动授权。 例如: - **小米**:`com.miui.securitycenter.permission.CanDrawOverlays` - **华为**:`com.huawei.systemmanager.startupmgr.ui.StartupAutoStartManagerActivity` - **三星**:`com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity` - **OPPO**:`com.coloros.safecenter.permission.floatwindow.FloatWindowListActivity` - **Vivo**:`com.vivo.permissionmanager.activity.BgStartUpManagerActivity` 这些适配逻辑通常通过反射或者预设意图来实现,具体实现代码需根据厂商 API 文档进行封装。 ### Android 14 及以上系统的特殊处理 从 Android 14 开始,Google 对悬浮窗权限的管理更加严格,不再支持简单的 `ACTION_MANAGE_OVERLAY_PERMISSION` 方式,而是要求使用 `AppOpsManager` 来动态控制权限。核心类包括: - `AppOpsManager` - `PhoneWindowManager` 具体的实现逻辑涉及调用 `AppOpsManager.setMode()` 方法,并传入目标包名及操作类型: ```java AppOpsManager appOps = (AppopsManager) getSystemService(Context.APP_OPS_SERVICE); appOps.setMode(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, Binder.getCallingUid(), getPackageName(), AppOpsManager.MODE_ALLOWED); ``` 需要注意的是,这种方式通常只能在系统级应用中使用,普通应用无法直接调用,除非具备系统签名权限[^2]。 ### 兼容性处理建议 - **统一入口检测**:无论系统版本如何,都应先调用 `Settings.canDrawOverlays()` 检测当前是否拥有权限。 - **厂商适配表维护**:建立一个厂商跳转表,根据不同设备型号跳转至对应的悬浮窗设置页面。 - **降级兼容处理**:对于 Android 6.0 以下设备,虽然默认允许悬浮窗,但仍需注意厂商自定义限制。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值