summaryrefslogtreecommitdiff
path: root/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java
diff options
context:
space:
mode:
Diffstat (limited to 'MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java')
-rw-r--r--MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java381
1 files changed, 0 insertions, 381 deletions
diff --git a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java b/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java
deleted file mode 100644
index 94ac023..0000000
--- a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright (C) 2014 Google Inc. All Rights Reserved.
- *
- * 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.musicservicedemo;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
-import android.os.AsyncTask;
-import android.util.LruCache;
-import android.util.SparseArray;
-
-import com.example.android.musicservicedemo.utils.BitmapHelper;
-import com.example.android.musicservicedemo.utils.LogHelper;
-
-import java.io.IOException;
-
-/**
- * Keeps track of a notification and updates it automatically for a given
- * MediaSession. Maintaining a visible notification (usually) guarantees that the music service
- * won't be killed during playback.
- */
-public class MediaNotification extends BroadcastReceiver {
- private static final String TAG = "MediaNotification";
-
- private static final int NOTIFICATION_ID = 412;
-
- public static final String ACTION_PAUSE = "com.example.android.musicservicedemo.pause";
- public static final String ACTION_PLAY = "com.example.android.musicservicedemo.play";
- public static final String ACTION_PREV = "com.example.android.musicservicedemo.prev";
- public static final String ACTION_NEXT = "com.example.android.musicservicedemo.next";
-
- private static final int MAX_ALBUM_ART_CACHE_SIZE = 1024*1024;
-
- private final MusicService mService;
- private MediaSession.Token mSessionToken;
- private MediaController mController;
- private MediaController.TransportControls mTransportControls;
- private final SparseArray<PendingIntent> mIntents = new SparseArray<PendingIntent>();
- private final LruCache<String, Bitmap> mAlbumArtCache;
-
- private PlaybackState mPlaybackState;
- private MediaMetadata mMetadata;
-
- private Notification.Builder mNotificationBuilder;
- private NotificationManager mNotificationManager;
- private Notification.Action mPlayPauseAction;
-
- private String mCurrentAlbumArt;
- private int mNotificationColor;
-
- private boolean mStarted = false;
-
- public MediaNotification(MusicService service) {
- mService = service;
- updateSessionToken();
-
- // simple album art cache that holds no more than
- // MAX_ALBUM_ART_CACHE_SIZE bytes:
- mAlbumArtCache = new LruCache<String, Bitmap>(MAX_ALBUM_ART_CACHE_SIZE) {
- @Override
- protected int sizeOf(String key, Bitmap value) {
- return value.getByteCount();
- }
- };
-
- mNotificationColor = getNotificationColor();
-
- mNotificationManager = (NotificationManager) mService
- .getSystemService(Context.NOTIFICATION_SERVICE);
-
- String pkg = mService.getPackageName();
- mIntents.put(R.drawable.ic_pause_white_24dp, PendingIntent.getBroadcast(mService, 100,
- new Intent(ACTION_PAUSE).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT));
- mIntents.put(R.drawable.ic_play_arrow_white_24dp, PendingIntent.getBroadcast(mService, 100,
- new Intent(ACTION_PLAY).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT));
- mIntents.put(R.drawable.ic_skip_previous_white_24dp, PendingIntent.getBroadcast(mService, 100,
- new Intent(ACTION_PREV).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT));
- mIntents.put(R.drawable.ic_skip_next_white_24dp, PendingIntent.getBroadcast(mService, 100,
- new Intent(ACTION_NEXT).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT));
- }
-
- protected int getNotificationColor() {
- int notificationColor = 0;
- String packageName = mService.getPackageName();
- try {
- Context packageContext = mService.createPackageContext(packageName, 0);
- ApplicationInfo applicationInfo =
- mService.getPackageManager().getApplicationInfo(packageName, 0);
- packageContext.setTheme(applicationInfo.theme);
- Resources.Theme theme = packageContext.getTheme();
- TypedArray ta = theme.obtainStyledAttributes(
- new int[] {android.R.attr.colorPrimary});
- notificationColor = ta.getColor(0, Color.DKGRAY);
- ta.recycle();
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
- return notificationColor;
- }
-
- /**
- * Posts the notification and starts tracking the session to keep it
- * updated. The notification will automatically be removed if the session is
- * destroyed before {@link #stopNotification} is called.
- */
- public void startNotification() {
- if (!mStarted) {
- mController.registerCallback(mCb);
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_NEXT);
- filter.addAction(ACTION_PAUSE);
- filter.addAction(ACTION_PLAY);
- filter.addAction(ACTION_PREV);
- mService.registerReceiver(this, filter);
-
- mMetadata = mController.getMetadata();
- mPlaybackState = mController.getPlaybackState();
-
- mStarted = true;
- // The notification must be updated after setting started to true
- updateNotificationMetadata();
- }
- }
-
- /**
- * Removes the notification and stops tracking the session. If the session
- * was destroyed this has no effect.
- */
- public void stopNotification() {
- mStarted = false;
- mController.unregisterCallback(mCb);
- try {
- mNotificationManager.cancel(NOTIFICATION_ID);
- mService.unregisterReceiver(this);
- } catch (IllegalArgumentException ex) {
- // ignore if the receiver is not registered.
- }
- mService.stopForeground(true);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- LogHelper.d(TAG, "Received intent with action " + action);
- if (ACTION_PAUSE.equals(action)) {
- mTransportControls.pause();
- } else if (ACTION_PLAY.equals(action)) {
- mTransportControls.play();
- } else if (ACTION_NEXT.equals(action)) {
- mTransportControls.skipToNext();
- } else if (ACTION_PREV.equals(action)) {
- mTransportControls.skipToPrevious();
- }
- }
-
- /**
- * Update the state based on a change on the session token. Called either when
- * we are running for the first time or when the media session owner has destroyed the session
- * (see {@link android.media.session.MediaController.Callback#onSessionDestroyed()})
- */
- private void updateSessionToken() {
- MediaSession.Token freshToken = mService.getSessionToken();
- if (mSessionToken == null || !mSessionToken.equals(freshToken)) {
- if (mController != null) {
- mController.unregisterCallback(mCb);
- }
- mSessionToken = freshToken;
- mController = new MediaController(mService, mSessionToken);
- mTransportControls = mController.getTransportControls();
- if (mStarted) {
- mController.registerCallback(mCb);
- }
- }
- }
-
- private final MediaController.Callback mCb = new MediaController.Callback() {
- @Override
- public void onPlaybackStateChanged(PlaybackState state) {
- mPlaybackState = state;
- LogHelper.d(TAG, "Received new playback state", state);
- updateNotificationPlaybackState();
- }
-
- @Override
- public void onMetadataChanged(MediaMetadata metadata) {
- mMetadata = metadata;
- LogHelper.d(TAG, "Received new metadata ", metadata);
- updateNotificationMetadata();
- }
-
- @Override
- public void onSessionDestroyed() {
- super.onSessionDestroyed();
- LogHelper.d(TAG, "Session was destroyed, resetting to the new session token");
- updateSessionToken();
- }
- };
-
- private void updateNotificationMetadata() {
- LogHelper.d(TAG, "updateNotificationMetadata. mMetadata=" + mMetadata);
- if (mMetadata == null || mPlaybackState == null) {
- return;
- }
-
- updatePlayPauseAction();
-
- mNotificationBuilder = new Notification.Builder(mService);
- int playPauseActionIndex = 0;
-
- // If skip to previous action is enabled
- if ((mPlaybackState.getActions() & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0) {
- mNotificationBuilder
- .addAction(R.drawable.ic_skip_previous_white_24dp,
- mService.getString(R.string.label_previous),
- mIntents.get(R.drawable.ic_skip_previous_white_24dp));
- playPauseActionIndex = 1;
- }
-
- mNotificationBuilder.addAction(mPlayPauseAction);
-
- // If skip to next action is enabled
- if ((mPlaybackState.getActions() & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) {
- mNotificationBuilder.addAction(R.drawable.ic_skip_next_white_24dp,
- mService.getString(R.string.label_next),
- mIntents.get(R.drawable.ic_skip_next_white_24dp));
- }
-
- MediaDescription description = mMetadata.getDescription();
-
- String fetchArtUrl = null;
- Bitmap art = description.getIconBitmap();
- if (art == null && description.getIconUri() != null) {
- // This sample assumes the iconUri will be a valid URL formatted String, but
- // it can actually be any valid Android Uri formatted String.
- // async fetch the album art icon
- String artUrl = description.getIconUri().toString();
- art = mAlbumArtCache.get(artUrl);
- if (art == null) {
- fetchArtUrl = artUrl;
- // use a placeholder art while the remote art is being downloaded
- art = BitmapFactory.decodeResource(mService.getResources(), R.drawable.ic_default_art);
- }
- }
-
- mNotificationBuilder
- .setStyle(new Notification.MediaStyle()
- .setShowActionsInCompactView(playPauseActionIndex) // only show play/pause in compact view
- .setMediaSession(mSessionToken))
- .setColor(mNotificationColor)
- .setSmallIcon(R.drawable.ic_notification)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setUsesChronometer(true)
- .setContentTitle(description.getTitle())
- .setContentText(description.getSubtitle())
- .setLargeIcon(art);
-
- updateNotificationPlaybackState();
-
- mService.startForeground(NOTIFICATION_ID, mNotificationBuilder.build());
- if (fetchArtUrl != null) {
- fetchBitmapFromURLAsync(fetchArtUrl);
- }
- }
-
- private void updatePlayPauseAction() {
- LogHelper.d(TAG, "updatePlayPauseAction");
- String playPauseLabel = "";
- int playPauseIcon;
- if (mPlaybackState.getState() == PlaybackState.STATE_PLAYING) {
- playPauseLabel = mService.getString(R.string.label_pause);
- playPauseIcon = R.drawable.ic_pause_white_24dp;
- } else {
- playPauseLabel = mService.getString(R.string.label_play);
- playPauseIcon = R.drawable.ic_play_arrow_white_24dp;
- }
- if (mPlayPauseAction == null) {
- mPlayPauseAction = new Notification.Action(playPauseIcon, playPauseLabel,
- mIntents.get(playPauseIcon));
- } else {
- mPlayPauseAction.icon = playPauseIcon;
- mPlayPauseAction.title = playPauseLabel;
- mPlayPauseAction.actionIntent = mIntents.get(playPauseIcon);
- }
- }
-
- private void updateNotificationPlaybackState() {
- LogHelper.d(TAG, "updateNotificationPlaybackState. mPlaybackState=" + mPlaybackState);
- if (mPlaybackState == null || !mStarted) {
- LogHelper.d(TAG, "updateNotificationPlaybackState. cancelling notification!");
- mService.stopForeground(true);
- return;
- }
- if (mNotificationBuilder == null) {
- LogHelper.d(TAG, "updateNotificationPlaybackState. there is no notificationBuilder. Ignoring request to update state!");
- return;
- }
- if (mPlaybackState.getPosition() >= 0) {
- LogHelper.d(TAG, "updateNotificationPlaybackState. updating playback position to ",
- (System.currentTimeMillis() - mPlaybackState.getPosition()) / 1000, " seconds");
- mNotificationBuilder
- .setWhen(System.currentTimeMillis() - mPlaybackState.getPosition())
- .setShowWhen(true)
- .setUsesChronometer(true);
- mNotificationBuilder.setShowWhen(true);
- } else {
- LogHelper.d(TAG, "updateNotificationPlaybackState. hiding playback position");
- mNotificationBuilder
- .setWhen(0)
- .setShowWhen(false)
- .setUsesChronometer(false);
- }
-
- updatePlayPauseAction();
-
- // Make sure that the notification can be dismissed by the user when we are not playing:
- mNotificationBuilder.setOngoing(mPlaybackState.getState() == PlaybackState.STATE_PLAYING);
-
- mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
- }
-
- public void fetchBitmapFromURLAsync(final String source) {
- LogHelper.d(TAG, "getBitmapFromURLAsync: starting asynctask to fetch ", source);
- new AsyncTask<Void, Void, Bitmap>() {
- @Override
- protected Bitmap doInBackground(Void[] objects) {
- Bitmap bitmap = null;
- try {
- bitmap = BitmapHelper.fetchAndRescaleBitmap(source,
- BitmapHelper.MEDIA_ART_BIG_WIDTH, BitmapHelper.MEDIA_ART_BIG_HEIGHT);
- mAlbumArtCache.put(source, bitmap);
- } catch (IOException e) {
- LogHelper.e(TAG, e, "getBitmapFromURLAsync: " + source);
- }
- return bitmap;
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- if (bitmap != null && mMetadata != null &&
- mNotificationBuilder != null && mMetadata.getDescription() != null &&
- !source.equals(mMetadata.getDescription().getIconUri())) {
- // If the media is still the same, update the notification:
- LogHelper.d(TAG, "getBitmapFromURLAsync: set bitmap to ", source);
- mNotificationBuilder.setLargeIcon(bitmap);
- mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
- }
- }
- }.execute();
- }
-
-}