2010-09-28 6 views
14

L'affichage de AlertDialog à partir du service présente un problème. Je suis capable d'afficher la fenêtre de disposition personnalisée en utilisant Toast ou en utilisant WindowManager (TYPE_SYSTEM_ALERT ou TYPE_SYSTEM_OVERLAY). Mais, je ne veux pas utiliser la mise en page personnalisée, je préfère utiliser une belle interface graphique AlertDialog directement.Affichage de AlertDialog en tant que fenêtre de recouvrement du système à partir du service

Scénario:

  • service en cours. Aucune activité active présente.
  • Sur un événement externe, service envoie une notification
  • Lorsque la notification de presse de l'utilisateur, le service est informé par PendingIntent et AlertDialog doit être affiché (créé avec AlertDialog.Builder(this))

Erreur:

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

Recherche car la réponse me conduit à l'impression que j'essaie quelque chose qui n'est actuellement pas possible (Android 2.2). Ou peut-être que c'est.

+0

double possible de [boîte de dialogue d'alerte du service Android] (http://stackoverflow.com/questions/3599563/alert-dialog-from-android-service) – araks

Répondre

25

Une solution correspondant au scénario décrit a été trouvée.

  • Une nouvelle activité a été créée et démarrée à partir du service. Cependant, c'est une activité avec un fond translucide. Une telle activité n'a pas la ligne super.setContentView() dans onCreate(). Plus important encore, pour assurer la transparence

    @android: Style/Theme.Translucent

est entré sous étiquette Thème pour cette activité dans l'interface graphique AndroidManifest.xml. Ainsi, la nouvelle ligne ajoutée au manifeste XML est

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

  • Dans onCreate() affichage réel de AlertDialog se produit

  • Appuyez sur les boutons AlertDialog provoque la fermeture de dialogue et de l'activité et l'envoi de l'intention (ou utilisation d'autres moyens) pour livrer les résultats au Service.

  • Assurez-vous que vous avez défini setOnDismissListener() pour la boîte de dialogue (l'implémentation doit appeler finish() sur l'activité). Si vous ne le faites pas, appuyez sur la touche Retour pour annuler la boîte de dialogue mais vous laisse dans l'activité en cours qui est transparente et regarde l'utilisateur comme si quelque chose ne va pas.

+0

Zelimir, merci beaucoup. J'ai le même problème et je suis exactement à la recherche de cela. – Amitku

+0

Je suis content que cela ait été utile. Meilleures salutations. – Zelimir

+0

S'il vous plaît corrigez-moi si je me trompe. n'est pas le problème avec translucide, c'est que c'est juste un miroir de ce qui est derrière? par exemple. si c'est sur l'écran d'appel entrant. Vous ne pouvez pas vraiment répondre au téléphone, n'est-ce pas? parce que votre activité le bloque (bien que translucide?) – Guy

6

Nous vous remercions de votre solution. J'ai fait face au même problème et j'ai travaillé avec votre aide.

Je mets cette réponse juste pour partager ma façon de transmettre le résultat au service.

Je n'ai créé aucune classe d'intention personnalisée supplémentaire et j'ai résolu le problème de passage des résultats par les méthodes Intent.putExtra() avec quelques astuces.

Dans le service, utilisez ce code pour démarrer le DialogActivity qui affiche la boîte de dialogue d'alerte dans 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); 

Et dans le DialogActivity, finir comme ça:

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(); 
} 

Enfin, dans le service, remplacer la méthode onStartCommand() et obtenir le résultat de l'intention. Je ne suis pas sûr si cette façon est une bonne solution, au moins cela fonctionne pour moi. J'espère que cela sera utile pour quelqu'un d'autre comme moi.

se trouve la source complète ici:

+2

L'utilisation de startService() pour retourner le résultat est une meilleure solution que l'utilisation de broadcast. J'utilise régulièrement cette approche. – Zelimir

+0

Salut CAn vous pls me dire ce qui est la constante CLASS_KEY ici – ekjyot

+0

CLASS_KEY est juste une chaîne qui fonctionne comme un nom pour la valeur que vous mettez dans l'intention. – Programus

Questions connexes