web-dev-qa-db-ja.com

ウィンドウAndroid.view.ViewRoot$W@44da9bc0を追加できません-このウィンドウタイプの許可は拒否されました

this postを好むが、viewgroupをwindowmanagerオブジェクトに追加する際にエラーが発生し、質問に投稿したものと同じクラスを変更せずに使用しましたそれを得ない

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
81
Pratik

AndroidManifest.でこの権限を使用してみてください

Android.permission.SYSTEM_ALERT_WINDOW

API> = 23を参照

154
Lalit Poptani

"@ 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"->許可の許可に表示されません。また...この許可の理由に関する説明リクエストの方法が他の方法と異なりますか?–匿名2月12日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)
137
ceph3us

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が必要とする場合に備えて、正当な正当性があることを確認してください。

3