/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Для начала рассмотрим простейший пример отправки уведомления на часы из собственной программы. Часы могут принимать уведомления не только о новых письмах, смс, звонках. Также вы можете уведомить хозяина часов, что пора кормить кота. В конце концов технология Notification была разработана именно для этих целей.
Создадим новый проект. В файле build.gradle (app) добавим строчку:
compile 'com.android.support:support-v4:21.0.+'
Синхронизируем файлы. Добавьте кнопку с атрибутом android:onClick="onClick" для щелчка. Наша задача - послать простенькое уведомление на часы по нажатию кнопки.
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
public void onClick(View view) {
int notificationId = 001;
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Мяу!")
.setContentText("А кота кто кормить будет?");
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(MainActivity.this);
notificationManager.notify(notificationId, notificationBuilder.build());
}
Запускаем проект и смотрим на результат.
На телефоне также будет уведомление. Таким образом из нашего приложения уведомления посылаются всем подходящим устройствам.
Можно применить стили BigTextStyle или InboxStyle.
public void onClick(View view) {
int notificationId = 001;
NotificationCompat.BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
bigStyle.bigText("А кота кто кормить будет?");
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Мяу!")
.setStyle(bigStyle);
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(MainActivity.this);
notificationManager.notify(notificationId, notificationBuilder.build());
}
На уведомление можно повесить кнопку действия, добавив интерактивности. Кнопка действия связывается с ожидающим намерением PendingIntent. Переделаем предыдущий пример.
public void onClick(View view) {
// Создадим намерение для просмотра карт
Intent mapIntent = new Intent(Intent.ACTION_VIEW);
Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode("Murmanks"));
mapIntent.setData(geoUri);
PendingIntent mapPendingIntent =
PendingIntent.getActivity(this, 0, mapIntent, 0);
int notificationId = 001;
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Мяу!")
.setContentText("А кота кто кормить будет?")
.addAction(android.R.drawable.ic_menu_mylocation,
"Open map", mapPendingIntent);
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(MainActivity.this);
notificationManager.notify(notificationId, notificationBuilder.build());
}
Запускаем снова. Теперь на уведомлении (на часах) будут две маленькие точки, сигнализирующие нам о наличии дополнительного экрана. Смахиваем экран влево и видим значок и текст. Нажимаем на значок и на телефоне откроются карты с показом города Мурманска. Видимо там находится кот, которого следует накормить.
На телефоне у уведомления также будет второй значок для действия.
Если вы хотите, чтобы кнопка действия появилась только на часах, а на телефоне её не было, то вместо метода addAction() следует использовать метод extend(), в котором указать NotificationCompat.WearableExtender.
public void onClick(View view) {
Intent mapIntent = new Intent(Intent.ACTION_VIEW);
Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode("Murmanks"));
mapIntent.setData(geoUri);
PendingIntent mapPendingIntent =
PendingIntent.getActivity(this, 0, mapIntent, 0);
int notificationId = 001;
// Create the action
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_mylocation,
"Open map", mapPendingIntent)
.build();
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Мяу!")
.setContentText("А кота кто кормить будет?")
.extend(new NotificationCompat.WearableExtender().addAction(action));
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(MainActivity.this);
notificationManager.notify(notificationId, notificationBuilder.build());
}
Класс WearableExtender позволяет задавать специальные настройки для уведомлений, которые поступают на часы. Для этого нужно создать экземпляр WearableExtender и указать необходимые настройки для часов. Далее создать экземпляр NotificationCompat.Builder и указать настройки для уведомления. Затем вызвать метод extend(), который присоединит настройки для часов к настройкам для уведомлений. Завершает операцию метод build().
В предыдущем пример мы уже использовали этот способ. Следующий пример покажет, как можно убрать значок приложения из уведомления.
public void onClick(View view) {
int notificationId = 001;
// Настройки для часов
NotificationCompat.WearableExtender wearableExtender =
new NotificationCompat.WearableExtender()
.setHintHideIcon(true);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Мяу!")
.setContentText("А кота кто кормить будет?")
.extend(wearableExtender);
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(MainActivity.this);
notificationManager.notify(notificationId, notificationBuilder.build());
}
Кроме метода setHintHideIcon() вы можете вдобавок использовать метод setBackground() для создания фона у уведомления на часах.
Для фона нужно использовать картинку размером 400x400 для статичного фона и 640x400 для фона, поддерживающего эффект параллакса. Разместите эти картинки в папке res/drawable-nodpi модуля app. Другие картинки, которые вы будете использовать в уведомлениях для часов, следует размещать в папке res/drawable-hdpi модуля app.
// Конвертируем Drawable в Bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.grumpy);
// Настройки для часов
NotificationCompat.WearableExtender wearableExtender =
new NotificationCompat.WearableExtender()
.setHintHideIcon(true)
.setBackground(bitmap);
Картинка во время убирания уведомления.
Чтобы узнать, скрыт ли значок у уведомления, используйте метод getHintHideIcon()
NotificationCompat.WearableExtender wearableExtender =
new NotificationCompat.WearableExtender(notif);
boolean hintHideIcon = wearableExtender.getHintHideIcon();
Если одного экрана для уведомления вам мало, то можете создать страницы для дополнительной информации и присоединить их к уведомлению.
public void onClick(View view) {
int notificationId = 001;
// Create an intent for the reply action
Intent replyIntent = new Intent(this, NotificationActivity.class);
PendingIntent viewPendingIntent =
PendingIntent.getActivity(this, 0, replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// Build the notification via WearableExtender
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Важное сообщение")
.setContentText("А кота кто кормить будет?")
.setContentIntent(viewPendingIntent)
.extend(new NotificationCompat.WearableExtender());
// Создадим стиль большого текста для второй страницы
NotificationCompat.BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
secondPageStyle.setBigContentTitle("Страница 2")
.bigText("Голодные коты осуждают вас...");
// Создаём вторую страницу для уведомления
Notification secondPageNotification =
new NotificationCompat.Builder(this)
.setContentTitle("Страница 2")
.setStyle(secondPageStyle)
.build();
// Расширяем notification builder для использования второй страницы
Notification notification = notificationBuilder
.extend(new NotificationCompat.WearableExtender()
.addPage(secondPageNotification))
.build();
// Выводим
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(MainActivity.this);
notificationManager.notify(notificationId, notification);
}
Метод setBigContentTitle("Страница 2") у меня не выводил текст в эмуляторе, поэтому я продублировал его в методе setContentTitle().
Теперь на часах появится обычное уведомление, лёгким движением руки влево переходим на вторую страницу. Далее вы можете либо вернуться на первую страницу, либо продолжить листать до третьей страницы, где можно открыть уведомление на телефоне и до четвёртой страницы, где можно заблокировать уведомления от данного приложения. Последние две страницы создаются самой системой.
Во всех примерах использовался менеджер NotificationManagerCompat из библиотеки совместимости вместо обычного NotificationManager. Это связано с тем, что некоторые настройки NotificationCompat.WearableExtender доступны только там. Поэтому рекомендуется использовать именно этот менеджер.