Android: no se puede agregar ventana. Permiso denegado para este tipo de ventana

Estoy trabajando en una aplicación donde necesito mostrar una ventana con información sobre la pantalla de locking (KeyGuard) sin desbloquear el teléfono. Pensé que probablemente podría hacerlo con WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG

Pero cada vez que mi aplicación se bloquea con el siguiente error:

android.view.WindowManager $ BadTokenException: no se puede agregar la ventana android.view.ViewRootImpl$W@40ec8528 – permiso denegado para este tipo de ventana

Estas publicaciones ( aquí , aquí y aquí ) dan la misma respuesta. Para agregar el siguiente permiso en el archivo Manifest.

android.permission.SYSTEM_ALERT_WINDOW

Solución que he implementado pero sigo recibiendo el mismo error. ¿Alguna idea de lo que estoy haciendo mal?

Aquí están los permisos en mi archivo de manifiesto:

           

Y este es el código que uso para agregar la ventana a la pantalla de locking

 WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); LayoutInflater mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); mView = mInflater.inflate(R.layout.lock_screen_notif, null); WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, PixelFormat.TRANSLUCENT ); wm.addView(mView, params); 

Alguien tiene alguna idea?

PD Estoy probando en un HTC Desire 620 DS con Android 4.4.2

Por razones completamente obvias, las aplicaciones normales no pueden crear ventanas arbitrarias en la parte superior de la pantalla de locking . ¿Qué crees que podría hacer si creara una ventana en tu pantalla de locking que pudiera imitar perfectamente la pantalla de locking real para que no pudieras notar la diferencia?

El motivo técnico de su error es el uso del indicador TYPE_KEYGUARD_DIALOG ; requiere android.permission.INTERNAL_SYSTEM_WINDOW que es un permiso de nivel de firma. Esto significa que solo las aplicaciones firmadas con el mismo certificado que el creador del permiso pueden usarlo.

El creador de android.permission.INTERNAL_SYSTEM_WINDOW es el sistema Android en sí, así que a menos que tu aplicación sea parte del sistema operativo, no tienes ninguna posibilidad.

Existen formas bien definidas y bien documentadas de notificar al usuario de la información de la pantalla de locking . Puede crear notificaciones personalizadas que se muestran en la pantalla de locking y el usuario puede interactuar con ellas.

si usa apiLevel >= 19 , no use

 WindowManager.LayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT 

que obtiene el siguiente error:

android.view.WindowManager $ BadTokenException: no se puede agregar la ventana android.view.ViewRootImpl$W@40ec8528 – permiso denegado para este tipo de ventana

Use esto en su lugar:

 LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL 

Supongo que deberías diferenciar el objective (antes y después de Oreo)

 int LAYOUT_FLAG; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else { LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE; } params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, LAYOUT_FLAG, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); 

Hice todo lo posible para probar todos los ejemplos disponibles para este problema. Finalmente obtuve la respuesta para esto. No sé cuánto es confiable, pero mi aplicación no está fallando ahora.

 windowManager = (WindowManager)getSystemService(WINDOW_SERVICE); //here is all the science of params final LayoutParams myParams = new LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_SYSTEM_ERROR, WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, PixelFormat.TRANSLUCENT ); 

En tu archivo de manifiesto solo da el permiso

   

Además de esto, también puedes verificar el nivel API si es> = 23 y luego

  if(Build.VERSION.SDK_INT >= 23) { if (!Settings.canDrawOverlays(Activity.this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, 1234); } } else { Intent intent = new Intent(Activity.this, Service.class); startService(intent); } 

Espero que ayude a alguien en alguna parte. Ejemplo completo https://anam-android-codes.blogspot.in/?m=1

Para Android API nivel de 8.0.0, debe utilizar

WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

en lugar de LayoutParams.TYPE_TOAST o TYPE_APPLICATION_PANEL o SYSTEM_ALERT.

TYPE_SYSTEM_OVERLAY finalmente mostrar una ventana en la pantalla de locking con el uso de TYPE_SYSTEM_OVERLAY lugar de TYPE_KEYGUARD_DIALOG . Esto funciona como se espera y agrega la ventana en la pantalla de locking.

El problema con esto es que la ventana se agrega a todo lo que posiblemente pueda. Es decir, la ventana incluso aparecerá en la parte superior de su teclado / locking de patrón en caso de pantallas de locking seguras. En el caso de una pantalla de locking no segura, aparecerá en la parte superior de la bandeja de notificaciones si la abre desde la pantalla de locking.

Para mí, eso es inaceptable. Espero que esto pueda ayudar a cualquier otra persona que enfrenta este problema.

Buscar

Dibuja sobre otras aplicaciones

en su configuración y habilite su aplicación. Para Android 8 Oreo, prueba

Configuración> Aplicaciones y notificaciones> Información de la aplicación> Mostrar en otras aplicaciones> Habilitar

LayoutParams.TYPE_PHONE está en desuso. He actualizado mi código como estos.

 parameters = if (Build.VERSION.SDK_INT > 25) { LayoutParams( minHW * 2 / 3, minHW * 2 / 3, LayoutParams.TYPE_APPLICATION_OVERLAY, LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT) }else { LayoutParams( minHW * 2 / 3, minHW * 2 / 3, LayoutParams.TYPE_PHONE, LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT) } 

LayoutParams.TYPE_APPLICATION_OVERLAY requiere api nivel 26 o superior.

cambie su marca de Windowmanger indicador “TYPE_SYSTEM_OVERLAY” a “TYPE_APPLICATION_OVERLAY” en su proyecto para hacer compatible con Android O

WindowManager.LayoutParams.TYPE_PHONE a WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY