Powiadomienie to wiadomość, która może wyświetlić się w systemie
poza naszą aplikacją. To ważna cecha i należy o niej pamiętać zawsze wtedy, gdy chcemy użytkownika o czymś poinformować. Niezależnie jak to zrobimy, nasza informacja może zarówno pokazać się w naszym programie jak i w innej używanej aplikacji. Same notyfikacje dzielimy na dwa typy:
Toasty, czyli proste i krótkie informacje pojawiające się na dole, oraz na
Notification, czyli typowe, pełno wymiarowe powiadomienia na pasku. Dziś postaram się oba te typy omówić.

Informacja: Nie radzisz sobie z kodem? Coś Ci nie wychodzi lub nie działa? Zgubiłeś się? W tym miejscu zobaczysz pełen kod aplikacji oraz zapiszesz go na dysk.
1. Powiadomienia
Kolejny raz muszę was uprzedzić o zmianach, jakie zaszły w systemie od wprowadzenia nowego API. Tym razem to
Android 4.1 namieszał w dokumentacji, przez co czytając oficjalne porady możemy się pogubić w różnych wersjach. My jednak będziemy dążyli starą ścieżką tworzenia notyfikacji, nie przejmując się póki co nowymi dodatkami (bo użytkownik ich i tak nie zauważy na Androidzie 4.0 i wcześniejszych) jak powiadomienia ze zdjęciem. Niewymagane jest zatem korzystanie z dodatkowych bibliotek.
Podstawowe, normalne powiadomienie wygląda mniej więcej tak jak powyżej. Możemy ustalić tytuł (i subtytuł w drugiej linii), dodać ikonę czy wyświetlić liczbę podobnych akcji. Oczywiście nadal istnieje możliwość tworzenia swoich layoutów (o tym powiem w drugiej części), tak jak ma to miejsce na przykład w odtwarzaczach muzyki.
Toast natomiast to małe okienko z prostą informacją do przekazania w obecnej chwili. Niestety, od początku systemu nie zmieniło się ono ani trochę (w przeciwieństwie do normalnych powiadomień), przez co jest to jedna z bardziej denerwujących rzeczy w systemie. Dlaczego? Jak pisałem wcześniej, notyfikacja o akcji może pokazać się poza naszą aplikacją, więc informacja na przykład o braku połączenia czy błędzie z jednego programu może pojawić się w drugim, poprawnie działającym, a użytkownik nie wie skąd ta informacja pochodzi.
2. Tworzenie powiadomienia
Wymienione wyżej powiadomienia tworzymy w różnysposób, więc rozdzielę tą część na dwie mniejsze.
Tworzenie Notification
Podobnie jak przy
Dialogach, tak i tutaj powiadomienia posiadają swoją podstawową klasę do obsługi zdarzeń. W tym wypadku jest to
NotificationCompat, i tak jak wcześniej - nigdy nie powinniśmy korzystać z możliwości tego obiektu bezpośrednio. Od tego są specjalne subklasy jak na przykład
Builder (
NotificationCompat.
Builder), na którym opieramy tworzenie powiadomienia. Ogólnie patrząc na oba poznane już
Buildery zauważymy, że są one do siebie bardzo podobne.
Zatem, aby stworzyć nowe powiadomienie typu
Notification musimy skorzystać z
Buildera i jego opcji. Tworzymy więc w naszym testowym programie nowe
Activity, w którym będziemy testować możliwości systemu...
View_Notifications:
package com.example.moja.pierwsza.aplikacja;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class View_Notifications extends Activity implements OnClickListener {
Button notificationFull;
Button notificationToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_notifications);
notificationFull = (Button) findViewById(R.id.bt_view_notifications_full);
notificationToast = (Button) findViewById(R.id.bt_view_notifications_toast);
notificationFull.setOnClickListener(this);
notificationToast.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_view_notifications_full:
// Normalne powiadomienie
break;
case R.id.bt_view_notifications_toast:
// Toast
break;
}
}
}
view_notifications.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button_view_notifications_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Notification" />
<Button
android:id="@+id/button_view_notifications_toast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Toast" />
</LinearLayout>
... oraz dodajemy podstawowego Buildera.
package com.example.moja.pierwsza.aplikacja;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class View_Notifications extends Activity implements OnClickListener {
Button notificationFull;
Button notificationToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_notifications);
notificationFull = (Button) findViewById(R.id.bt_view_notifications_full);
notificationToast = (Button) findViewById(R.id.bt_view_notifications_toast);
notificationFull.setOnClickListener(this);
notificationToast.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_view_notifications_full:
// Normalne powiadomienie
// Nasz builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
break;
case R.id.bt_view_notifications_toast:
// Toast
break;
}
}
}
Kolejnym krokiem jest dodanie do powiadomienia podstawowych (
wymaganych!) opcji. Są to kolejno tytuł, ikona oraz opis. Aby to zrobić, używamy kolejno metod
setContentTitle(),
setSmallIcon() oraz
setContentText() na naszym
Builderze. Korzystając z kolejnych funkcji możecie przyjrzeć się możliwościom jakie oferuje nam ten element.
package com.example.moja.pierwsza.aplikacja;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class View_Notifications extends Activity implements OnClickListener {
Button notificationFull;
Button notificationToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_notifications);
notificationFull = (Button) findViewById(R.id.bt_view_notifications_full);
notificationToast = (Button) findViewById(R.id.bt_view_notifications_toast);
notificationFull.setOnClickListener(this);
notificationToast.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_view_notifications_full:
// Normalne powiadomienie
// Nasz builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
// Dodajemy podstawowe (wymagane) elementy
mBuilder.setContentTitle("Tytuł powiadomienia");
mBuilder.setContentText("Opis powiadomienia");
mBuilder.setSmallIcon(R.drawable.ic_launcher);
break;
case R.id.bt_view_notifications_toast:
// Toast
break;
}
}
}
Ważną częścią powiadomienia jest również
akcja. Nie jest to wymagana część, ale w końcu nasza wyświetlona informacja ma do czegoś służyć. Tutaj decyzja o tym co ma się wydarzyć po wybraniu jednej z opcji należy wyłącznie do was. Na potrzeby poradnika stworzę coś prostego -
po kliknięciu po prostu otworzona zostanie nasza aplikacja jeszcze raz. Jak się do tego zabrać? Bardzo prosto - tworząc nowego
Intenta (z opcjami) i przypisując jego zadanie do czegoś, co nazywa się
PendingIntent.
Cóż to takiego? Najzwyklejszy opis, który zawiera zarówno zwykły
Intent jak i dane aplikacji, która go wywołała. Dzięki temu system (lub jakiś inny program) wie co ma zrobić po otrzymaniu obiektu tego typu. Dodatkowym atutem
PendingIntentu jest to, że może on posiadać prawa, na mocy których inne elementy Androida mogą dołączać się do naszego programu i korzystać z jego możliwości i zasobów.
Wracając jednak do kodu naszego powiadomienia. Chcemy powtórnie otworzyć naszą aplikację, jeżeli wybrane zostanie powiadomienie. Tworzymy więc
Intent ze wskazaniem na odpowiednią klasę, po czym dołączamy całość do
PendingIntentu, który znowu przypisany zostanie do jednej z akcji
Buildera (
setContentIntent()).
package com.example.moja.pierwsza.aplikacja;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class View_Notifications extends Activity implements OnClickListener {
Button notificationFull;
Button notificationToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_notifications);
notificationFull = (Button) findViewById(R.id.bt_view_notifications_full);
notificationToast = (Button) findViewById(R.id.bt_view_notifications_toast);
notificationFull.setOnClickListener(this);
notificationToast.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_view_notifications_full:
// Normalne powiadomienie
// Nasz builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
// Dodajemy podstawowe (wymagane) elementy
mBuilder.setContentTitle("Tytuł powiadomienia");
mBuilder.setContentText("Opis powiadomienia");
mBuilder.setSmallIcon(R.drawable.ic_launcher);
// Tworzymy intent
Intent mIntent = new Intent(this, View_Main.class);
PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0, mIntent, 0);
// I go łączymy
mBuilder.setContentIntent(mPendingIntent);
break;
case R.id.bt_view_notifications_toast:
// Toast
break;
}
}
}
Opisaliśmy już główne części powiadomienia.
Czas je wyświetlić. Jak to zrobić? Jak już nie raz dziś pisałem,
nasze notyfikacje obsługiwane są przez system a nie przez nas samych. Zatem należy skorzystać z jednego z rozwiązań Androida, w tym przypadku
NotificationManagera, aby mieć możliwość utworzenia powiadomienia na pasku. Czym on jest, nie trzeba tłumaczyć. Ten element po prostu dba o wyświetlanie powiadomień w odpowiednim czasie.
Aby powiadomić
Managera o nowo stworzonym wydarzeniu, należy skorzystać z jednej z metod -
notify.
package com.example.moja.pierwsza.aplikacja;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class View_Notifications extends Activity implements OnClickListener {
Button notificationFull;
Button notificationToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_notifications);
notificationFull = (Button) findViewById(R.id.bt_view_notifications_full);
notificationToast = (Button) findViewById(R.id.bt_view_notifications_toast);
notificationFull.setOnClickListener(this);
notificationToast.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_view_notifications_full:
// Normalne powiadomienie
// Nasz builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
// Dodajemy podstawowe (wymagane) elementy
mBuilder.setContentTitle("Tytuł powiadomienia");
mBuilder.setContentText("Opis powiadomienia");
mBuilder.setSmallIcon(R.drawable.ic_launcher);
// Tworzymy intent
Intent mIntent = new Intent(this, View_Main.class);
PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0, mIntent, 0);
// I go łączymy
mBuilder.setContentIntent(mPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
break;
case R.id.bt_view_notifications_toast:
// Toast
break;
}
}
}
Po wybraniu przycisku w
Activtiy utworzone zostanie nowe powiadomienie.
Tworzenie Toast
Tworzenie
Toastu jest dużo prostsze, głównie dla tego, że sama notyfikacja nie jest tak skomplikowana i rozbudowana.
Sam Toast posiada tylko dwie opcje do skonfigurowania - tekst, jaki ma zostać wyświetlony, oraz przedział czasowy, w jakim ma być widoczne okienko. Aby jeszcze bardziej sprawę uprościć, przedziału czasowego nie możemy zdefiniować ręcznie - musimy skorzystać z dwóch rodzajów: długo (TOAST_LONG) albo krótko (TOAST_SHORT) widoczne powiadomienie.
package com.example.moja.pierwsza.aplikacja;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class View_Notifications extends Activity implements OnClickListener {
Button notificationFull;
Button notificationToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_notifications);
notificationFull = (Button) findViewById(R.id.bt_view_notifications_full);
notificationToast = (Button) findViewById(R.id.bt_view_notifications_toast);
notificationFull.setOnClickListener(this);
notificationToast.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_view_notifications_full:
// Normalne powiadomienie
// Nasz builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
// Dodajemy podstawowe (wymagane) elementy
mBuilder.setContentTitle("Tytuł powiadomienia");
mBuilder.setContentText("Opis powiadomienia");
mBuilder.setSmallIcon(R.drawable.ic_launcher);
// Tworzymy intent
Intent mIntent = new Intent(this, View_Main.class);
PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0, mIntent, 0);
// I go łączymy
mBuilder.setContentIntent(mPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
break;
case R.id.bt_view_notifications_toast:
// Toast
Toast.makeText(this, "Toast!", Toast.LENGTH_SHORT).show();
break;
}
}
}
Ot to wszystko. Niestety czasu mu nie starczy aby bardziej omówić ten temat, więc powiadomienia z własnym layoutem zostawię na jutro.