package com.kure.musicplayer;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import com.kure.musicplayer.activities.ActivityNowPlaying;
import com.kure.musicplayer.model.Song;
/**
* Specific way to stick an on-going message on the system
* with the current song I'm playing.
*
* This is a rather complicated set of functions because
* it interacts with a great deal of the Android API.
* Read with care.
*
* Thanks:
*
* - Gave me a complete example on how to add a custom
* action to a button click on the Notification:
* http://stackoverflow.com/a/21927248
*/
public class NotificationMusic extends NotificationSimple {
/**
* Reference to the context that notified.
*/
Context context = null;
/**
* Reference to the service we're attached to.
*/
Service service = null;
/**
* Used to create and update the same notification.
*/
Notification.Builder notificationBuilder = null;
/**
* Custom appearance of the notification, also updated.
*/
RemoteViews notificationView = null;
/**
* Used to actually broadcast the notification.
* Depends on the Activity that originally called
* the nofitication.
*/
NotificationManager notificationManager = null;
/**
* Sends a system notification with a song's information.
*
* If the user clicks the notification, will be redirected
* to the "Now Playing" Activity.
*
* If the user clicks on any of the buttons inside it,
* custom actions will be executed on the
* `NotificationButtonHandler` class.
*
* @param context Activity that calls this function.
* @param service Service that calls this function.
* Required so the Notification can
* run on the background.
* @param song Song which we'll display information.
*
* @note By calling this function multiple times, it'll
* update the old notification.
*/
public void notifySong(Context context, Service service, Song song) {
if (this.context == null)
this.context = context;
if (this.service == null)
this.service = service;
// Intent that launches the "Now Playing" Activity
Intent notifyIntent = new Intent(context, ActivityNowPlaying.class);
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Letting the Intent be executed later by other application.
PendingIntent pendingIntent = PendingIntent.getActivity
(context,
0,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// Setting our custom appearance for the notification
notificationView = new RemoteViews(kMP.packageName, R.layout.notification);
// Manually settings the buttons and text
// (ignoring the defaults on the XML)
notificationView.setImageViewResource(R.id.notification_button_play, R.drawable.pause);
notificationView.setImageViewResource(R.id.notification_button_skip, R.drawable.skip);
notificationView.setTextViewText(R.id.notification_text_title, song.getTitle());
notificationView.setTextViewText(R.id.notification_text_artist, song.getArtist());
// On the notification we have two buttons - Play and Skip
// Here we make sure the class `NotificationButtonHandler`
// gets called when user selects one of those.
//
// First, building the play button and attaching it.
Intent buttonPlayIntent = new Intent(context, NotificationPlayButtonHandler.class);
buttonPlayIntent.putExtra("action", "togglePause");
PendingIntent buttonPlayPendingIntent = PendingIntent.getBroadcast(context, 0, buttonPlayIntent, 0);
notificationView.setOnClickPendingIntent(R.id.notification_button_play, buttonPlayPendingIntent);
// And now, building and attaching the Skip button.
Intent buttonSkipIntent = new Intent(context, NotificationSkipButtonHandler.class);
buttonSkipIntent.putExtra("action", "skip");
PendingIntent buttonSkipPendingIntent = PendingIntent.getBroadcast(context, 0, buttonSkipIntent, 0);
notificationView.setOnClickPendingIntent(R.id.notification_button_skip, buttonSkipPendingIntent);
// Finally... Actually creating the Notification
notificationBuilder = new Notification.Builder(context);
notificationBuilder.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_launcher_white)
.setTicker("kMP: Playing '" + song.getTitle() + "' from '" + song.getArtist() + "'")
.setOngoing(true)
.setContentTitle(song.getTitle())
.setContentText(song.getArtist())
.setContent(notificationView);
Notification notification = notificationBuilder.build();
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
// notificationManager.notify(NOTIFICATION_ID, notification);
// Sets the notification to run on the foreground.
// (why not the former commented line?)
service.startForeground(NOTIFICATION_ID, notification);
}
/**
* Called when user clicks the "play/pause" button on the on-going system Notification.
*/
public static class NotificationPlayButtonHandler extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
kMP.musicService.togglePlayback();
}
}
/**
* Called when user clicks the "skip" button on the on-going system Notification.
*/
public static class NotificationSkipButtonHandler extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
kMP.musicService.next(true);
kMP.musicService.playSong();
}
}
/**
* Updates the Notification icon if the music is paused.
*/
public void notifyPaused(boolean isPaused) {
if ((notificationView == null) || (notificationBuilder == null))
return;
int iconID = ((isPaused)?
R.drawable.play :
R.drawable.pause);
notificationView.setImageViewResource(R.id.notification_button_play, iconID);
notificationBuilder.setContent(notificationView);
// notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
// Sets the notification to run on the foreground.
// (why not the former commented line?)
service.startForeground(NOTIFICATION_ID, notificationBuilder.build());
}
/**
* Cancels this notification.
*/
public void cancel() {
service.stopForeground(true);
notificationManager.cancel(NOTIFICATION_ID);
}
/**
* Cancels all sent notifications.
*/
public static void cancelAll(Context c) {
NotificationManager manager = (NotificationManager)c.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancelAll();
}
}