检测到的屏幕覆盖阻止了 Android 权限 [英] Screen overlay detected blocks Android permissions

查看:17
本文介绍了检测到的屏幕覆盖阻止了 Android 权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到我的新手机上的 Android 应用出现了一个奇怪的问题.SDK 23 权限弹出窗口(如外部存储)被下面附加的警报阻止.我最初认为这与我的手机有关,但它似乎不会影响我安装的任何其他应用程序.

这个问题可能与安装调试版本有关,还是我的权限处理有问题?我认为它可能与我正在使用的广告平台之一有关,但我尝试禁用它们,它仍然出现

我在下面粘贴了生成此权限请求的图像保存功能.我正在使用

解决方案

这个弹窗是由 manifest.PERMISSION.SYSTEM_ALERT_WINDOW 权限由清单声明.开发人员必须了解 3 类权限.

  1. 正常许可 - 不对它们做任何事情,只需在清单中声明
  2. 易受攻击的权限 - 在 Manifest 中声明并询问第一次获得许可.它们可以通过系统设置进行更改
  3. 以上危险权限:SYSTEM_ALERT_WINDOWWRITE_SETTINGS 属于这一类.它们必须被授予,但在系统设置中不可见.要请求它,您不使用标准方式(int checkSelfPermission (String permission)),但您必须检查 Settings.canDrawOverlays()Settings.System.canWrite() 适当

<小时>

如果您没有 SYSTEM_ALERT_WINDOW 权限:

  1. 检查在与权限弹出窗口交互时是否有可见的 Toast. 尽管检测到叠加层弹出窗口没有提到它,Toast> 也算作叠加
  2. 检查您的任何依赖项是否需要它.

<小时>

如果您不确定是否正在使用此权限,您可以执行以下几个测试用例:

  1. 自行请求此权限:

    公共类 MainActivity 扩展 AppCompatActivity {公共最终静态 int REQUEST_CODE = 10101;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);如果(checkDrawOverlayPermission()){开始服务(新意图(这个,PowerButtonService.class));}}公共布尔 checkDrawOverlayPermission() {如果 (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {返回真;}如果 (!Settings.canDrawOverlays(this)) {意图意图 = 新意图(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,uri.parse("package:" + getPackageName()));startActivityForResult(intent, REQUEST_CODE);返回假;} 别的 {返回真;}}@覆盖@TargetApi(Build.VERSION_CODES.M)protected void onActivityResult(int requestCode, int resultCode, Intent data) {如果(请求代码 == REQUEST_CODE){如果 (Settings.canDrawOverlays(this)) {开始服务(新意图(这个,PowerButtonService.class));}}}}

  2. 检查是否这个不是你的情况

  3. 查看这篇文章以了解,通过 Play 商店安装应用程序时会自动授予此权限(我没有检查过,所以无法确认)

权限模型可以理解,只是有时候需要多挖掘一下.

I've noticed a strange issue with my Android app on my new phone. SDK 23 permission popups like external storage are blocked by the attached alert below. I initially thought this was related to my phone, but it doesn't seem to affect any of my other installed apps.

Is this issue perhaps related to having a debug version installed, or is it something wrong with my permission handling? I thought it could somehow be related to one of the ad platforms I'm using but I tried disabling them and it still showed up

I've pasted the image saving function that is generate this permission request below. I'm using Dexter to save on writing a whole bunch of hideous boilerplate

public static void saveToExternalStorageIfAllowed(final Context context, final Bitmap bitmapImage, final String title) {
    final Tracker t = ((LoLHistory) context.getApplicationContext()).getTracker(LoLHistory.TrackerName.APP_TRACKER);

    // saving to publicly visible/accessible folder. Requires write permission
    int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        // do not have permissions to write, request
        t.send(new HitBuilders.EventBuilder()
                .setCategory("FILE")
                .setAction("PermissionMissing")
                .setLabel("WRITE_EXTERNAL")
                .build());
        Dexter.checkPermission(new PermissionListener() {
            @Override
            public void onPermissionGranted(PermissionGrantedResponse response) {
                t.send(new HitBuilders.EventBuilder()
                        .setCategory("FILE")
                        .setAction("PermissionGranted")
                        .setLabel("WRITE_EXTERNAL")
                        .build());

                saveToExternalStorage(context, bitmapImage, title);
            }

            @Override
            public void onPermissionDenied(PermissionDeniedResponse response) {
                t.send(new HitBuilders.EventBuilder()
                        .setCategory("FILE")
                        .setAction("PermissionDenied")
                        .setLabel("WRITE_EXTERNAL")
                        .build());
            }

            @Override
            public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {/* ... */}
        }, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    } else {
        saveToExternalStorage(context, bitmapImage, title);
    }
}

