20

I'm trying to create a system overlay. But I keep getting "permission denied". I'm using SDK version 23.

My manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test" >

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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".activity.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

The code I use to create the overlay:

    //mView = new HUDView(this);
    mButton = new Button(this);
    mButton.setText("Overlay button");
    mButton.setOnTouchListener(this);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
            WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
            PixelFormat.TRANSLUCENT);
    params.gravity = Gravity.RIGHT | Gravity.TOP;
    params.setTitle("Load Average");
    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    wm.addView(mButton, params);
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
Tom
  • 472
  • 1
  • 6
  • 12
  • Possible duplicate of [Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type](http://stackoverflow.com/questions/7569937/unable-to-add-window-android-view-viewrootw44da9bc0-permission-denied-for-t) – ceph3us Nov 13 '16 at 18:11

7 Answers7

35

First, there is no permission named SYSTEM_OVERLAY_WINDOW. It is SYSTEM_ALERT_WINDOW.

Second, if your targetSdkVersion is 23 or higher, and you are running on Android 6.0+ devices, your app will not get this permission at the outset. Call Settings.canDrawOverlays() to see if you have the permission, and use ACTION_MANAGE_OVERLAY_PERMISSION to lead the user over to Settings if you do not.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I change the permission to SYSTEM_ALERT_WINDOW but that didn't fixed the issue. So i'm trying to implement your second suggestion. But how do i use ACTION_MANAGE_OVERLAY_PERMISSION to lead the user over to Settings? – Tom Sep 18 '15 at 13:24
  • 2
    @VeryEvilBetty: That's an `Intent` action. `startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))` should bring up an activity where the user can opt into allowing your app to draw over the screen. – CommonsWare Sep 18 '15 at 13:27
  • Is there at least a way to enable overlaying only for my app, without requesting the user to go search for my app among all the others? Ideally, a small popup, as with Permissions, would be the best thing. Any way to do that? – Meymann Nov 12 '15 at 10:07
  • @Meymann: Not that I am aware of, sorry. And even if there were, [they might ban you from the Play Store for using it](https://commonsware.com/blog/2015/11/11/google-anti-trust-issues.html) if they do not feel that it is justified. – CommonsWare Nov 12 '15 at 12:56
  • @Meymann Just add settingsIntent.setData(Uri.parse("package:" + getPackageName())); to the intent, this will open the detailed page of your app in that settings list – Ion Aalbers Dec 11 '15 at 13:12
  • Worked.Had to call startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)); and then WindowManager overlay functionality. – Ahmad Shahwaiz Nov 03 '16 at 15:23
  • @CommonsWare Got this **/Window: You must attach your view to the given frame in onCreateAndAttachView()** on 7.0 or above, any idea? tried various solutions its not working – Nisarg Nov 27 '17 at 12:08
  • @Nisarg: I suggest that you ask a separate Stack Overflow question, where you can provide a [mcve]. That would include the full Java stack trace, plus your code that is triggering the error. – CommonsWare Nov 27 '17 at 12:12
27

In AndroidManifest (for version < 23)

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


public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE= 5469;
//Random value

    public void testPermission() {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
        }
    }

Result :

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
        if (Settings.canDrawOverlays(this)) {
            // You have permission
        }
    }
}
Anthone
  • 2,156
  • 21
  • 26
  • in official site it says that we can do same for API v23, did u try this code on 23 ? http://developer.android.com/reference/android/provider/Settings.html#canDrawOverlays(android.content.Context) – MBH Nov 21 '15 at 10:06
  • Yes you can. Just the permission in manifest is for version <23, It's ignore for version 23 because of Runtime ask permission. The reste of my anwser is for both. – Anthone Nov 23 '15 at 08:33
  • i checked the list of runtime permissions, SYSTEM_ALERT_WINDOW is not on the list. I guess the only solution to guide user on how to grant the permission! – MBH Nov 23 '15 at 08:39
  • They are 3 level of permission. http://developer.android.com/guide/topics/security/permissions.html#normal-dangerous SYSTEM_ALERT_WINDOW is in dangerous permission. http://developer.android.com/reference/android/Manifest.permission.html#SYSTEM_ALERT_WINDOW – Anthone Nov 23 '15 at 16:45
  • 1
    @Anthone I've tried your code and `Settings.canDrawOverlays(this)` returns `false` in the `onActivityResult` method. When calling it later, returns `true`. Seems like the change is done asynchronously. Is there a way to get notified when user changes this setting? – Piotr Aleksander Chmielowski Feb 14 '18 at 16:03
  • @PiotrAleksanderChmielowski Hum to my knoledge, it's not possible – Anthone Mar 13 '18 at 19:28
  • 1
    *Note:* on some devices on Android 8.0 and 8.1 `Settings.canDrawOverlays(this)` may return always `false` when a user just enabled the permission and got back to your app. It may take 5-7 seconds before this method will return the real value `true`. Check this answer on how to bypass this known bug: https://stackoverflow.com/questions/46173460/why-in-android-o-method-settings-candrawoverlays-returns-false-when-user-has – Kirill Karmazin Apr 08 '19 at 20:04
0

You can also lead the user over to the specific app's overlaying page. The documentation states:

Input: Optionally, the Intent's data URI can specify the application package name to directly invoke the management GUI specific to the package name. For example "package:com.my.app".

So something like:

intent.setData(Uri.fromParts("package", getPackageName(), null));
Nonos
  • 2,450
  • 2
  • 23
  • 34
0

As an alternative solution, you can try WindowManager.LayoutParams.TYPE_TOAST instead of WindowManager.LayoutParams.TYPE_SYSTEM_ALERT. This not requires any permission. I'm using it to show image, maybe button will work to

Arkady
  • 624
  • 1
  • 8
  • 17
0

for users below and above android 8 use

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
   LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
arwTheDev
  • 109
  • 1
  • 4
0

I handled all of the overlay permissions for every android version in my library. Please see the gist here. enter image description here

Gk Mohammad Emon
  • 6,084
  • 3
  • 42
  • 42
0

For Display over the other apps permissions is required to add in the manifest is

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

To check your app has permission

Settings.canDrawOverlays(context)

To check permission checkOverlayPermission

private const val CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084

private fun checkOverlayPermission(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
        //If the draw over permission is not available open the settings screen
        //to grant the permission.
        val intent = Intent(
            Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
            Uri.parse("package:$packageName")
        )
        startActivityForResult(
            intent,
            CODE_DRAW_OVER_OTHER_APP_PERMISSION
        )
    }
}

And in onActivityResult you can check permission is granted or not

override fun onActivityResult(
    requestCode: Int,
    resultCode: Int,
    data: Intent?
) {
    if (requestCode == CODE_DRAW_OVER_OTHER_APP_PERMISSION) {
        if (Settings.canDrawOverlays(this)) {
            // Permission Granted
        } else {
            // Permission not Granted
            // If you want then call again checkOverlayPermission until permission granted
        }
    } 
}
Upendra Shah
  • 2,218
  • 17
  • 27