簡體   English   中英

如何處理SYSTEM_ALERT_WINDOW權限未在某些Marshmallow設備上自動授予

[英]How to handle SYSTEM_ALERT_WINDOW permission not being auto-granted on some pre-Marshmallow devices

我一直在收到一些小米設備(例如Mi 2,運行API級別21)沒有顯示疊加層的報告。 我的應用針對API 23。

關於此,有幾個 帖子 似乎MIUI設備在安裝時不啟用此權限(與其他Marshmallow之前的設備不同)。

不幸的是, Settings.canDrawOverlays()僅適用於Android 23+。

  1. 在Marshmallow之前檢查此權限是否尚未啟用的正確方法是什么?
  2. 是否有意圖將用戶帶到相關的MUIU設置頁面? 也許: new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION", packageName)但我無法測試這個。

1)在API 23之前,已經給出了權限,因為用戶在安裝時授予了權限。

編輯:似乎Android 6上有一個錯誤(將在6.0.1上修復 ),如果用戶拒絕此權限,應用程序將與SecurityException崩潰。 不知道谷歌如何修復它。

2)這樣:

public static void requestSystemAlertPermission(Activity context, Fragment fragment, int requestCode) {
    if (VERSION.SDK_INT < VERSION_CODES.M)
        return;
    final String packageName = context == null ? fragment.getActivity().getPackageName() : context.getPackageName();
    final Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + packageName));
    if (fragment != null)
        fragment.startActivityForResult(intent, requestCode);
    else
        context.startActivityForResult(intent, requestCode);
}

然后,在onActivityResult中,您可以檢查是否給出了權限,如下:

@TargetApi(VERSION_CODES.M)
public static boolean isSystemAlertPermissionGranted(Context context) {
    final boolean result = VERSION.SDK_INT < VERSION_CODES.M || Settings.canDrawOverlays(context);
    return result;
}

編輯:目前,如果您將應用程序發布到Play商店,您的應用程序將自動獲得此權限。 你可以在這里閱讀它。 當我詢問它時,我認為它是Android本身的一部分,因為我認為我們所需要的是為targetSdkVersion設定足夠高的值。 谷歌寫給我的( 這里 )是他們希望避免流行應用上的問題。

我建議正確處理此權限,即使您將自動授予它。

使用以下方法檢查您是否具有drawOverlays權限更安全:

@SuppressLint("NewApi")
public static boolean canDrawOverlayViews(Context con){
    if(Build.VERSION.SDK_INT< Build.VERSION_CODES.LOLLIPOP){return true;}
    try { 
        return Settings.canDrawOverlays(con); 
    }
    catch(NoSuchMethodError e){ 
        return canDrawOverlaysUsingReflection(con); 
    }
}


public static boolean canDrawOverlaysUsingReflection(Context context) {

    try {

        AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        Class clazz = AppOpsManager.class;
        Method dispatchMethod = clazz.getMethod("checkOp", new Class[] { int.class, int.class, String.class });
        //AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
        int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });

        return AppOpsManager.MODE_ALLOWED == mode;

    } catch (Exception e) {  return false;  }

}

自定義ROM可以更改操作系統,以便Settings.canDrawOverlays()不可用。 小米設備和應用程序崩潰后發生了這種情況。

申請許可:

@SuppressLint("InlinedApi")
public static void requestOverlayDrawPermission(Activity act, int requestCode){
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + act.getPackageName()));
    act.startActivityForResult(intent, requestCode);

}

這是一步一步如何處理這個:

首先在清單文件中給出以下權限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

要么

<uses-permission-sdk-23 android:name="android.permission.SYSTEM_ALERT_WINDOW" />

然后使用以下代碼處理其余的事情:

 public final static int REQUEST_CODE = 65635;

    public void checkDrawOverlayPermission() {
        /** check if we already  have permission to draw over other apps */
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                /** if not construct intent to request permission */
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                /** request permission via start activity for result */
                startActivityForResult(intent, REQUEST_CODE);
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,  Intent data) {
        /** check if received result code
         is equal our requested code for draw permission  */
        if (requestCode == REQUEST_CODE) {
            // ** if so check once again if we have permission */
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (Settings.canDrawOverlays(this)) {
                    // continue here - permission was granted
                    goYourActivity();
                }
            }
        }
    }

只需從LauncherActivity或任何地方調用checkDrawOverlayPermission()

執行項目時,您將看到一個窗口並要求啟用該權限。 在獲得許可后,您將能夠對此做任何事情。

為了尋找關於小米的問題,魅族我找到了這個。 它完美地工作..

public static boolean isMiuiFloatWindowOpAllowed(@NonNull Context context) {
    final int version = Build.VERSION.SDK_INT;

    if (version >= 19) {
        return checkOp(context, OP_SYSTEM_ALERT_WINDOW); //See AppOpsManager.OP_SYSTEM_ALERT_WINDOW=24 /*@hide/
    } else {
        return (context.getApplicationInfo().flags & 1<<27) == 1;
    }
}

public static boolean checkOp(Context context, int op, String packageName, int uid) {
    final int version = Build.VERSION.SDK_INT;

    if (version >= 19) {
        AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        try {
            return (AppOpsManager.MODE_ALLOWED == (Integer) ReflectUtils.invokeMethod(manager, "checkOp", op, uid, packageName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        Flog.e("Below API 19 cannot invoke!");
    }
    return false;
}

ReflectUtils.java

public static Object invokeMethod(@NonNull Object receiver, String methodName, Object... methodArgs) throws Exception {
Class<?>[] argsClass = null;
    if (methodArgs != null && methodArgs.length != 0) {
        int length = methodArgs.length;
        argsClass = new Class[length];
        for (int i=0; i<length; i++) {
            argsClass[i] = getBaseTypeClass(methodArgs[i].getClass());
        }
    }

    Method method = receiver.getClass().getMethod(methodName, argsClass);
    return method.invoke(receiver, methodArgs);
}

參考

你可以檢查這樣的權限:

boolean granted = activity.checkSelfPermission("android.permission.SYSTEM_ALERT_WINDOW") == PackageManager.PERMISSION_GRANTED;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM