Окно оверлей системы Android

Я пытаюсь создать оверлей системы. Но я продолжаю получать "разрешение отказано". Я использую SDK версии 23.

Мой файл манифеста:

<?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>

Код, который я использую для создания наложения:

    //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);

Ответ 1

Во-первых, нет разрешения с именем SYSTEM_OVERLAY_WINDOW. Это SYSTEM_ALERT_WINDOW.

Во-вторых, если ваш targetSdkVersion равен 23 или выше, и вы работаете на устройствах Android 6.0+, ваше приложение не получит это разрешение с самого начала. Вызовите Settings.canDrawOverlays(), чтобы узнать, есть ли у вас разрешение, и используйте ACTION_MANAGE_OVERLAY_PERMISSION, чтобы привести пользователя к настройкам, если вы этого не сделаете.

Ответ 2

В AndroidManifest (для версии < 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);
        }
    }

Результат:

@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
        }
    }
}

Ответ 3

Вы также можете перевести пользователя на конкретную страницу наложения приложений. Документация указывает:

Ввод: Необязательно, URI данных Intent может указывать имя пакета приложения, чтобы напрямую вызвать GUI управления, специфичный для имени пакета. Например, "package: com.my.app".

Так что-то вроде:

intent.setData(Uri.fromParts("package", getPackageName(), null));

Ответ 4

В качестве альтернативного решения вы можете попробовать WindowManager.LayoutParams.TYPE_TOAST вместо WindowManager.LayoutParams.TYPE_SYSTEM_ALERT. Это не требует разрешения.  Я использую его для показа изображения, возможно, кнопка будет работать для

Ответ 5

для пользователей ниже и выше использование Android 8

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
   LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}