07 March 2021
© Денис Колисниченко
Приложения могут отображать два типа уведомлений: краткие всплывающие сообщения (Toast Notification) и постоянные напоминания (Status Bar Notification). Первые отображаются на экране мобильного устройства какое-то время и не требуют внимания пользователя. Как правило, это не критические информационные уведомления. Вторые постоянно отображаются в строке состояния и требуют реакции пользователя.
Например, приложение требует подключение к вашему серверу. Если соединение успешно установлено, можно отобразить краткое уведомление, а вот если подключиться не получилось, тогда отображается постоянное уведомление, чтобы пользователь сразу мог понять, почему приложение не работает.
Чтобы отобразить всплывающее сообщение, используйте класс Toast и его методы makeText (создает текст уведомления) и show (отображает уведомление):
Context context = getApplicationContext();
Toast toast = Toast.makeText(context, "This is notification",
Toast.LENGTH_LONG);
toast.show();
Первый параметр метода makeText() — это контекст приложения, который можно получить с помощью вызова getApplicationContext(). Второй параметр — текст уведомления. Третий — задает продолжительность отображения уведомления:
r LENGTH_SHORT — небольшая продолжительность (1—2 секунды) отображения текстового уведомления;
r LENGTH_LONG — показывает уведомление в течение более длительного периода времени (примерно 4 секунды).
По умолчанию всплывающее уведомление появится в нижней части экрана. Чтобы отобразить уведомление в другом месте (специально для dkws.org.ua), можно воспользоваться методом setGravity(), который нужно вызвать до метода show():
toast.setGravity(Gravity.CENTER, 0, 0);
Первый параметр задает размещение в пределах большего контейнера, например, GRAVITY.CENTER, GRAVITY.TOP и т. д. Второй параметр — это смещение по оси X, третий — смещение по оси Y.
В нашем примере уведомление будет отображено по центру окна.
Теперь немного практики. Создайте новый проект (пусть он называется Test6 — для совместимости с моим кодом), разметку можете не изменять, а можете вообще удалить все элементы деятельности. Наше приложение отобразит при запуске уведомление (рис. 1).
Рис. 1. Всплывающее уведомление
Java-код приложения представлен в листинге 1.
Листинг 1. Отображение всплывающего уведомления
package com.samples.test6;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import android.content.Context;
import android.view.Gravity;
public class Test6Activity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Context context = getApplicationContext();
Toast toast = Toast.makeText(context, "This is notification", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
Создать уведомление в строке состояния немного сложнее. А тем более в современных версиях Android. Ведь раньше для создания таких уведомлений использовались классы Notification и NotificationManager. В Android 4 и 5 вместо класса Notification нужно использовать класс Notification.Builder. В листинге 6.2а приводится старая версия кода, а в листинге 6.2б - новая (чтобы вы могли сравнить).
Листинг 6.2а. Старая версия кода (классы Notification и NotificationManager)
int NOTIFY_ID = 101;
Context context = getApplicationContext();
NotificationManager Mgr = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int icon = R.drawable.icon;
CharSequence cText = "Ошибка!";
long t = System.currentTimeMillis();
Notification notify = new Notification(icon, cText, t);
CharSequence nTitle = "Ошибка";
CharSequence nText = "Не могу подключиться к серверу";
Intent intent = new Intent(this, Test6Activity.class);
PendingIntent cIntent = PendingIntent.getActivity(this, 0, intent, 0);
notify.setLatestEventInfo(context, nTitle, nText, cIntent);
Mgr.notify(NOTIFY_ID, notify);
Листинг 6.2б. Новая версия кода для Android 4 и 5 (класс Notification.Builder)
package com.glava.glava6;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.content.Context;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.res.*;
public class MainActivity extends ActionBarActivity {
private static final int NOTIFY_ID = 101;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context context = getApplicationContext();
Intent notificationIntent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,
0, notificationIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = context.getResources();
Notification.Builder builder = new Notification.Builder(context);
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher)
// большая картинка
// .setLargeIcon(R.drawable.ic_launcher)
//.setTicker(res.getString(R.string.warning)) // текст в строке состояния
.setTicker("Ошибка!")
.setWhen(System.currentTimeMillis()
.setAutoCancel(true)
// Заголовок уведомления
.setContentTitle("Ошибка!")
// Текст уведомления
.setContentText("Не могу подключиться к серверу");
Notification n = builder.getNotification();
//Notification n = builder.build();
nm.notify(NOTIFY_ID, n);
}
}
Как вы заметили, в листинге 6.2б приводится полный код приложения, а не его фрагмент. Код хоть и хорошо закомментирован, но есть некоторые нюансы, которые вам следует знать. Метод setSmallIcon() формирует маленькую картинку уведомления, а setLargeIcon() - большую. Я большую не указывал, поскольку мне было лень ее готовить для демо проекта. Однако в реальном приложении вы будете использовать этот метод. Метод setTicker() устанавливает текст сообщения в строке состояния, которое исчезнет, как только вы просмотрите уведомление, останется только картинка, заданная с помощью setSmallIcon(). Методы setContentTitle() и setContentText() задают, соответственно, заголовок и текст уведомления.
Метод getNotification() уже считается устаревшим и вместо него нужно использовать метод build(). Однако метод build() вы можете использовать, только если минимальный уровень API в настройках проекта будет 16 (Android 4.1.2). Поэтому если вы пишете приложение для самых современных версий Android, устанавливайте минимальный уровень API 16 или выше (© Денис Колисниченко dkws.org.ua) и используйте метод build(). Если же вам нужно написать приложение, которое должно работать пусть не в самых древних версиях (та же 4.0 - это API 15), тогда используйте метод getNotification() и не обращайте внимание на предупреждение об устаревшем коде. Приложения с этим методом будут нормально выполняться и на более новых версиях Android. Результат наших стараний приведен на рис. 6.2.
Рис. 6.2. Уведомление в строке состояния (Android 4.4)
Но это еще не все. Вы можете отменить собственные уведомления, когда в них уже нет необходимости (например, ваша программа уже может установить соединение с сервером, а уведомление об ошибке все еще продолжает "висеть" в строке уведомления):
nm.cancel(NOTIFY_ID); // nm - экземпляр класса NotificationManager
Если нужно в уведомлении выводить индикатор прогресса (вы видели такой при установке программ из Play Market), используйте метод setProgress():
setProgress(100, 75, false);
При появлении уведомления можно заставить смартфон звучать (SOUND), вибрировать (VIBRATE), а также мерцать (LIGHT). Для всего этого используются следующие константы:
r Notification.DEFAULT_SOUND
r Notification.DEFAULT_VIBRATE
r Notification.DEFAULT_LIGHTS
Нужное поведение задается так:
notification.defaults = Notification.DEFAULT_SOUND |
Notification.DEFAULT_VIBRATE;
Если вам нужно все и сразу, используйте константу Notification.DEFAULT_ALL. Для доступа к виброзвонку в файл манифеста нужно добавить строчку:
<uses-permission android:name="android.permission.VIBRATE"/>