am 620b29a5: media router sample: handle remote volume change
* commit '620b29a566e87ce7bb21223150ff97f919fee836': media router sample: handle remote volume change
This commit is contained in:
@@ -48,7 +48,11 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<receiver android:name="com.example.android.supportv7.media.SampleMediaButtonReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
<!-- MediaRouter Support Samples -->
|
<!-- MediaRouter Support Samples -->
|
||||||
|
|
||||||
<activity android:name=".media.SampleMediaRouterActivity"
|
<activity android:name=".media.SampleMediaRouterActivity"
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 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.example.android.supportv7.media;
|
||||||
|
|
||||||
|
import com.example.android.supportv7.R;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcast receiver for handling ACTION_MEDIA_BUTTON.
|
||||||
|
*
|
||||||
|
* This is needed to create the RemoteControlClient for controlling
|
||||||
|
* remote route volume in lock screen. It routes media key events back
|
||||||
|
* to main app activity SampleMediaRouterActivity.
|
||||||
|
*/
|
||||||
|
public class SampleMediaButtonReceiver extends BroadcastReceiver {
|
||||||
|
private static final String TAG = "SampleMediaButtonReceiver";
|
||||||
|
private static SampleMediaRouterActivity mActivity;
|
||||||
|
|
||||||
|
public static void setActivity(SampleMediaRouterActivity activity) {
|
||||||
|
mActivity = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (mActivity != null && Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
|
||||||
|
mActivity.handleMediaKey(
|
||||||
|
(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.IntentFilter.MalformedMimeTypeException;
|
import android.content.IntentFilter.MalformedMimeTypeException;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.media.AudioManager;
|
||||||
import android.media.MediaRouter;
|
import android.media.MediaRouter;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -161,6 +162,7 @@ final class SampleMediaRouteProvider extends MediaRouteProvider {
|
|||||||
r.getString(R.string.fixed_volume_route_name))
|
r.getString(R.string.fixed_volume_route_name))
|
||||||
.setDescription(r.getString(R.string.sample_route_description))
|
.setDescription(r.getString(R.string.sample_route_description))
|
||||||
.addControlFilters(CONTROL_FILTERS)
|
.addControlFilters(CONTROL_FILTERS)
|
||||||
|
.setPlaybackStream(AudioManager.STREAM_MUSIC)
|
||||||
.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
|
.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
|
||||||
.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED)
|
.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED)
|
||||||
.setVolume(VOLUME_MAX)
|
.setVolume(VOLUME_MAX)
|
||||||
@@ -171,6 +173,7 @@ final class SampleMediaRouteProvider extends MediaRouteProvider {
|
|||||||
r.getString(R.string.variable_volume_route_name))
|
r.getString(R.string.variable_volume_route_name))
|
||||||
.setDescription(r.getString(R.string.sample_route_description))
|
.setDescription(r.getString(R.string.sample_route_description))
|
||||||
.addControlFilters(CONTROL_FILTERS)
|
.addControlFilters(CONTROL_FILTERS)
|
||||||
|
.setPlaybackStream(AudioManager.STREAM_MUSIC)
|
||||||
.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
|
.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
|
||||||
.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
|
.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
|
||||||
.setVolumeMax(VOLUME_MAX)
|
.setVolumeMax(VOLUME_MAX)
|
||||||
@@ -287,6 +290,9 @@ final class SampleMediaRouteProvider extends MediaRouteProvider {
|
|||||||
if (volume >= 0 && volume <= VOLUME_MAX) {
|
if (volume >= 0 && volume <= VOLUME_MAX) {
|
||||||
mVolume = volume;
|
mVolume = volume;
|
||||||
Log.d(TAG, mRouteId + ": New volume is " + mVolume);
|
Log.d(TAG, mRouteId + ": New volume is " + mVolume);
|
||||||
|
AudioManager audioManager =
|
||||||
|
(AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
|
||||||
publishRoutes();
|
publishRoutes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.example.android.supportv7.media;
|
|||||||
|
|
||||||
import com.example.android.supportv7.R;
|
import com.example.android.supportv7.R;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
@@ -26,7 +27,13 @@ import android.content.res.Resources;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Presentation;
|
import android.app.Presentation;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.AudioManager.OnAudioFocusChangeListener;
|
||||||
|
import android.media.MediaMetadataRetriever;
|
||||||
|
import android.media.RemoteControlClient;
|
||||||
|
import android.media.RemoteControlClient.MetadataEditor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
@@ -44,6 +51,7 @@ import android.support.v7.media.MediaRouteSelector;
|
|||||||
import android.support.v7.media.MediaItemStatus;
|
import android.support.v7.media.MediaItemStatus;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -193,11 +201,17 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
playerCB = mRemotePlayer;
|
playerCB = mRemotePlayer;
|
||||||
mRemotePlayer.reset();
|
mRemotePlayer.reset();
|
||||||
|
|
||||||
|
// Create and register the remote control client
|
||||||
|
registerRCC();
|
||||||
} else {
|
} else {
|
||||||
// Local Playback:
|
// Local Playback:
|
||||||
// Use local player and feed media player one item at a time
|
// Use local player and feed media player one item at a time
|
||||||
player = mLocalPlayer;
|
player = mLocalPlayer;
|
||||||
playerCB = mMediaPlayer;
|
playerCB = mMediaPlayer;
|
||||||
|
|
||||||
|
// Unregister the remote control client
|
||||||
|
unregisterRCC();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player != mPlayer || playerCB != mPlayerCB) {
|
if (player != mPlayer || playerCB != mPlayerCB) {
|
||||||
@@ -301,6 +315,24 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private RemoteControlClient mRemoteControlClient;
|
||||||
|
private ComponentName mEventReceiver;
|
||||||
|
private AudioManager mAudioManager;
|
||||||
|
private PendingIntent mMediaPendingIntent;
|
||||||
|
private final OnAudioFocusChangeListener mAfChangeListener =
|
||||||
|
new OnAudioFocusChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onAudioFocusChange(int focusChange) {
|
||||||
|
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
|
||||||
|
Log.d(TAG, "onAudioFocusChange: LOSS_TRANSIENT");
|
||||||
|
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
|
||||||
|
Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_GAIN");
|
||||||
|
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
|
||||||
|
Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_LOSS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
// Be sure to call the super class.
|
// Be sure to call the super class.
|
||||||
@@ -471,6 +503,97 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
|
|||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(SampleMediaRouterActivity.ACTION_STATUS_CHANGE);
|
filter.addAction(SampleMediaRouterActivity.ACTION_STATUS_CHANGE);
|
||||||
registerReceiver(mReceiver, filter);
|
registerReceiver(mReceiver, filter);
|
||||||
|
|
||||||
|
// Build the PendingIntent for the remote control client
|
||||||
|
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
mEventReceiver = new ComponentName(getPackageName(),
|
||||||
|
SampleMediaButtonReceiver.class.getName());
|
||||||
|
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||||
|
mediaButtonIntent.setComponent(mEventReceiver);
|
||||||
|
mMediaPendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerRCC() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||||
|
// Create the RCC and register with AudioManager and MediaRouter
|
||||||
|
mAudioManager.requestAudioFocus(mAfChangeListener,
|
||||||
|
AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
|
||||||
|
mAudioManager.registerMediaButtonEventReceiver(mEventReceiver);
|
||||||
|
mRemoteControlClient = new RemoteControlClient(mMediaPendingIntent);
|
||||||
|
mAudioManager.registerRemoteControlClient(mRemoteControlClient);
|
||||||
|
mMediaRouter.addRemoteControlClient(mRemoteControlClient);
|
||||||
|
SampleMediaButtonReceiver.setActivity(SampleMediaRouterActivity.this);
|
||||||
|
mRemoteControlClient.setTransportControlFlags(
|
||||||
|
RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE);
|
||||||
|
mRemoteControlClient.setPlaybackState(
|
||||||
|
RemoteControlClient.PLAYSTATE_PLAYING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregisterRCC() {
|
||||||
|
// Unregister the RCC with AudioManager and MediaRouter
|
||||||
|
if (mRemoteControlClient != null) {
|
||||||
|
mRemoteControlClient.setTransportControlFlags(0);
|
||||||
|
mAudioManager.abandonAudioFocus(mAfChangeListener);
|
||||||
|
mAudioManager.unregisterMediaButtonEventReceiver(mEventReceiver);
|
||||||
|
mAudioManager.unregisterRemoteControlClient(mRemoteControlClient);
|
||||||
|
mMediaRouter.removeRemoteControlClient(mRemoteControlClient);
|
||||||
|
SampleMediaButtonReceiver.setActivity(null);
|
||||||
|
mRemoteControlClient = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleMediaKey(KeyEvent event) {
|
||||||
|
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
|
||||||
|
switch (event.getKeyCode()) {
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
|
{
|
||||||
|
Log.d(TAG, "Received Play/Pause event from RemoteControlClient");
|
||||||
|
if (!mPaused) {
|
||||||
|
mPlayer.pause();
|
||||||
|
} else {
|
||||||
|
mPlayer.resume();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||||
|
{
|
||||||
|
Log.d(TAG, "Received Play event from RemoteControlClient");
|
||||||
|
if (mPaused) {
|
||||||
|
mPlayer.resume();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||||
|
{
|
||||||
|
Log.d(TAG, "Received Pause event from RemoteControlClient");
|
||||||
|
if (!mPaused) {
|
||||||
|
mPlayer.pause();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||||
|
{
|
||||||
|
Log.d(TAG, "Received Stop event from RemoteControlClient");
|
||||||
|
mPlayer.stop();
|
||||||
|
clearContent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
|
return handleMediaKey(event) || super.onKeyDown(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
|
return handleMediaKey(event) || super.onKeyUp(keyCode, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -549,6 +672,10 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
|
|||||||
// only enable seek bar when duration is known
|
// only enable seek bar when duration is known
|
||||||
MediaQueueItem item = getCheckedMediaQueueItem();
|
MediaQueueItem item = getCheckedMediaQueueItem();
|
||||||
mSeekBar.setEnabled(item != null && item.getContentDuration() > 0);
|
mSeekBar.setEnabled(item != null && item.getContentDuration() > 0);
|
||||||
|
if (mRemoteControlClient != null) {
|
||||||
|
mRemoteControlClient.setPlaybackState(mPaused ?
|
||||||
|
RemoteControlClient.PLAYSTATE_PAUSED : RemoteControlClient.PLAYSTATE_PLAYING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProgress(MediaQueueItem queueItem) {
|
private void updateProgress(MediaQueueItem queueItem) {
|
||||||
@@ -684,6 +811,13 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
|
|||||||
Log.d(TAG, "LocalPlayer: enqueue, uri=" + uri + ", pos=" + pos);
|
Log.d(TAG, "LocalPlayer: enqueue, uri=" + uri + ", pos=" + pos);
|
||||||
MediaQueueItem playlistItem = mSessionManager.enqueue(mSessionId, uri, null);
|
MediaQueueItem playlistItem = mSessionManager.enqueue(mSessionId, uri, null);
|
||||||
mSessionId = playlistItem.getSessionId();
|
mSessionId = playlistItem.getSessionId();
|
||||||
|
// Set remote control client title
|
||||||
|
if (mPlayListItems.getCount() == 0 && mRemoteControlClient != null) {
|
||||||
|
RemoteControlClient.MetadataEditor ed = mRemoteControlClient.editMetadata(true);
|
||||||
|
ed.putString(MediaMetadataRetriever.METADATA_KEY_TITLE,
|
||||||
|
playlistItem.toString());
|
||||||
|
ed.apply();
|
||||||
|
}
|
||||||
mPlayListItems.add(playlistItem);
|
mPlayListItems.add(playlistItem);
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
// Seek to initial position if needed
|
// Seek to initial position if needed
|
||||||
|
|||||||
Reference in New Issue
Block a user