विंडो जोड़ने में असमर्थ Android.view.ViewRoot$W@44da9bc0 - इस विंडो प्रकार के लिए अनुमति से इनकार कर दिया गया


82

मैंने इस पोस्ट को उदाहरण के लिए पसंद किया है, लेकिन मुझे विंडो मैनजर ऑब्जेक्ट में व्यूग्रुप को जोड़ने में त्रुटि मिली, मैंने सेवा के लिए उसी वर्ग का उपयोग किया है, जिस प्रश्न में कोई बदलाव नहीं है, जहां मैं गलती कर सकता हूं।

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

जवाबों:


154

में इस अनुमति का उपयोग करके देखें AndroidManifest.

android.permission.SYSTEM_ALERT_WINDOW

API पर = = 23 देखें


@ ceph3us क्या आप जानते हैं कि इसे कैसे प्राप्त करना है> = M? ActivityCompat.requestPokes (यह, नया स्ट्रिंग [] {Manifest.permission.SYSTEM_ALERT_WINDOW}, Perm.PERMISSIONS_REQUEST_SYSTEM_ALERT_WINDOW); कुछ भी आग नहीं करेगा। उसी के साथ: ActivityCompat.requestPches (यह, नया स्ट्रिंग [] {Manifest.permission.SYSTEM_ALERT_WINDOW}, Perm.PERMISSIONS_REQUEST_SYSTEM_ALERT_WINDOW);
मार्टिन फ़फ़र

इसके अतिरिक्त आपको अपने फोन पर सेटिंग्स से प्रोग्राम या तो मैन्युअल रूप से अनुमति देने की आवश्यकता हो सकती है। मैं Huawei Nexus 6p का उपयोग कर रहा था और अपने एप्लिकेशन के लिए सेटिंग्स में मैंने स्क्रीन सेक्शन के अन्य एप्लिकेशन पर ड्राइंग पर "Yes" पर क्लिक किया।
अमीर

इसे एक अच्छे समाधान के लिए देखें: github.com/facebook/react-native/issues/…
WiRa

144

" @ ceph3us क्या आप जानते हैं कि इसे कैसे प्राप्त किया जा सकता है = = M? ActivityCompat.requestPien (यह, नया स्ट्रिंग [] {Manifest.permission.SYSTEM_ALERT_WINDOW} ..."

  1. API_ = 23 पर SYSTEM_ALERT_WINDOW पेर्मिशन (अन्य ऐप्स पर ड्रा करें) आदि।

    • अब ऐप की अनुमतियां स्क्रीन में दिखाई नहीं देता है।
    • यह अजीब तरह से भ्रमित करने वाली नई "ऑल परमिशन" स्क्रीन में भी दिखाई नहीं देता है
  2. इस अनुमति के साथ Calling गतिविधि.requestPims (),

    • अनुमति / इनकार करने के लिए उपयोगकर्ता के लिए कोई संवाद नहीं दिखाएगा।
    • इसके बजाय, गतिविधि.onRequestPimsResult () कॉलबैक को एक अस्वीकृत ध्वज के साथ तुरंत कॉल किया जाएगा।

समाधान:

यदि एप्लिकेशन API स्तर 23 या उच्चतर को लक्षित करता है, तो ऐप उपयोगकर्ता को अनुमति प्रबंधन स्क्रीन के माध्यम से ऐप को यह अनुमति स्पष्ट रूप से देनी होगी। एप्लिकेशन कार्रवाई ACTION_MANAGE_OVERLAY_PERMISSION के साथ एक इरादे भेजकर उपयोगकर्ता की मंजूरी का अनुरोध करता है । एप्लिकेशन यह जाँच सकता है कि क्या सेटिंग.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 "-> अनुमतियों में। यह भी ... कि यह अनुमति दूसरों से अलग क्यों है के रूप में कोई स्पष्टीकरण। जिस तरह से हम इसके लिए अनुरोध करते हैं? - अनाम 12 फरवरी को 21:01 बजे "

