Download File
Download Project
Settings
Line Wrap
Themes
default
ambiance
bespin
dracula
eclipse
material
mbo
mdn-like
neat
solarized dark
ttcn
zenburn
MediaNotificationManager.java
/* * Copyright 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.mediasession.service.notifications; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.RequiresApi; import android.support.v4.app.NotificationCompat; import android.support.v4.content.ContextCompat; import android.support.v4.media.MediaDescriptionCompat; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.app.NotificationCompat.MediaStyle; import android.support.v4.media.session.MediaButtonReceiver; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import android.support.v4.os.BuildCompat; import android.util.Log; import com.example.android.mediasession.R; import com.example.android.mediasession.service.MusicService; import com.example.android.mediasession.service.PlaybackInfoListener; import com.example.android.mediasession.service.contentcatalogs.MusicLibrary; import com.example.android.mediasession.ui.MainActivity; /** * Keeps track of a notification and updates it automatically for a given MediaSession. This is * required so that the music service don't get killed during playback. */ public class MediaNotificationManager { public static final int NOTIFICATION_ID = 412; private static final String TAG = MediaNotificationManager.class.getSimpleName(); private static final String CHANNEL_ID = "com.example.android.musicplayer.channel"; private static final int REQUEST_CODE = 501; private final MusicService mService; private final NotificationCompat.Action mPlayAction; private final NotificationCompat.Action mPauseAction; private final NotificationCompat.Action mNextAction; private final NotificationCompat.Action mPrevAction; private final NotificationManager mNotificationManager; public MediaNotificationManager(MusicService service) { mService = service; mNotificationManager = (NotificationManager) mService.getSystemService(Context.NOTIFICATION_SERVICE); mPlayAction = new NotificationCompat.Action( R.drawable.ic_play_arrow_white_24dp, mService.getString(R.string.label_play), MediaButtonReceiver.buildMediaButtonPendingIntent( mService, PlaybackStateCompat.ACTION_PLAY)); mPauseAction = new NotificationCompat.Action( R.drawable.ic_pause_white_24dp, mService.getString(R.string.label_pause), MediaButtonReceiver.buildMediaButtonPendingIntent( mService, PlaybackStateCompat.ACTION_PAUSE)); mNextAction = new NotificationCompat.Action( R.drawable.ic_skip_next_white_24dp, mService.getString(R.string.label_next), MediaButtonReceiver.buildMediaButtonPendingIntent( mService, PlaybackStateCompat.ACTION_SKIP_TO_NEXT)); mPrevAction = new NotificationCompat.Action( R.drawable.ic_skip_previous_white_24dp, mService.getString(R.string.label_previous), MediaButtonReceiver.buildMediaButtonPendingIntent( mService, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)); // Cancel all notifications to handle the case where the Service was killed and // restarted by the system. mNotificationManager.cancelAll(); } public void onDestroy() { Log.d(TAG, "onDestroy: "); } public NotificationManager getNotificationManager() { return mNotificationManager; } public Notification getNotification(MediaMetadataCompat metadata, @NonNull PlaybackStateCompat state, MediaSessionCompat.Token token) { boolean isPlaying = state.getState() == PlaybackStateCompat.STATE_PLAYING; MediaDescriptionCompat description = metadata.getDescription(); NotificationCompat.Builder builder = buildNotification(state, token, isPlaying, description); return builder.build(); } private NotificationCompat.Builder buildNotification(@NonNull PlaybackStateCompat state, MediaSessionCompat.Token token, boolean isPlaying, MediaDescriptionCompat description) { // Create the (mandatory) notification channel when running on Android Oreo. if (isAndroidOOrHigher()) { createChannel(); } NotificationCompat.Builder builder = new NotificationCompat.Builder(mService, CHANNEL_ID); builder.setStyle( new MediaStyle() .setMediaSession(token) .setShowActionsInCompactView(0, 1, 2) // For backwards compatibility with Android L and earlier. .setShowCancelButton(true) .setCancelButtonIntent( MediaButtonReceiver.buildMediaButtonPendingIntent( mService, PlaybackStateCompat.ACTION_STOP))) .setColor(ContextCompat.getColor(mService, R.color.notification_bg)) .setSmallIcon(R.drawable.ic_stat_image_audiotrack) // Pending intent that is fired when user clicks on notification. .setContentIntent(createContentIntent()) // Title - Usually Song name. .setContentTitle(description.getTitle()) // Subtitle - Usually Artist name. .setContentText(description.getSubtitle()) .setLargeIcon(MusicLibrary.getAlbumBitmap(mService, description.getMediaId())) // When notification is deleted (when playback is paused and notification can be // deleted) fire MediaButtonPendingIntent with ACTION_STOP. .setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent( mService, PlaybackStateCompat.ACTION_STOP)) // Show controls on lock screen even when user hides sensitive content. .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); // If skip to next action is enabled. if ((state.getActions() & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) { builder.addAction(mPrevAction); } builder.addAction(isPlaying ? mPauseAction : mPlayAction); // If skip to prev action is enabled. if ((state.getActions() & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) { builder.addAction(mNextAction); } return builder; } // Does nothing on versions of Android earlier than O. @RequiresApi(Build.VERSION_CODES.O) private void createChannel() { if (mNotificationManager.getNotificationChannel(CHANNEL_ID) == null) { // The user-visible name of the channel. CharSequence name = "MediaSession"; // The user-visible description of the channel. String description = "MediaSession and MediaPlayer"; int importance = NotificationManager.IMPORTANCE_LOW; NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance); // Configure the notification channel. mChannel.setDescription(description); mChannel.enableLights(true); // Sets the notification light color for notifications posted to this // channel, if the device supports this feature. mChannel.setLightColor(Color.RED); mChannel.enableVibration(true); mChannel.setVibrationPattern( new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); mNotificationManager.createNotificationChannel(mChannel); Log.d(TAG, "createChannel: New channel created"); } else { Log.d(TAG, "createChannel: Existing channel reused"); } } private boolean isAndroidOOrHigher() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; } private PendingIntent createContentIntent() { Intent openUI = new Intent(mService, MainActivity.class); openUI.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); return PendingIntent.getActivity( mService, REQUEST_CODE, openUI, PendingIntent.FLAG_CANCEL_CURRENT); } }