Googles Android/ Notifications

Aus Wikibooks

Zurück zu Googles Android

Wenn auf einem Android-Telefon ein Anruf eintrifft, wird automatisch die Telefon-Activity aufgerufen. Wie das grundsätzlich funktioniert, haben wir im Kapitel „BroadcastReceiver“ gesehen. In den meisten Fällen ist es aber kein gutes GUI-Design wenn Activities plötzlich den Vordergrund dominieren. Trifft beispielsweise eine SMS ein, dann werden wir darüber, wie in der der folgenden Abbildung 1, durch ein kleines Icon oben links in der Statusleiste informiert.

Diese so genannte Notification kann noch durch einen Vibrationsalarm, eine Audiosignal oder eine blinkende LED begleitet werden. Wenn wir die Statusleiste wie in der Abbildung 2 nach unten ziehen, sehen wir eine kleine Activity, die zur Notification gehört. Wenn wir diese Activity anklicken gelangen wir zur eigentlichen SMS-Activity (Abbildung 3).

Ein Beispiel[Bearbeiten]

So eine Notification wollen wir hier entwickeln. Ganz ähnlich wie im Kapitel über BroadcastReceiver wird der Broadcast, der ausgelöst wird, wenn ein Anwender die Zeitzone ändert, abgefangen. In unserem Beispiel verschickt der Receiver dieses Mal eine Notification. Wenn der Anwender diese Notification anklickt, wird er zu einer Activity geführt, die die Zeitzone – in Großbuchstaben – anzeigt.

In der onReceive-Methode unseres Broadcast-Receivers, mit dem wir Änderungen an der Zeitzone verarbeiten (siehe auch das Kapitel über BroadcastReceiver) erzeugen wir mit Hilfe eines Konstruktors der Klasse Notification [1] eine Notification:

public class TimeChangedReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    int icon = android.R.drawable.ic_dialog_alert;
    String title = "Settings Changed";
    String text = "User select new timezone";
    long when = System.currentTimeMillis();
    String timezone = intent.getStringExtra("time-zone");
    Notification notification = new Notification(icon, title, when);
  }
}

Die Parameter des Konstruktors bedürfen einer kurzen Erläuterung.

  • Jede Notification wird durch ein Symbol (icon) in der Statusleiste repräsentiert, dessen Code wir aus der Ressourcenklasse R erhalten.
  • Zusammen mit dem Symbol wird ein Kurztitel in der Statusleiste angezeigt (title).
  • Außerdem geben wir noch die Uhrzeit (when) an, zu der die Notification rausgeht.

Der Notification-Manager[Bearbeiten]

An unserem Telefon tut sich jetzt aber noch nichts. Die Notification muss einem Objekt vom Typ NotificationManager[2] übergeben werden, der die Notification bearbeitet und sie in geeigneter Form zur Anzeige bringt.