कुछ अनुमतियाँ हैं जो सामान्य और खतरनाक अनुमतियों की तरह व्यवहार नहीं करती हैं। SYSTEM_ALERT_WINDOW और WRITE_SETTINGS विशेष रूप से संवेदनशील हैं, इसलिए अधिकांश ऐप उनका उपयोग नहीं करना चाहिए। यदि किसी ऐप को इन अनुमतियों में से किसी एक की आवश्यकता है, तो उसे प्रकट में अनुमति की घोषणा करनी चाहिए, और उपयोगकर्ता के प्राधिकरण का अनुरोध करने वाला एक इरादा भेजना चाहिए। सिस्टम उपयोगकर्ता को एक विस्तृत प्रबंधन स्क्रीन दिखाकर इरादे का जवाब देता है।

विशेष अनुमतियाँ

संपादित करें II:

मैंने इस कोड का उपयोग FragmentActivity को बढ़ाने वाली गतिविधि में किया है और मुझे अपवाद java.lang.IllegalArgumentException मिली है: केवल 16 बिट्स का उपयोग अनुरोधकोड के लिए कर सकते हैं क्योंकि उपयोग किया गया अनुरोध कोड 0 .. 65535 की सीमा में नहीं है। आप अपना अनुरोध कोड बदलने पर विचार कर सकते हैं एक उचित मूल्य। - मत्सहाकिस

यह सास के रूप में:

अनुरोध कोड 0 .. 65535 की सीमा में होना चाहिए ।

यह कारण है:

  • जावा में पूर्णांक 32 बिट्स द्वारा दर्शाया गया है
  • आपको अनुरोधकोड के लिए कम 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)

2
और उपयोगकर्ता इस अनुमति को कैसे अक्षम कर सकता है? यह सेटिंग में अनुमतियों में नहीं दिखता है-> ऐप्स -> "MyApp" -> अनुमतियां। इसके अलावा ... किसी भी स्पष्टीकरण के रूप में क्यों यह अनुमति दूसरों से अलग है जिस तरह से हम इसके लिए अनुरोध करते हैं?
बेनामी

1
मैंने इस कोड का उपयोग FragmentActivity को बढ़ाने वाली गतिविधि में किया था और मुझे अपवाद मिला java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCodeक्योंकि उपयोग किया गया अनुरोध कोड 0 .. 65535 की सीमा में नहीं है। आप अपने अनुरोध कोड को उचित मान में बदलने पर विचार कर सकते हैं।
मत्सहाकिस

1
इस अनुरोध कोड का उपयोग करें ....... सार्वजनिक अंतिम स्थिर int REQUEST_CODE = 5463 & 0xffffff00;
मुहम्मद आदिल

@MuhammadAdil यहाँ बिटवाइस का क्या उद्देश्य है? u मान 5376
ceph3us

@ ceph3us यहां हमें यह त्रुटि मिलती है अगर हम उस REQUEST_CODE ..... java.lang.IllegalArgumentException का उपयोग करते हैं: केवल अनुरोध 16 के लिए निचले 16 बिट्स का उपयोग कर सकते हैं ........ तो इसलिए मुझे इसे ठीक करना चाहिए।
मुहम्मद आदिल

3

चेतावनी संवाद को जोड़ने के लिए 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 takedown नीति चालू हो सकती है। सुनिश्चित करें कि आपके पास एक वैध औचित्य है यदि Google को इसकी आवश्यकता है।


Android 7.1.1 या इससे कम वाले फ़ोन के लिए TYPE_APPLICATION_OVERLAY लेकिन कुछ अन्य प्रकार (मेरे मामले में TYPE_PHONE) का उपयोग नहीं करने से मुझे अपने मामले में इस pesky BadTokenException से छुटकारा पाने में मदद मिली। देखें stackoverflow.com/questions/32224452/...
मार्टिन Vysny

-8

आप अपने लक्ष्य एसडीके को 22 या उससे कम में बदल सकते हैं, फिर यह एपीआई 23 पर भी काम करता है।

इसे Gradle.Build में बदलें।


3
@ हेलक यह शायद सबसे अच्छा समाधान नहीं है, लेकिन इसे इंगित करना अच्छा है।
क्वार्क

यह समस्या को ठीक नहीं करेगा, यह एक त्वरित समाधान है जिसका आप उपयोग कर सकते हैं लेकिन आप एपि> 23 को लक्षित नहीं कर सकते हैं
हारून
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.