X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff..269195b3729c1bdc22e9053ee4ebca667ea8549d:/Android/app/src/main/java/com/moiseum/wolnelektury/view/player/service/MediaNotificationManager.java diff --git a/Android/app/src/main/java/com/moiseum/wolnelektury/view/player/service/MediaNotificationManager.java b/Android/app/src/main/java/com/moiseum/wolnelektury/view/player/service/MediaNotificationManager.java new file mode 100755 index 0000000..b11607b --- /dev/null +++ b/Android/app/src/main/java/com/moiseum/wolnelektury/view/player/service/MediaNotificationManager.java @@ -0,0 +1,213 @@ +/* + * 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.moiseum.wolnelektury.view.player.service; + +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.util.Log; + +import com.bumptech.glide.Glide; +import com.moiseum.wolnelektury.R; +import com.moiseum.wolnelektury.view.main.MainActivity; + +import java.util.concurrent.ExecutionException; + + +/** + * 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.moiseum.wolnelektury.audiobookplayer.channel"; + private static final int REQUEST_CODE = 501; + + private final AudiobookService 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(AudiobookService 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.colorAccent)) + .setSmallIcon(R.drawable.ic_notification_player) + // 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(AudiobookLibrary.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); + } + +} \ No newline at end of file