[android] 창 android.view.ViewRoot$W@44da9bc0을 추가 할 수 없습니다.이 창 유형에 대한 권한이 거부되었습니다.

내가 선호가 변화없이 질문에 게시 된 내가 그것을 gettting하지 않은 실수 할 수있는 예를 들어 게시물을하지만 난 창 관리자 객체로 뷰 그룹 추가에서 오류가 발생했습니다, 나는 서비스에 대해 동일한 클래스를 사용했다

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params); // here

WindowManger에 뷰를 추가하면

여기 내 매니페스트 파일입니다

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.searce.testoverlay"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name="TestOverlayActivity"
                      android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        <service android:enabled="true" android:name=".HUD"></service>
    </application>
</manifest>

오류

09-27 18:49:23.561: ERROR/AndroidRuntime(653): Uncaught handler: thread main exiting due to uncaught exception
09-27 18:49:23.571: ERROR/AndroidRuntime(653): java.lang.RuntimeException: Unable to create service com.searce.testoverlay.HUD: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2790)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.access$3200(ActivityThread.java:119)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1917)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.os.Looper.loop(Looper.java:123)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.main(ActivityThread.java:4363)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at java.lang.reflect.Method.invokeNative(Native Method)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at java.lang.reflect.Method.invoke(Method.java:521)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at dalvik.system.NativeStart.main(Native Method)
09-27 18:49:23.571: ERROR/AndroidRuntime(653): Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRoot$W@44da9bc0 -- permission denied for this window type
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.view.ViewRoot.setView(ViewRoot.java:492)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at com.searce.testoverlay.HUD.onCreate(HUD.java:41)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2780)
09-27 18:49:23.571: ERROR/AndroidRuntime(653):     ... 10 more



답변

이 권한을 사용하십시오. AndroidManifest.

android.permission.SYSTEM_ALERT_WINDOW

API> = 23 참조


답변

