Docs: Sync browseable samples for lmp-docs
Synced to developers/samples/android commit bc036ecdf44cd03163c206096172299f3940b057. Change-Id: Ib68230d79ca300e7db906aff2ebfc2cb6c6968f7
@@ -4,8 +4,14 @@ sample.group=Media
|
||||
|
||||
<p>
|
||||
|
||||
This sample shows how to implement an audio media app that provides
|
||||
media library metadata and playback controls through a standard
|
||||
service.
|
||||
|
||||
</p>
|
||||
This sample shows how to implement an audio media app that provides
|
||||
media library metadata and playback controls through a standard
|
||||
service. It exposes a simple music library through the new
|
||||
MediaBrowserService and provides MediaSession callbacks. This allows
|
||||
it to be used in Android Auto, for example.
|
||||
When not connected to a car, the app has a very simple UI that browses
|
||||
the media library and provides simple playback controls. When
|
||||
connected to Android Auto, the same service provides data and callback
|
||||
to the Android Auto UI in the same manner as it provides them to the
|
||||
local UI.
|
||||
</p>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
@@ -37,7 +37,6 @@ 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.mediabrowserservice.utils.BitmapHelper;
|
||||
import com.example.android.mediabrowserservice.utils.LogHelper;
|
||||
@@ -65,7 +64,6 @@ public class MediaNotification extends BroadcastReceiver {
|
||||
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;
|
||||
@@ -75,6 +73,8 @@ public class MediaNotification extends BroadcastReceiver {
|
||||
private NotificationManager mNotificationManager;
|
||||
private Notification.Action mPlayPauseAction;
|
||||
|
||||
private PendingIntent mPauseIntent, mPlayIntent, mPreviousIntent, mNextIntent;
|
||||
|
||||
private String mCurrentAlbumArt;
|
||||
private int mNotificationColor;
|
||||
|
||||
@@ -99,14 +99,14 @@ public class MediaNotification extends BroadcastReceiver {
|
||||
.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));
|
||||
mPauseIntent = PendingIntent.getBroadcast(mService, 100,
|
||||
new Intent(ACTION_PAUSE).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
mPlayIntent = PendingIntent.getBroadcast(mService, 100,
|
||||
new Intent(ACTION_PLAY).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
mPreviousIntent = PendingIntent.getBroadcast(mService, 100,
|
||||
new Intent(ACTION_PREV).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
mNextIntent = PendingIntent.getBroadcast(mService, 100,
|
||||
new Intent(ACTION_NEXT).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
}
|
||||
|
||||
protected int getNotificationColor() {
|
||||
@@ -241,8 +241,7 @@ public class MediaNotification extends BroadcastReceiver {
|
||||
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));
|
||||
mService.getString(R.string.label_previous), mPreviousIntent);
|
||||
playPauseActionIndex = 1;
|
||||
}
|
||||
|
||||
@@ -251,8 +250,7 @@ public class MediaNotification extends BroadcastReceiver {
|
||||
// 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));
|
||||
mService.getString(R.string.label_next), mNextIntent);
|
||||
}
|
||||
|
||||
MediaDescription description = mMetadata.getDescription();
|
||||
@@ -294,22 +292,24 @@ public class MediaNotification extends BroadcastReceiver {
|
||||
|
||||
private void updatePlayPauseAction() {
|
||||
LogHelper.d(TAG, "updatePlayPauseAction");
|
||||
String playPauseLabel = "";
|
||||
int playPauseIcon;
|
||||
String label;
|
||||
int icon;
|
||||
PendingIntent intent;
|
||||
if (mPlaybackState.getState() == PlaybackState.STATE_PLAYING) {
|
||||
playPauseLabel = mService.getString(R.string.label_pause);
|
||||
playPauseIcon = R.drawable.ic_pause_white_24dp;
|
||||
label = mService.getString(R.string.label_pause);
|
||||
icon = R.drawable.ic_pause_white_24dp;
|
||||
intent = mPauseIntent;
|
||||
} else {
|
||||
playPauseLabel = mService.getString(R.string.label_play);
|
||||
playPauseIcon = R.drawable.ic_play_arrow_white_24dp;
|
||||
label = mService.getString(R.string.label_play);
|
||||
icon = R.drawable.ic_play_arrow_white_24dp;
|
||||
intent = mPlayIntent;
|
||||
}
|
||||
if (mPlayPauseAction == null) {
|
||||
mPlayPauseAction = new Notification.Action(playPauseIcon, playPauseLabel,
|
||||
mIntents.get(playPauseIcon));
|
||||
mPlayPauseAction = new Notification.Action(icon, label, intent);
|
||||
} else {
|
||||
mPlayPauseAction.icon = playPauseIcon;
|
||||
mPlayPauseAction.title = playPauseLabel;
|
||||
mPlayPauseAction.actionIntent = mIntents.get(playPauseIcon);
|
||||
mPlayPauseAction.icon = icon;
|
||||
mPlayPauseAction.title = label;
|
||||
mPlayPauseAction.actionIntent = intent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,14 @@ public class PackageValidator {
|
||||
*/
|
||||
public static boolean isCallerAllowed(Context context, String callingPackage, int callingUid) {
|
||||
// Always allow calls from the framework or development environment.
|
||||
if (Process.SYSTEM_UID == callingUid || !"user".equals(Build.TYPE)) {
|
||||
if (Process.SYSTEM_UID == callingUid || Process.myUid() == callingUid) {
|
||||
return true;
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
// When your app is built in debug mode, any app is allowed to connect to it and browse
|
||||
// its media library. If you want to test the behavior of your app when it gets
|
||||
// released, either build a release version or remove this clause.
|
||||
Log.i(TAG, "Allowing caller '"+callingPackage+" because app was built in debug mode.");
|
||||
return true;
|
||||
}
|
||||
PackageInfo packageInfo;
|
||||
|
||||