W serii „Twoja aplikacja” będę pokazywał, w jaki sposób stworzyć aplikację kompletną wraz z najważniejszymi komponentami. Taka aplikacja będzie posiadać wszystkie podstawowe rzeczy, która powinna mieć. Seria będzie podzielona na części, a każda część będzie zawierać poszczególne zagadnienie.
W tej serii stworzymy aplikację do odtwarzania muzyki wraz z najważniejszymi komponentami.
- Część 1: MediaSession i MediaController
- Cześć 2: AudioFocus
- Cześć 3: Powiadomienia
Wiesz już czym jest MediaSsesion, MediaController i AudioFocus. Cała aplikacja nie byłaby kompletna bez powiadomień. W tym wpisie własnie zajmiemy się tym zagadnieniem.
1. Kod klasy powiadomień.
Stwórz klasę podobną do tej:
public class MediaNotificationHelper { private final NotificationManager mNotificationManager; private MediaSessionHelper mMediaSession; private PlayerService mService; private static final int NOTIFICATION_ID = 404; private static final String CHANNEL_ID = "MUSIC_CHANNEL"; private int playbackState; public MediaNotificationHelper(PlayerService serv) { this.mService = serv; mNotificationManager = (NotificationManager) mService.getSystemService(Context.NOTIFICATION_SERVICE); } public void updateNotification(int state) { playbackState = state; switch (playbackState) { case PlaybackStateCompat.STATE_PLAYING: { mService.startForeground(NOTIFICATION_ID, createNotification() ); break; } case PlaybackStateCompat.STATE_PAUSED: { NotificationManagerCompat.from(mService).notify(NOTIFICATION_ID, createNotification()); mService.stopForeground(false); break; } default: { mService.stopForeground(true); break; } } } private Notification createNotification() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { createNotificationChannel(); } // Get album art MediaControllerCompat mController = new MediaControllerCompat(mService, mMediaSession.getmMediaSession()); MediaMetadataCompat mMetadata = mController.getMetadata(); MediaDescriptionCompat description = mMetadata.getDescription(); Bitmap art; String url = description.getIconUri().toString(); if (url != null) { art = Image.getBitmap(url); }else { art = BitmapFactory.decodeResource(mService.getResources(), R.drawable.art); } // Open application after clicking on Notification Intent intent = new Intent(mService, MediaControllersActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(mService, 0, intent, 0); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mService, CHANNEL_ID); addActions(notificationBuilder); notificationBuilder .setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle() .setShowActionsInCompactView(1) .setMediaSession(mMediaSession.getMediaSessionToken()) // For API < 21 // Show "X" button .setShowCancelButton(true) .setCancelButtonIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(mService, PlaybackStateCompat.ACTION_STOP))) .setShowWhen(false) .setPriority(NotificationCompat.PRIORITY_LOW) .setVisibility(Notification.VISIBILITY_PUBLIC) .setContentIntent(contentIntent) // .setDeleteIntent(stopService) .setColor(ContextCompat.getColor(mService, R.color.colorPrimaryDark)) .setContentTitle(description.getTitle()) .setContentText(description.getSubtitle()) .setLargeIcon(art) .setSmallIcon(R.mipmap.ic_launcher); return notificationBuilder.build(); } private void addActions(NotificationCompat.Builder notificationBuilder) { NotificationCompat.Action PlayPause, Prev, Next; Prev = new NotificationCompat.Action(android.R.drawable.ic_media_previous, "Previous", MediaButtonReceiver.buildMediaButtonPendingIntent(mService, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)); if (playbackState == PlaybackStateCompat.STATE_PLAYING) PlayPause = new NotificationCompat.Action(android.R.drawable.ic_media_pause, "Pause", MediaButtonReceiver.buildMediaButtonPendingIntent(mService, PlaybackStateCompat.ACTION_PLAY_PAUSE)); else PlayPause = new NotificationCompat.Action(android.R.drawable.ic_media_play, "Play", MediaButtonReceiver.buildMediaButtonPendingIntent(mService, PlaybackStateCompat.ACTION_PLAY_PAUSE)); Next = new NotificationCompat.Action(android.R.drawable.ic_media_next, "Next", MediaButtonReceiver.buildMediaButtonPendingIntent(mService, PlaybackStateCompat.ACTION_SKIP_TO_NEXT)); notificationBuilder.addAction(Prev); notificationBuilder.addAction(PlayPause); notificationBuilder.addAction(Next); } @RequiresApi(Build.VERSION_CODES.O) private void createNotificationChannel() { if (mNotificationManager.getNotificationChannel(CHANNEL_ID) == null) { NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "AUDIO_PLAYER_Channel_ID", NotificationManager.IMPORTANCE_LOW); notificationChannel.setDescription("Channel ID for Audio Player"); mNotificationManager.createNotificationChannel(notificationChannel); } } public void setmediaSessionHelper(MediaSessionHelper mMediaSessionHelper) { this.mMediaSession = mMediaSessionHelper; } }
W klasie z serwisem (w naszym przypadku to PlayerService) w metodzie onCreate() dodaj:
mNotification = new MediaNotificationHelper(this); mNotification.setmediaSessionHelper(mMediaSessionHelper);
W klasie MediaSessionHelper w poszczególnych metodach onPlay() / onStop() itp. dodaj wpis:
mNotification.updateNotification(statePlaying);
2. Wyjaśnienie powiadomień.
W metodzie updateNotification() wyświetlamy powiadomienia w zależności od stanu odtwarzania. Nas głównie interesuje metoda createNotification() w której wszystko się dzieje.
W androidzie Oreo wprowadzono kanały powiadomień. Wszystkie powiadomienia muszą być przypisane do kanału. Dla każdego kanału możesz ustawić wizualne i dźwiękowe zachowania powiadomień. Użytkownik może zmieniać te ustawienia i zdecydować, w jaki sposób powiadomienia mają się zachowywać w danym kanale. Po utworzeniu kanału powiadomień nie można zmienić zachowań. Jedynym sposobem, aby zmienić zachowania powiadomień to zmiana nazwy i opisu kanału. Jeśli utworzysz powiadomienie na Androidzie 8.0 bez określania kanału, powiadomienie nie pojawi się, a system zarejestruje błąd. W naszym przypadku aplikacja do odtwarzania muzyki nie potrzebuje specjalnych zachowań, dlatego wystarczy nazwa, opis i priorytet, który mówi, że powiadomienia ma się pojawić bez dźwięków i wibracji. Więcej o kanałach możesz przeczytać tutaj.
Następnie budujemy powiadomienie o następujących atrybutach. W metodzie addActions() dodajemy przyciski które chcemy aby pokazały się w powiadomieniach. U nas wystarczą tylko trzy. Klasa MediaStyle jest specjalnie stworzona dla powiadomień aplikacji multimedialnych, warto w tym przypadku skorzystać. Związku z tym w atrybucie setStyle mamy następujące opcje:
- setShowActionsInCompactView – która ikona ma pokazać się gdy jest kompaktowe (małe) powiadomienie. W naszym przypadku pokazuje play lub pauzę w zależności od stanu odtwarzania.
- setMediaSession – ustawiając token, informujesz systemowy interfejs użytkownika, że ma do czynienia z aktywną sesję multimedialną i może na przykład wyświetlić okładkę albumu na ekranie blokady.
- setShowCancelButton – dla systemu Android poniżej 5.0. Ustawiamy czy ma pokazać ikonę „X”, aby usunąć powiadomienie,
- setCancelButtonIntent – zachowanie po przyciśnięciu ikony „X”.
Kolejne atrybuty kreatora powiadomienia to:
- setShowWhen – czy ma pokazywać się czas utworzonego powiadomienia,
- setPriority – ustawienie priorytetu powiadomienia. W przykładzie – brak dźwięków i wibracji,
- setContentIntent – otwieramy aplikację po kliknięciu w powiadomienie,
- setDeleteIntent – co ma się stać po usunięciu powiadomienia,
- setColor – kolor tła dla Androida 6.0 i poniżej, a dla pozostałych kolor ikonek,
- setContentTitle – ustawienie tytułu powiadomienia – w naszym przypadku artysta,
- setContentText – ustawienie opisu powiadomienia – w naszym przypadku tytuł utworu,
- setLargeIcon – ustawienie dużej ikony powiadomienia,
- setSmallIcon – ustawienie małej ikony powiadomienia.
Oczywiście nie jest to lista zamknięta, możemy ustawić jeszcze własne atrybuty według potrzeb. Tutaj tylko pokazałem te, które są wymagane i warto dodać do naszej aplikacji. Poniżej przykład wyglądu powiadomień. Od lewej: Android 5, Android 7, Android 8.
3. Podsumowanie.
Wiesz już jak budować powiadomienia dla aplikacji multimedialnych. Gdybyś chciał więcej dowiedzieć się o powiadomieniach zobacz ten przewodnik.Teraz masz już pełnosprawną aplikację do odtwarzania muzyki. Mam nadzieje, że niedługo zobaczę Twoją aplikację multimedialną :).
Krótki wpis, ale dotarliśmy do końca i mam nadzieje, że Ci się pomógł.