46

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

enter image description here

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:

enter image description here

Community
  • 1
  • 1
alexgophermix
  • 3,785
  • 5
  • 30
  • 54
  • If I had to guess, I'd say the issue lies elsewhere in your app. Are you using a SystemAlertWindow anywhere? Do you have any transparent screens being drawn over the top of anything, perhaps in a separate service, activity or fragment? – Tim Malseed Aug 29 '16 at 22:03
  • No SystemAlertWindow. Happens on standalone activities as well as fragments of a view pager. Almost all views within the app contain either a `ScrollView` or a `ListView` wrapped by a `android.support.v4.widget.SwipeRefreshLayout` – alexgophermix Aug 30 '16 at 16:36
  • 2
    In my case it was the Toast as well. Thanks! – Felix D. Sep 30 '16 at 18:03
  • 1
    In my case too it was the Toast. Can't thank enough. – Mustafa sabir Sep 05 '17 at 07:39

8 Answers8

59

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.

Community
  • 1
  • 1
R. Zagórski
  • 18,351
  • 5
  • 59
  • 86
  • I haven't found the solution yet, but I think you've set me on the right track. I tried removing a bunch of dependencies and suddenly the popup didn't show up. I didn't check which dependencies I removed so I'm going through one by one and pulling them out until the overlay detected popup is gone again. If possible please highlight that component of your answer as I think it will be the source of at least some issues. – alexgophermix Sep 06 '16 at 19:08
  • 5
    WOW the issue was caused by a `Toast`. This popup sent me on the completely wrong track... If a `Toast` is visible when you try to interact with the permissions popup you'll get this overlay detected popup... Android, why? – alexgophermix Sep 06 '16 at 19:45
  • 3
    A very unusual case. Indeed, when looking at the `Toast` source code: [Line 1](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/Toast.java#408) and [Line 2](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/Toast.java#432), the `Toast` view is pinned to the global `WindowManager` invoked on application or activity context. I would have never thought, that the simple `Toast` might cause such problems. – R. Zagórski Sep 06 '16 at 20:06
  • 8
    A Toast?? Seriously Android?? Things are breaking because of your built in convenience notifications system !?!??!?! – HaydenKai Oct 25 '16 at 21:36
  • Thanks, same here as well. A simple toast which I was displaying if the user hadn't enabled the permission, was causing the issue. – steliosf Jul 11 '17 at 16:18
  • In my case, a simple toast msg is making this issue – Sarun1001 Dec 27 '17 at 13:03
12

It's not an issue, You just have an overlay app installed, The most common are

  • Facebook Messenger
  • Whatsapp with Pop-up enabled
  • Seebye Chat heads
  • Viber
  • Any app that shows a menu or something on the screen is an Overlay App.

just close it, Then try.

Ahmed I. Elsayed
  • 1,753
  • 2
  • 10
  • 27
2

This popup became an issue with the inclusion of the permissions manager in Android Marshmallow. If you have any apps installed on you phone that have permission to overlay on the screen there are a number of permission settings, File access included, that you can't change without disabling those screen overlay permissions first. For me, my text app and the facebook messenger app are the culprits. Every time I want to give any other app the requested permissions I have to click the Open Settings option on that popup and revoke the screen overlay access for the two aforementioned apps, then reopen the app in question to get the permission prompt again. Then I have to re-enable the overlay permissions again if I want my message popups or my chat heads. It's really annoying. I think your app is fine, android's permissions management is just a confusing mess.

  • While I totally agree the current system is a mess (I wish I never switched from target SDK 22) this isn't the issue for me. I currently have all my apps under "Draw over other apps" as disallowed. As mentioned other apps I have used that request permissions don't seem to be affected so I'm suspecting maybe there's an issue with my app and the error message is sending me in the wrong direction. – alexgophermix Aug 30 '16 at 19:22
  • I've disabled ALL the apps and I still get the error message. I even disabled the overlay permission for all the System Apps – Jonathan Sep 07 '16 at 23:17
2

When a screen overlay is detected, System will not allow you to continue to granting permissions for apps. Because the screen overlay can receive the input of user. So you have to disable all the "screen overlay" things before granting permissions for your apps. It is not the problem of your app. All apps that have target SDK 23 get this problem.

TOP
  • 2,354
  • 5
  • 26
  • 55
  • 1
    I tried disabling all the overlays and it still shows the same error. On other apps e.g. hangouts when I request the same permission it doesn't show this popup – alexgophermix Sep 01 '16 at 00:08
2

Usually, this is caused by the use a floating app.

For Samsung Android Phone users:

Open the Settings
Then Applications > Application manager
Press on More > Apps that can appear on top

If you find an app with a bubble, display screen overlay. If an app adjusts your phone’s brightness, disable screen overlay option on those apps as well. Point is, you have to figure out the culprit app and disable screen overlay.

Source: Fix Screen Overlay Detected Error On Android

Certified
  • 21
  • 1
0

I googled for so many solution but nothing worked. Then I tried with all the options in settings :)

Finally I can give you definite way to disable overlay -

Go to Setting > Application > Default application > Device Assistance > "Turn of Read Text on screen" option

Pankaj
  • 748
  • 10
  • 33
0

I've fixed this issue by installing Alert Window Checker: https://play.google.com/store/apps/details?id=jp.sfapps.alertwindowchecker. It indicates you which applications are currently using the screen overlay feature.

In my case, I had to disable the swipe detector in application ES FileExplorer to fix this issue

bma350
  • 881
  • 7
  • 9
0

Restarting my phone worked for me.

Yatin
  • 2,348
  • 6
  • 20
  • 38