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ł.