...
NotificationManager mgr =
  (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int notidication_id = (int) System.currentTimeMillis();
mgr.notify(notidication_id, notification);

Es gibt im Android-System verschiedene Manager-Klassen, die der Kontext über die getSystemService-Methode zur Verfügung stellt.

So bekommen wir auch den NotificationManager, über den wir dann die Notification mit der Methode notify[3] (die nichts mit der gleichnamigen Methode der Klasse Object zu tun hat) verschicken.

  • Der erste Parameter, den wir dieser Methode übergeben, ist eine Zahl, die Android verwendet, um Notifications zu unterscheiden. Wenn wir hier immer die gleiche Zahl verwenden würden, dann würden auch alle Notifications wie eine einzige erscheinen.
  • Der zweite Parameter ist die eigentliche Notification.

Wenn wir die Notifications wie beschrieben versenden, erhalten wir noch zur Laufzeit einen Fehler. Wir haben es nämlich versäumt eine Activity anzugeben, die uns beim Anklicken der Notification – ähnlich wie in Abbildung 3 – angezeigt werden soll.

Intents und Pending-Intents[Bearbeiten]

Da wir die Activity verzögert ausführen wollen, müssen wir sie irgendwie 'einpacken'. Auf den ersten Blick scheint dazu ein Intent bestens geeignet zu sein.

...
Intent notificationIntent = new Intent(context, UpperActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.putExtra("time-zone", timezone);

Auf diese Weise haben wir schon häufiger Intents erzeugt. Hier werden auch wieder Extras übergeben und ein Flag gesetzt, damit die Activity in einem eigenen DVM-Prozess ausgeführt wird.

Diesen Intent definieren wir in unserem Beispiel aber in der onReceive-Methode eines BroadcastRecevier-Objektes. Nach dem Ende der Methode müssen wir davon ausgehen, dass der zugehörige DVM-Prozess nicht mehr existiert und die Activity, die wir in dem Intent verpackt haben, nicht mehr gestartet werden kann. Wir können den Intent und damit die Activity aber konservieren, indem wir sie in ein Objekt vom Typ PendingIntent (siehe auch das Kapitel „Intents“) einbetten:

...
PendingIntent contentIntent =
  PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT );        
  • Der erste Parameter repräsentiert ein Objekt vom Typ Context,
  • Der zweite wird derzeit (Android 2.2) noch nicht ausgewertet,
  • Im dritten ist der Intent hinterlegt und
  • Im vierten, wird beschrieben, was beim Anklicken der Notification passieren soll. Hier haben wir uns für die Variante FLAG_ONE_SHOT entschieden: Nur der erste Klick führt uns zur Activity.

Unsere Notification können wir um einen Pending-Intent erweitern. In dem Fall wird nicht nur eine Mitteilung angezeigt, sondern die Mitteilung auch mit einer Activity verbunden. Diese Activity ist im Pending-Intent definiert, den wir jetzt zur Notification hinzufügen.

...
notification.setLatestEventInfo(context, title, text, contentIntent);
mgr.notify(notidication_id, notification);

Es ist zu sehen, dass die Notification, die weiter oben erzeugt wurde, mittels setLastestEventInfo[4] um ein PendingIntent-Objekt erweitert wird und dass danach der NotificationManager gebeten wird, diese Notification anzuzeigen.

Alles zusammen[Bearbeiten]

Wenn wir die Code-Fragmente dieses Kapitels zusammensetzen, ergibt sich die folgende Receiver-Klasse

public class TimeChangedReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    int icon = android.R.drawable.ic_dialog_alert;
    String title = "Settings Changed";
    String text = "User select new timezone";
    long when = System.currentTimeMillis();
    String timezone = intent.getStringExtra("time-zone");

    Notification notification = new Notification(icon, title, when);
        
    NotificationManager mgr =
      (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    int notidication_id = (int) System.currentTimeMillis();
    Intent notificationIntent = new Intent(context, UpperActivity.class);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    notificationIntent.putExtra("time-zone", timezone);
    PendingIntent contentIntent =
      PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT );        
    notification.setLatestEventInfo(context, title, text, contentIntent);
    mgr.notify(notidication_id, notification);

}

Die Gestaltung der sehr einfachen Klasse UpperActivity sowie die Erfassung der Komponenten im Manifest haben wir bereits mehrfach erläutert. Diese abschließenden Schritte bleiben dem Leser zur Übung überlassen.

Einzelnachweise[Bearbeiten]

  1. http://developer.android.com/reference/android/app/Notification.html#Notification%28%29. Stand 14. Nov. 2010
  2. http://developer.android.com/reference/android/app/NotificationManager.html
  3. http://developer.android.com/reference/android/app/NotificationManager.html#notify%28java.lang.String,%20int,%20android.app.Notification%29. Stand 14. Nov. 2010
  4. http://developer.android.com/reference/android/app/Notification.html#setLatestEventInfo(android.content.Context,%20java.lang.CharSequence,%20java.lang.CharSequence,%20android.app.PendingIntent)