2010-09-28 14 views
14

Tengo problemas para mostrar AlertDialog desde el Servicio. Puedo mostrar la ventana de diseño personalizada usando Toast o usando WindowManager (TYPE_SYSTEM_ALERT o TYPE_SYSTEM_OVERLAY). Pero, no quiero usar un diseño personalizado, prefiero usar una buena GUI de AlertDialog directamente.Mostrar AlertDialog como ventana de superposición del sistema desde el Servicio

Escenario:

  • Ejecución de Servicio. No hay actividad activa presente.
  • En algún evento externo, Servicio envía una notificación
  • Cuando el usuario pulse notificación, el servicio es informado a través de PendingIntent y AlertDialog se debe mostrar (creados con AlertDialog.Builder(this))

error:

ERROR/AndroidRuntime(1063): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application 

Búsqueda la respuesta me llevó a la impresión de que estoy intentando algo que actualmente no es posible (Android 2.2). O tal vez lo es.

+0

Posible duplicado de [diálogo Alerta de servicio de Android] (http://stackoverflow.com/questions/3599563/alert-dialog-from-android-service) – araks

Respuesta

25

Se ha encontrado una solución que coincide con el escenario descrito.

  • Nueva actividad se ha creado y se inició desde el servicio. Sin embargo, es actividad con fondo translúcido. Tal actividad no tiene la línea super.setContentView() en onCreate(). Más importante, para garantizar la transparencia

    @android: Estilo/Theme.Translucent

se introduce bajo la etiqueta Tema para esta actividad en AndroidManifest.xml interfaz gráfica de usuario. Así, la nueva línea añade al manifiesto XML es

android:theme="@android:style/Theme.Translucent"

  • En onCreate() visualización real de AlertDialog se produce

  • Press el AlertDialog botones provoca diálogo y la Actividad de cierre y el envío de la Intención (o uso de algún otro medio) para entregar el resultado al Servicio.

  • Asegúrese de haber definido setOnDismissListener() para el cuadro de diálogo (la implementación debe llamar a finish() en la actividad). Si no lo haces, presiona la tecla Atrás para cancelar el diálogo, pero te deja en la actividad actual que es transparente y mira al usuario como si algo estuviera realmente mal.

+0

Zelimir, muchas gracias. Tengo el mismo problema y estoy buscando exactamente esto. – Amitku

+0

Me alegra que haya sido útil. Atentamente. – Zelimir

+0

Por favor corrígeme si me equivoco. no es el problema con translúcido es que es solo un espejo de lo que está detrás? p.ej. si está sobre la pantalla de llamada entrante. Realmente no puedes contestar el teléfono ¿verdad? porque tu actividad lo está bloqueando (¿aunque es translúcido?) – Guy

6

Gracias por su solución. Me enfrenté al mismo problema y resolví con su ayuda.

Puse esta respuesta solo para compartir mi manera de pasar el resultado al servicio.

No creé ninguna clase de intención personalizada adicional y resolví el problema del pase de resultados por solo Intent.putExtra() métodos con algunos trucos.

En el servicio, utilice este código para iniciar el DialogActivity que muestra el cuadro de diálogo de alerta en onCreate().

Intent intent = new Intent(this.getApplicationContext(), DialogActivity.class); 
intent.putExtra(DialogActivity.CLASS_KEY, this.getClass().getCanonicalName()); 
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(intent); 

Y en el DialogActivity, terminar de esta manera:

private void returnOk(boolean ok) { 
    Intent srcIntent = this.getIntent(); 
    Intent tgtIntent = new Intent(); 
    String className = srcIntent.getExtras().getString(CLASS_KEY); 
    Log.d("DialogActivity", "Service Class Name: " + className); 
    ComponentName cn = new ComponentName(this.getApplicationContext(), className); 
    tgtIntent.setComponent(cn); 
    tgtIntent.putExtra(RESULT_KEY, ok ? RESULT_OK : RESULT_CANCEL); 
    this.startService(tgtIntent); 
    this.finish(); 
} 

Por fin, en el servicio, reemplazar el método onStartCommand() y obtener el resultado del intento.

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    int ret = super.onStartCommand(intent, flags, startId); 
    Bundle extras = intent.getExtras(); 
    if (extras != null) { 
     int result = extras.getInt(DialogActivity.RESULT_KEY, -1); 
     if (result >= 0) { 
      if (result == DialogActivity.RESULT_OK) { 
       // Your logic here... 
      } 
     } else { 
      // Your other start logic here... 
     } 
    } 
    return ret; 
} 

No estoy seguro si esta es una buena solución, al menos me sirve. Espero que esto sea útil para alguien más como yo.

La fuente completo se puede encontrar aquí:

+2

Usar startService() para devolver el resultado es una mejor solución que usar broadcast. Regularmente uso ese enfoque. – Zelimir

+0

Hola ¿Por qué me dicen cuál es la constante CLASS_KEY aquí? – ekjyot

+0

CLASS_KEY es solo una cadena que funciona como un nombre para el valor que pone en el intento. – Programus

Cuestiones relacionadas