Implemented RemoteControlClient in PlaybackService

This commit is contained in:
daniel oeh 2012-08-18 15:55:58 +02:00
parent 6336db46ed
commit 095618855d
1 changed files with 83 additions and 7 deletions

View File

@ -15,7 +15,10 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener; import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.media.RemoteControlClient;
import android.media.RemoteControlClient.MetadataEditor;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
@ -29,13 +32,16 @@ import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AudioplayerActivity; import de.danoeh.antennapod.activity.AudioplayerActivity;
import de.danoeh.antennapod.activity.VideoplayerActivity; import de.danoeh.antennapod.activity.VideoplayerActivity;
import de.danoeh.antennapod.asynctask.FeedImageLoader;
import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.feed.Feed;
import de.danoeh.antennapod.feed.FeedImage;
import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.feed.FeedManager;
import de.danoeh.antennapod.feed.FeedMedia; import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.feed.SimpleChapter; import de.danoeh.antennapod.feed.SimpleChapter;
import de.danoeh.antennapod.receiver.MediaButtonReceiver; import de.danoeh.antennapod.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.receiver.PlayerWidget; import de.danoeh.antennapod.receiver.PlayerWidget;
import de.danoeh.antennapod.util.Converter;
/** Controls the MediaPlayer that plays a FeedMedia-file */ /** Controls the MediaPlayer that plays a FeedMedia-file */
public class PlaybackService extends Service { public class PlaybackService extends Service {
@ -94,6 +100,7 @@ public class PlaybackService extends Service {
private ComponentName mediaButtonReceiver; private ComponentName mediaButtonReceiver;
private MediaPlayer player; private MediaPlayer player;
private RemoteControlClient remoteControlClient;
private FeedMedia media; private FeedMedia media;
private Feed feed; private Feed feed;
@ -157,6 +164,7 @@ public class PlaybackService extends Service {
} }
} }
@SuppressLint("NewApi")
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -177,11 +185,16 @@ public class PlaybackService extends Service {
mediaButtonReceiver = new ComponentName(getPackageName(), mediaButtonReceiver = new ComponentName(getPackageName(),
MediaButtonReceiver.class.getName()); MediaButtonReceiver.class.getName());
audioManager.registerMediaButtonEventReceiver(mediaButtonReceiver); audioManager.registerMediaButtonEventReceiver(mediaButtonReceiver);
if (android.os.Build.VERSION.SDK_INT >= 14) {
audioManager
.registerRemoteControlClient(setupRemoteControlClient());
}
registerReceiver(headsetDisconnected, new IntentFilter( registerReceiver(headsetDisconnected, new IntentFilter(
Intent.ACTION_HEADSET_PLUG)); Intent.ACTION_HEADSET_PLUG));
} }
@SuppressLint("NewApi")
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
@ -190,6 +203,9 @@ public class PlaybackService extends Service {
unregisterReceiver(headsetDisconnected); unregisterReceiver(headsetDisconnected);
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Service is about to be destroyed"); Log.d(TAG, "Service is about to be destroyed");
if (android.os.Build.VERSION.SDK_INT >= 14) {
audioManager.unregisterRemoteControlClient(remoteControlClient);
}
audioManager.unregisterMediaButtonEventReceiver(mediaButtonReceiver); audioManager.unregisterMediaButtonEventReceiver(mediaButtonReceiver);
audioManager.abandonAudioFocus(audioFocusChangeListener); audioManager.abandonAudioFocus(audioFocusChangeListener);
player.release(); player.release();
@ -295,7 +311,7 @@ public class PlaybackService extends Service {
switch (keycode) { switch (keycode) {
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
if (status == PlayerStatus.PLAYING) { if (status == PlayerStatus.PLAYING) {
pause(true); pause(false);
} else if (status == PlayerStatus.PAUSED) { } else if (status == PlayerStatus.PAUSED) {
play(); play();
} }
@ -307,7 +323,7 @@ public class PlaybackService extends Service {
break; break;
case KeyEvent.KEYCODE_MEDIA_PAUSE: case KeyEvent.KEYCODE_MEDIA_PAUSE:
if (status == PlayerStatus.PLAYING) { if (status == PlayerStatus.PLAYING) {
pause(true); pause(false);
} }
break; break;
} }
@ -433,7 +449,8 @@ public class PlaybackService extends Service {
Log.d(TAG, "Resource prepared"); Log.d(TAG, "Resource prepared");
mp.seekTo(media.getPosition()); mp.seekTo(media.getPosition());
if (media.getDuration() == 0) { if (media.getDuration() == 0) {
if (AppConfig.DEBUG) Log.d(TAG, "Setting duration of media"); if (AppConfig.DEBUG)
Log.d(TAG, "Setting duration of media");
media.setDuration(mp.getDuration()); media.setDuration(mp.getDuration());
} }
setStatus(PlayerStatus.PREPARED); setStatus(PlayerStatus.PREPARED);
@ -455,7 +472,7 @@ public class PlaybackService extends Service {
}; };
private MediaPlayer.OnInfoListener onInfoListener = new MediaPlayer.OnInfoListener() { private MediaPlayer.OnInfoListener onInfoListener = new MediaPlayer.OnInfoListener() {
@Override @Override
public boolean onInfo(MediaPlayer mp, int what, int extra) { public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) { switch (what) {
@ -465,12 +482,12 @@ public class PlaybackService extends Service {
case MediaPlayer.MEDIA_INFO_BUFFERING_END: case MediaPlayer.MEDIA_INFO_BUFFERING_END:
sendNotificationBroadcast(NOTIFICATION_TYPE_BUFFER_END, 0); sendNotificationBroadcast(NOTIFICATION_TYPE_BUFFER_END, 0);
return true; return true;
default: default:
return false; return false;
} }
} }
}; };
private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() { private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() {
private static final String TAG = "PlaybackService.onErrorListener"; private static final String TAG = "PlaybackService.onErrorListener";
@ -521,6 +538,7 @@ public class PlaybackService extends Service {
notificationCode = EXTRA_CODE_VIDEO; notificationCode = EXTRA_CODE_VIDEO;
} }
resetVideoSurface(); resetVideoSurface();
refreshRemoteControlClientState();
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
notificationCode); notificationCode);
} else { } else {
@ -636,6 +654,7 @@ public class PlaybackService extends Service {
status = newStatus; status = newStatus;
sendBroadcast(new Intent(ACTION_PLAYER_STATUS_CHANGED)); sendBroadcast(new Intent(ACTION_PLAYER_STATUS_CHANGED));
updateWidget(); updateWidget();
refreshRemoteControlClientState();
} }
private void sendNotificationBroadcast(int type, int code) { private void sendNotificationBroadcast(int type, int code) {
@ -735,6 +754,63 @@ public class PlaybackService extends Service {
} }
} }
@SuppressLint("NewApi")
private RemoteControlClient setupRemoteControlClient() {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setComponent(mediaButtonReceiver);
PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 0, mediaButtonIntent, 0);
remoteControlClient = new RemoteControlClient(mediaPendingIntent);
remoteControlClient
.setTransportControlFlags(RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE);
return remoteControlClient;
}
/** Refresh player status and metadata. */
@SuppressLint("NewApi")
private void refreshRemoteControlClientState() {
if (android.os.Build.VERSION.SDK_INT >= 14) {
if (remoteControlClient != null) {
switch (status) {
case PLAYING:
remoteControlClient
.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
break;
case PAUSED:
remoteControlClient
.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
break;
case STOPPED:
remoteControlClient
.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
break;
case ERROR:
remoteControlClient
.setPlaybackState(RemoteControlClient.PLAYSTATE_ERROR);
break;
default:
remoteControlClient
.setPlaybackState(RemoteControlClient.PLAYSTATE_BUFFERING);
}
if (media != null) {
MetadataEditor editor = remoteControlClient
.editMetadata(false);
editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE,
media.getItem().getTitle());
editor.putLong(
MediaMetadataRetriever.METADATA_KEY_DURATION,
media.getDuration());
editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM,
media.getItem().getFeed().getTitle());
editor.apply();
}
if (AppConfig.DEBUG)
Log.d(TAG, "RemoteControlClient state was refreshed");
}
}
}
/** /**
* Pauses playback when the headset is disconnected and the preference is * Pauses playback when the headset is disconnected and the preference is
* set * set