@ ceph3us> = M에 대해 달성하는 방법을 알고 있습니까? ActivityCompat.requestPermissions (this, new String [] {Manifest.permission.SYSTEM_ALERT_WINDOW} …”

  1. API의 SYSTEM_ALERT_WINDOW PERMISSION> = 23 (다른 앱 위에 그리기 등) :

    • 더 이상 앱의 권한 화면에 나타나지 않습니다.
    • 이상하게 혼동되는 새로운 “모든 권한”화면에도 나타나지 않습니다.
  2. 이 권한으로 Activity.requestPermissions () 호출,

    • 사용자에게 허용 / 거부 대화 상자가 표시되지 않습니다.
    • 대신 Activity.onRequestPermissionsResult () 콜백이 거부 된 플래그와 함께 즉시 호출됩니다.

해결책:

앱이 API 레벨 23 이상을 대상으로하는 경우 앱 사용자는 권한 관리 화면을 통해 앱에이 권한을 명시 적으로 부여해야합니다. 앱 은 ACTION_MANAGE_OVERLAY_PERMISSION 작업과 함께 인 텐트를 전송하여 사용자의 승인을 요청합니다 . 앱은 Settings.canDrawOverlays ()를 호출하여이 권한이 있는지 확인할 수 있습니다.

예제 코드 :

/** code to post/handler request for permission */
public final static int REQUEST_CODE = -1010101; *(see edit II)*

public void checkDrawOverlayPermission() {
    /** check if we already  have permission to draw over other apps */
    if (!Settings.canDrawOverlays(Context)) {
        /** 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 (Settings.canDrawOverlays(this)) {
           // continue here - permission was granted 
       }
    }
}

“사용자가이 권한을 어떻게 비활성화 할 수 있습니까? 설정-> 앱->”MyApp “-> 권한의 권한에 표시되지 않습니다. 또한 …이 권한이 다른 권한과 다른 이유에 대한 설명 요청하는 방법은 무엇입니까? – Anonymous Feb 12 at 21:01 “

정상적이고 위험한 권한처럼 작동하지 않는 몇 가지 권한이 있습니다. SYSTEM_ALERT_WINDOW 및 WRITE_SETTINGS는 특히 민감하므로 대부분의 앱에서 사용해서는 안됩니다. 앱에 이러한 권한 중 하나가 필요한 경우 매니페스트에서 권한을 선언하고 사용자의 승인을 요청하는 인 텐트를 보내야합니다. 시스템은 사용자에게 세부 관리 화면을 표시하여 의도에 응답합니다.

특별 권한

편집 II :

FragmentActivity를 확장하는 활동에서이 코드를 사용했는데 예외 java.lang.IllegalArgumentException : 사용 된 요청 코드가 0 .. 65535 범위에 있지 않기 때문에 requestCode에 대해 하위 16 비트 만 사용할 수 있습니다. 요청 코드를 다음으로 변경하는 것을 고려할 수 있습니다. 적절한 값. – mtsahakis

말 그대로 :

요청 코드0 .. 65535 범위에 있어야합니다 .

이것은 때문입니다.

  • Java의 정수는 32 비트로 표시됩니다.
  • requestCode에 대해 하위 16 비트를 사용할 수 있습니다.
  • 다른 비트는 요청 처리에 사용됩니다.

예를 들면 :

integer value:  5463             ///hi 16 bits //   |    // lo 16 bits //
as binary string will look like: 0000 0000 0000 0000 0001 0101 0101 0111

주어진 범위의 간단한 사용 코드

편집 III :

AOSP API 26을 대상으로하는 앱용 (Android oreo / 8+)

SYSTEM_ALERT_WINDOW 권한을 사용하는 앱은 더 이상 다음 창 유형을 사용하여 다른 앱 및 시스템 창 위에 경고 창을 표시 할 수 없습니다.

TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR

대신 앱은 TYPE_APPLICATION_OVERLAY라는 새 창 유형을 사용해야합니다.

TYPE_APPLICATION_OVERLAY

창 유형 : 응용 프로그램 오버레이 창은 모든 활동 창 (FIRST_APPLICATION_WINDOW와 LAST_APPLICATION_WINDOW 사이의 유형) 위에 표시되지만 상태 표시 줄 또는 IME와 같은 중요한 시스템 창 아래에 표시됩니다.

시스템은 사용자의 시각적 혼란을 줄이고 리소스를 관리하기 위해 언제든지 이러한 창의 위치, 크기 또는 가시성을 변경할 수 있습니다.

SYSTEM_ALERT_WINDOW 권한이 필요합니다.

시스템은이 창 유형을 사용하여 프로세스의 중요성을 조정하여 메모리 부족으로 인해 프로세스를 죽일 가능성을 줄입니다. 다중 사용자 시스템에서는 소유 사용자의 화면에만 표시됩니다.

WindowManager.LayoutParams wLp = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
      ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
      : WindowManager.LayoutParams.TYPE_PHONE;

Window.setAttributes(WindowManager.LayoutParams)


답변

경고 대화 상자를 추가하는 ceph3us 응답에 따라 제대로 작동했습니다.

final AlertDialog dialog = dialogBuilder.create();
                final Window dialogWindow = dialog.getWindow();
                final WindowManager.LayoutParams dialogWindowAttributes = dialogWindow.getAttributes();

                // Set fixed width (280dp) and WRAP_CONTENT height
                final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
                lp.copyFrom(dialogWindowAttributes);
                lp.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 280, getResources().getDisplayMetrics());
                lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
                dialogWindow.setAttributes(lp);

                // Set to TYPE_SYSTEM_ALERT so that the Service can display it
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    dialogWindow.setType(WindowManager.LayoutParams.TYPE_TOAST);
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    dialogWindow.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
                }
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
                {
                    dialogWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                }
                dialog.show();

하지만 TYPE_SYSTEM_ALERT를 사용하면 위험한 권한을 사용하는 앱에 대한 Google 게시 중단 정책이 트리거 될 수 있습니다. Google에서 요구하는 경우에 대비하여 유효한 근거가 있는지 확인하십시오.


답변

대상 SDK를 22 이하로 변경할 수 있으며 API 23에서도 작동합니다.

Gradle.Build에서 변경하십시오.


답변