package danielr2001.audioplayer.notifications; import danielr2001.audioplayer.audioplayers.ForegroundAudioPlayer; import danielr2001.audioplayer.enums.NotificationDefaultActions; import danielr2001.audioplayer.enums.NotificationCustomActions; import danielr2001.audioplayer.interfaces.AsyncResponse; import danielr2001.audioplayer.R; import danielr2001.audioplayer.models.AudioObject; import android.app.Activity; 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.content.res.Resources; import android.graphics.Bitmap; import android.os.Build; import android.support.v4.media.session.MediaSessionCompat; import android.util.Log; import androidx.core.app.NotificationCompat; import java.util.Map; public class MediaNotificationManager { public static final String PLAY_ACTION = "com.daniel.exoPlayer.action.play"; public static final String PAUSE_ACTION = "com.daniel.exoPlayer.action.pause"; public static final String PREVIOUS_ACTION = "com.daniel.exoPlayer.action.previous"; public static final String NEXT_ACTION = "com.daniel.exoPlayer.action.next"; public static final String CUSTOM1_ACTION = "com.daniel.exoPlayer.action.custom1"; public static final String CUSTOM2_ACTION = "com.daniel.exoPlayer.action.custom2"; private static final int NOTIFICATION_ID = 1; private static final String CHANNEL_ID = "Playback"; private ForegroundAudioPlayer foregroundExoPlayer; private Context context; private Activity activity; private NotificationManager notificationManager; private MediaSessionCompat mediaSession; private Intent playIntent; private Intent pauseIntent; private Intent prevIntent; private Intent nextIntent; private Intent notificationIntent; private Intent customIntent1; private Intent customIntent2; private PendingIntent ppPlayIntent; private PendingIntent pPauseIntent; private PendingIntent pPrevIntent; private PendingIntent pNextIntent; private PendingIntent pNotificatioIntent; private PendingIntent pCustomIntent1; private PendingIntent pCustomIntent2; private AudioObject audioObject; private boolean isPlaying; private boolean isShowing; private boolean isInitialized; public void setIsShowing(boolean isShowing) { this.isShowing = isShowing; } public boolean isShowing() { return isShowing; } public void setIsInitialized(boolean isInitialized) { this.isInitialized = isInitialized; } public boolean isInitialized() { return isInitialized; } public MediaNotificationManager(ForegroundAudioPlayer foregroundExoPlayer, Context context, MediaSessionCompat mediaSession, Activity activity) { this.context = context; this.foregroundExoPlayer = foregroundExoPlayer; this.mediaSession = mediaSession; this.activity = activity; isInitialized = false; initIntents(); } private void initIntents() { notificationIntent = new Intent(this.context, activity.getClass()); pNotificatioIntent = PendingIntent.getActivity(this.context, 0, notificationIntent, 0); playIntent = new Intent(this.context, ForegroundAudioPlayer.class); playIntent.setAction(PLAY_ACTION); ppPlayIntent = PendingIntent.getService(this.context, 1, playIntent, 0); pauseIntent = new Intent(this.context, ForegroundAudioPlayer.class); pauseIntent.setAction(PAUSE_ACTION); pPauseIntent = PendingIntent.getService(this.context, 1, pauseIntent, 0); prevIntent = new Intent(this.context, ForegroundAudioPlayer.class); prevIntent.setAction(PREVIOUS_ACTION); pPrevIntent = PendingIntent.getService(this.context, 1, prevIntent, 0); nextIntent = new Intent(this.context, ForegroundAudioPlayer.class); nextIntent.setAction(NEXT_ACTION); pNextIntent = PendingIntent.getService(this.context, 1, nextIntent, 0); customIntent1 = new Intent(this.context, ForegroundAudioPlayer.class); customIntent1.setAction(CUSTOM1_ACTION); pCustomIntent1 = PendingIntent.getService(this.context, 1, customIntent1, 0); customIntent2 = new Intent(this.context, ForegroundAudioPlayer.class); customIntent2.setAction(CUSTOM2_ACTION); pCustomIntent2 = PendingIntent.getService(this.context, 1, customIntent2, 0); } // make new notification public void makeNotification(AudioObject audioObject, boolean isPlaying) { isInitialized = true; isShowing = true; this.audioObject = audioObject; this.isPlaying = isPlaying; if (audioObject.getLargeIconUrl() != null) { loadImageFromUrl(audioObject.getLargeIconUrl(), audioObject.getIsLocal()); } else { showNotification(); } } // update current notification public void makeNotification(boolean isPlaying) { this.isPlaying = isPlaying; showNotification(); } private void showNotification() { Notification notification; int icon = this.context.getResources().getIdentifier(audioObject.getSmallIconFileName(), "drawable", this.context.getPackageName()); notificationManager = initNotificationManager(); NotificationCompat.Builder builder = new NotificationCompat.Builder(this.context, CHANNEL_ID) .setSmallIcon(icon) .setWhen(System.currentTimeMillis()) .setShowWhen(false) .setColorized(true) .setSound(null) .setContentIntent(pNotificatioIntent); if (audioObject.getTitle() != null) { builder.setContentTitle(audioObject.getTitle()); } if (audioObject.getSubTitle() != null) { builder.setContentText(audioObject.getSubTitle()); } if (audioObject.getLargeIcon() != null) { builder.setLargeIcon(audioObject.getLargeIcon()); } if (!this.isPlaying) { builder.setTimeoutAfter(900000); } builder = initNotificationActions(builder); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder = initNotificationStyle(builder); } notification = builder.build(); notificationManager.notify(NOTIFICATION_ID, notification); if (this.isPlaying) { foregroundExoPlayer.startForeground(NOTIFICATION_ID, notification); } else { foregroundExoPlayer.stopForeground(false); } } private NotificationManager initNotificationManager() { NotificationManager notificationManager; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "Playback", android.app.NotificationManager.IMPORTANCE_DEFAULT); notificationChannel.setSound(null, null); notificationChannel.setShowBadge(false); notificationManager = (android.app.NotificationManager) this.context .getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(notificationChannel); } else { notificationManager = (android.app.NotificationManager) this.context .getSystemService(Context.NOTIFICATION_SERVICE); } return notificationManager; } private NotificationCompat.Builder initNotificationActions(NotificationCompat.Builder builder) { int customIcon1 = this.context.getResources().getIdentifier("ic_custom1", "drawable", // ! TODO maybe change to custom file name this.context.getPackageName()); int customIcon2 = this.context.getResources().getIdentifier("ic_custom2", "drawable", this.context.getPackageName()); if (audioObject.getNotificationCustomActions() == NotificationCustomActions.ONE || audioObject.getNotificationCustomActions() == NotificationCustomActions.TWO) { builder.addAction(customIcon1, "Custom1", pCustomIntent1); } if (audioObject.getNotificationActionMode() == NotificationDefaultActions.PREVIOUS || audioObject.getNotificationActionMode() == NotificationDefaultActions.ALL) { builder.addAction(R.drawable.ic_previous, "Previous", pPrevIntent); } if (this.isPlaying) { builder.addAction(R.drawable.ic_pause, "Pause", pPauseIntent); } else { builder.addAction(R.drawable.ic_play, "Play", ppPlayIntent); } if (audioObject.getNotificationActionMode() == NotificationDefaultActions.NEXT || audioObject.getNotificationActionMode() == NotificationDefaultActions.ALL) { builder.addAction(R.drawable.ic_next, "Next", pNextIntent); } if (audioObject.getNotificationCustomActions() == NotificationCustomActions.TWO) { builder.addAction(customIcon2, "Custom2", pCustomIntent2); } return builder; } private NotificationCompat.Builder initNotificationStyle(NotificationCompat.Builder builder) { if (audioObject.getNotificationActionMode() == NotificationDefaultActions.NEXT || audioObject.getNotificationActionMode() == NotificationDefaultActions.PREVIOUS) { builder.setStyle(new androidx.media.app.NotificationCompat.DecoratedMediaCustomViewStyle() .setShowActionsInCompactView(0, 1).setMediaSession(mediaSession.getSessionToken())); } else if (audioObject.getNotificationActionMode() == NotificationDefaultActions.ALL) { builder.setStyle(new androidx.media.app.NotificationCompat.DecoratedMediaCustomViewStyle() .setShowActionsInCompactView(0, 1, 2).setMediaSession(mediaSession.getSessionToken())); } else { builder.setStyle(new androidx.media.app.NotificationCompat.DecoratedMediaCustomViewStyle() .setShowActionsInCompactView(0).setMediaSession(mediaSession.getSessionToken())); } return builder; } private void loadImageFromUrl(String imageUrl, boolean isLocal) { try { new LoadImageFromUrl(imageUrl, isLocal, new AsyncResponse() { @Override public void processFinish(Map<String, Bitmap> bitmapMap) { if (bitmapMap != null) { if (bitmapMap.get(audioObject.getLargeIconUrl()) != null) { audioObject.setLargeIcon(bitmapMap.get(audioObject.getLargeIconUrl())); showNotification(); } else { Log.e("ExoPlayerPlugin", "canceled showing notification!"); } } else { showNotification(); Log.e("ExoPlayerPlugin", "Failed loading image!"); } } }).execute(); } catch (Exception e) { Log.e("ExoPlayerPlugin", "Failed loading image!"); } } }