美文网首页
Android中代码动态判断是否开启悬浮窗权限和申请悬浮窗权限

Android中代码动态判断是否开启悬浮窗权限和申请悬浮窗权限

作者: 泱千澈 | 来源:发表于2020-03-24 15:26 被阅读0次

    原因

    <!-- 在应用程序的AndroidManifest.xml文件中添加权限 -->
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    

    在某些机型上居然后出现permission denied for window type 2038错误:

    E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.lanmao.jpsg.android, PID: 27024
    android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W @ff8b1a 
        -- permission denied for window type 2038
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:1090)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:381)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
        at com.quicksdk.apiadapter.undefined.a.y.b(ToolBar.java:58)
        at com.quicksdk.apiadapter.undefined.UserAdapter$6.onClick(UserAdapter.java:138)
        at com.quicksdk.apiadapter.undefined.a.r$a$1.onClick(LoginDialog.java:88)
        at android.view.View.performClick(View.java:7339)
        at android.widget.TextView.performClick(TextView.java:14226)
        at android.view.View.performClickInternal(View.java:7305)
        at android.view.View.access$3200(View.java:846)
        at android.view.View$PerformClick.run(View.java:27787)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7081)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965) ```
    

    Build.VERSION.SDK_INT

    Build.VERSION.SDK_INT 软件app安装在哪个手机上,该手机的操作系统版本号 比如8.1对应的SDK_INT是27

    The SDK version of the software currently running on this hardware device.
    This value never changes while a device is booted, but it may increase when
    the hardware manufacturer provides an OTA update.

    Android API与Android版本对应关系


    SDK_INT

    解决方案

    主要代码

        private static final int FloatRequestCode = 1002;
        public void onCreate() {
            super.onCreate();
            Activity context =  getContext();
            com.quicksdk.Sdk.getInstance().onCreate(context);
            if(!checkFloatPermission(context)){
                requestFloatPermission(context, FloatRequestCode);
            }
          }
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            final Activity context = getContext();
            com.quicksdk.Sdk.getInstance().onActivityResult(context,
                    requestCode, resultCode, data);
            if(requestCode == FloatRequestCode) {
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if(!checkFloatPermission(context)){
                            requestFloatPermission(context,FloatRequestCode);
                        }
                    }
                },1000);
            }
        }
        /***
         * 检查悬浮窗开启权限
         * @param context
         * @return
         */
        public boolean checkFloatPermission(Context context) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
                return true;
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                try {
                    Class cls = Class.forName("android.content.Context");
                    Field declaredField = cls.getDeclaredField("APP_OPS_SERVICE");
                    declaredField.setAccessible(true);
                    Object obj = declaredField.get(cls);
                    if (!(obj instanceof String)) {
                        return false;
                    }
                    String str2 = (String) obj;
                    obj = cls.getMethod("getSystemService", String.class).invoke(context, str2);
                    cls = Class.forName("android.app.AppOpsManager");
                    Field declaredField2 = cls.getDeclaredField("MODE_ALLOWED");
                    declaredField2.setAccessible(true);
                    Method checkOp = cls.getMethod("checkOp", Integer.TYPE, Integer.TYPE, String.class);
                    int result = (Integer) checkOp.invoke(obj, 24, Binder.getCallingUid(), context.getPackageName());
                    return result == declaredField2.getInt(cls);
                } catch (Exception e) {
                    return false;
                }
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    AppOpsManager appOpsMgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
                    if (appOpsMgr == null)
                        return false;
                    int mode = appOpsMgr.checkOpNoThrow("android:system_alert_window", android.os.Process.myUid(), context
                            .getPackageName());
                    return Settings.canDrawOverlays(context) || mode == AppOpsManager.MODE_ALLOWED || mode == AppOpsManager.MODE_IGNORED;
                } else {
                    return Settings.canDrawOverlays(context);
                }
            }
        }
    
        /**
         * 悬浮窗开启权限
         * @param context
         * @param requestCode
         */
        public void requestFloatPermission(Activity context, int requestCode){
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
            intent.setData(Uri.parse("package:" + context.getPackageName()));
            context.startActivityForResult(intent, requestCode);
        }
    

    参考

    相关文章

      网友评论

          本文标题:Android中代码动态判断是否开启悬浮窗权限和申请悬浮窗权限

          本文链接:https://www.haomeiwen.com/subject/gsvoyhtx.html