private static void saveToExternalStorage(Context context, Bitmap bitmapImage, String title) {
    Tracker t = ((LoLHistory) context.getApplicationContext()).getTracker(LoLHistory.TrackerName.APP_TRACKER);

    // create image folder if does not exist
    File imagesFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), context.getString(R.string.app_name));
    if (!imagesFolder.mkdirs() && !imagesFolder.isDirectory()) {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // failed to create and is not a directory. Something went wrong...
            t.send(new HitBuilders.EventBuilder()
                    .setCategory("FILE")
                    .setAction("CreateDirFailed")
                    .setLabel(imagesFolder.getPath())
                    .build());
        } else {
            t.send(new HitBuilders.EventBuilder()
                    .setCategory("FILE")
                    .setAction("CreateDirFailedMediaNotMounted")
                    .setLabel(imagesFolder.getPath())
                    .build());
        }
    }

    // delete image if already exists so FOS can create a new one
    File image = new File(imagesFolder, title + ".jpg");
    if (image.exists()) {
        // image already exists, deleting to start from clean state
        if (!image.delete()) {
            // failed to delete
            t.send(new HitBuilders.EventBuilder()
                    .setCategory("FILE")
                    .setAction("DeleteFailed")
                    .setLabel(image.getPath())
                    .build());
        }
    }

    // compress bitmap and write to file stream. FOS creates file if does not exist
    FileOutputStream out = null;
    try {
        out = new FileOutputStream(image);
        bitmapImage.compress(Bitmap.CompressFormat.JPEG, 50, out);
        out.flush();
    } catch (Exception e) {
        e.printStackTrace();
        t.send(new HitBuilders.ExceptionBuilder()
                .setDescription(e.getLocalizedMessage())
                .setFatal(true)
                .build());
    } finally {
        try {
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            t.send(new HitBuilders.ExceptionBuilder()
                    .setDescription(e.getLocalizedMessage())
                    .setFatal(true)
                    .build());
        }
    }

    // get Uri from saved image
    Uri uriSavedImage = Uri.fromFile(image);

    // media scan the new file so it shows up in the gallery
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    mediaScanIntent.setData(uriSavedImage);
    context.sendBroadcast(mediaScanIntent);
}


UPDATE: Since a lot of people are mentioning it, as stated earlier this issue is not due to having an overlay app installed. Under the Draw over other apps menu, I have the following applications: Google Play Music, Google Play services, Photos, TalkBack, Twitch, Twitter. All of these are set to No.

Additionally, I have tested other applications like Google Hangouts and Twitter which also have actions that require Dangerous Permissions and I am able to provide those permissions without this issue.


SOLUTION: I have marked R. Zagorski's answer as the solution as it includes a lot of general cases. For me it was actually a Toast that was breaking my permissions flow. This popup wasted so much time by sending me on the completely wrong path...

This is the Toast I had visible for the first few seconds after the permission popup showed up:

解决方案

This popup is caused by the manifest.PERMISSION.SYSTEM_ALERT_WINDOW permission declared by the manifest. The are 3 categories of permissions, that developer must be aware of.:

  1. Normal permission - do nothing with them, just declare in the Manifest
  2. Vulnerable permissions - declare in Manifest and ask for permission at first time. They can be changed through system settings
  3. Above dangerous permissions: SYSTEM_ALERT_WINDOW and WRITE_SETTINGS belong to this category. They must be granted, but are not visible in system settings. To request for it you don't use a standard way (int checkSelfPermission (String permission)) but you have to check Settings.canDrawOverlays() or Settings.System.canWrite() appropriately


If you don't have SYSTEM_ALERT_WINDOW permission:

  1. check if you have a Toast visible when interacting with the permissions popup. Though the Overlay Detected popup doesn't mention it, a Toast also counts as an overlay
  2. check if any of your dependencies require it.


If you're not sure if you're using this permission, there are a couple of test cases that you can do:

  1. Request this permission by yourself:

    public class MainActivity extends AppCompatActivity {
    
        public final static int REQUEST_CODE = 10101;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (checkDrawOverlayPermission()) {
                startService(new Intent(this, PowerButtonService.class));
            }
        }
    
        public boolean checkDrawOverlayPermission() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                return true;
            }
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, REQUEST_CODE);
                return false;
            } else {
                return true;
            }
        }
    
        @Override
        @TargetApi(Build.VERSION_CODES.M)
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == REQUEST_CODE) {
                if (Settings.canDrawOverlays(this)) {
                    startService(new Intent(this, PowerButtonService.class));
                }
            }
        }
    }
    

  2. Check if this or this is not your case

  3. Check out this post to be aware, that when installing app through Play Store this permission is automatically granted (I have not checked is, therefore cannot confirm)

The permission model can be understood, just sometimes requires more digging.

这篇关于检测到的屏幕覆盖阻止了 Android 权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