diff --git a/build.gradle b/build.gradle index 6e77fb3ae..7e4738052 100644 --- a/build.gradle +++ b/build.gradle @@ -5,13 +5,11 @@ buildscript { mavenCentral() mavenLocal() jcenter() - maven { url 'https://maven.fabric.io/public' } } dependencies { classpath 'com.android.tools.build:gradle:1.2.0-beta1' - classpath 'me.tatarka:gradle-retrolambda:3.0.0' - classpath 'io.fabric.tools:gradle:1.18.0' + classpath 'me.tatarka:gradle-retrolambda:3.0.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -20,7 +18,6 @@ buildscript { allprojects { repositories { maven { url 'http://dl.bintray.com/kelsos/maven' } - maven { url 'https://maven.fabric.io/public' } mavenCentral() mavenLocal() jcenter() diff --git a/remote/build.gradle b/remote/build.gradle index 1d1e8f6e5..53e47c11a 100644 --- a/remote/build.gradle +++ b/remote/build.gradle @@ -2,7 +2,6 @@ import java.text.SimpleDateFormat apply plugin: 'me.tatarka.retrolambda' apply plugin: 'com.android.application' -apply plugin: 'io.fabric' apply plugin: 'checkstyle' apply plugin: 'findbugs' apply plugin: 'pmd' @@ -18,16 +17,6 @@ def gitHash() { return "git -C ${rootDir} rev-parse --short HEAD".execute().text.trim() } -// Load the fabric api key. -def fabricApiKey = "" -def crashProperties = file('fabric.properties') - -if (crashProperties.exists()) { - def properties = new Properties() - properties.load(new FileInputStream(crashProperties)) - fabricApiKey = properties.getAt('apiKey') -} - def hasModifiedDeletedOrOtherFiles() { return !"git -C ${rootDir} ls-files -mdo --exclude-standard".execute().text.trim().isEmpty() } @@ -58,7 +47,6 @@ android { versionName "0.10.0-rc.3" buildConfigField "String", "GIT_SHA", "\"${gitHash()}\"" buildConfigField "String", "BUILD_TIME", "\"${buildTime()}\"" - manifestPlaceholders = [fabricApiKey: fabricApiKey] } signingConfigs { @@ -156,9 +144,6 @@ dependencies { compile 'com.jakewharton:butterknife:6.1.0' compile 'io.reactivex:rxandroid:0.24.0' provided 'org.roboguice:roboblender:3.0.1' - compile('com.crashlytics.sdk.android:crashlytics:2.2.2@aar') { - transitive = true; - } } allprojects { diff --git a/remote/src/main/AndroidManifest.xml b/remote/src/main/AndroidManifest.xml index fc0d67585..ff5480bdc 100644 --- a/remote/src/main/AndroidManifest.xml +++ b/remote/src/main/AndroidManifest.xml @@ -71,6 +71,15 @@ + + + + + + + + + @@ -78,8 +87,5 @@ android:name="roboguice.annotations.packages" android:value="roboguice,mbrc" /> - diff --git a/remote/src/main/java/com/kelsos/mbrc/RemoteApplication.java b/remote/src/main/java/com/kelsos/mbrc/RemoteApplication.java index 7a596ace7..c9785b620 100644 --- a/remote/src/main/java/com/kelsos/mbrc/RemoteApplication.java +++ b/remote/src/main/java/com/kelsos/mbrc/RemoteApplication.java @@ -4,14 +4,12 @@ import android.content.Intent; import android.util.Log; import android.view.ViewConfiguration; -import com.crashlytics.android.Crashlytics; import com.kelsos.mbrc.controller.RemoteService; import com.kelsos.mbrc.messaging.NotificationService; import com.kelsos.mbrc.model.MainDataModel; import com.kelsos.mbrc.services.ProtocolHandler; import com.kelsos.mbrc.services.SocketService; import com.kelsos.mbrc.utilities.RemoteBroadcastReceiver; -import io.fabric.sdk.android.Fabric; import java.lang.reflect.Field; import roboguice.RoboGuice; import roboguice.inject.RoboInjector; @@ -20,7 +18,6 @@ public class RemoteApplication extends Application { public void onCreate() { super.onCreate(); - Fabric.with(this, new Crashlytics()); final RoboInjector injector = RoboGuice.getInjector(this); startService(new Intent(this, RemoteService.class)); diff --git a/remote/src/main/java/com/kelsos/mbrc/commands/ProcessUserAction.java b/remote/src/main/java/com/kelsos/mbrc/commands/ProcessUserAction.java index aa6caf99c..8922cd6ac 100644 --- a/remote/src/main/java/com/kelsos/mbrc/commands/ProcessUserAction.java +++ b/remote/src/main/java/com/kelsos/mbrc/commands/ProcessUserAction.java @@ -15,6 +15,7 @@ public class ProcessUserAction implements ICommand { } @Override public void execute(IEvent e) { - socket.sendData(new SocketMessage(((UserAction) e.getData()).getContext(), ((UserAction) e.getData()).getData())); + socket.sendData(new SocketMessage(((UserAction) e.getData()).getContext(), + ((UserAction) e.getData()).getData())); } } diff --git a/remote/src/main/java/com/kelsos/mbrc/commands/ProtocolPingHandle.java b/remote/src/main/java/com/kelsos/mbrc/commands/ProtocolPingHandle.java index 13b89e6b4..0aade6127 100644 --- a/remote/src/main/java/com/kelsos/mbrc/commands/ProtocolPingHandle.java +++ b/remote/src/main/java/com/kelsos/mbrc/commands/ProtocolPingHandle.java @@ -6,7 +6,6 @@ import com.kelsos.mbrc.interfaces.ICommand; import com.kelsos.mbrc.interfaces.IEvent; import com.kelsos.mbrc.services.SocketService; -import com.kelsos.mbrc.utilities.RemoteUtils; public class ProtocolPingHandle implements ICommand { private final SocketService service; @@ -16,6 +15,6 @@ public class ProtocolPingHandle implements ICommand { } @Override public void execute(IEvent e) { - service.sendData(new SocketMessage(Protocol.PONG, RemoteUtils.getUtcNow())); + service.sendData(new SocketMessage(Protocol.PONG, "")); } } diff --git a/remote/src/main/java/com/kelsos/mbrc/configuration/CommandRegistration.java b/remote/src/main/java/com/kelsos/mbrc/configuration/CommandRegistration.java index 6da1939d2..26d7c8b88 100644 --- a/remote/src/main/java/com/kelsos/mbrc/configuration/CommandRegistration.java +++ b/remote/src/main/java/com/kelsos/mbrc/configuration/CommandRegistration.java @@ -140,7 +140,8 @@ public static void unregister(RemoteController controller) { controller.unregister(UserInputEventType.KeyVolumeUp, KeyVolumeUpCommand.class); controller.unregister(UserInputEventType.KeyVolumeDown, KeyVolumeDownCommand.class); controller.unregister(SocketEventType.SocketDataAvailable, SocketDataAvailableCommand.class); - controller.unregister(SocketEventType.SocketStatusChanged, ConnectionStatusChangedCommand.class); + controller.unregister(SocketEventType.SocketStatusChanged, + ConnectionStatusChangedCommand.class); controller.unregister(SocketEventType.SocketHandshakeUpdate, HandleHandshake.class); } } diff --git a/remote/src/main/java/com/kelsos/mbrc/controller/RemoteController.java b/remote/src/main/java/com/kelsos/mbrc/controller/RemoteController.java index fbf10a6dc..3f30aaf53 100644 --- a/remote/src/main/java/com/kelsos/mbrc/controller/RemoteController.java +++ b/remote/src/main/java/com/kelsos/mbrc/controller/RemoteController.java @@ -73,7 +73,6 @@ public synchronized void executeCommand(IEvent event) { //noinspection InfiniteLoopStatement while (true) { executeCommand(eventQueue.take()); - Ln.d("Executing"); } } catch (InterruptedException e) { Ln.d(e); diff --git a/remote/src/main/java/com/kelsos/mbrc/controller/RemoteService.java b/remote/src/main/java/com/kelsos/mbrc/controller/RemoteService.java index c26e9f515..5eb417a5c 100644 --- a/remote/src/main/java/com/kelsos/mbrc/controller/RemoteService.java +++ b/remote/src/main/java/com/kelsos/mbrc/controller/RemoteService.java @@ -9,6 +9,8 @@ import com.kelsos.mbrc.constants.UserInputEventType; import com.kelsos.mbrc.events.MessageEvent; import com.squareup.otto.Subscribe; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import roboguice.service.RoboService; import roboguice.util.Ln; @@ -17,7 +19,7 @@ private final IBinder mBinder = new ControllerBinder(); @Inject private RemoteController remoteController; - private Thread controllerThread; + private ExecutorService threadPoolExecutor; public RemoteService() { } @@ -37,8 +39,8 @@ public RemoteService() { } @Override public int onStartCommand(Intent intent, int flags, int startId) { Ln.d("Background Service::Started"); CommandRegistration.register(remoteController); - controllerThread = new Thread(remoteController); - controllerThread.start(); + threadPoolExecutor = Executors.newSingleThreadExecutor(); + threadPoolExecutor.execute(remoteController); return super.onStartCommand(intent, flags, startId); } @@ -46,9 +48,8 @@ public RemoteService() { } remoteController.executeCommand(new MessageEvent(UserInputEventType.CancelNotification)); remoteController.executeCommand(new MessageEvent(UserInputEventType.TerminateConnection)); CommandRegistration.unregister(remoteController); - if (controllerThread != null && controllerThread.isAlive()) { - controllerThread.interrupt(); - controllerThread = null; + if (threadPoolExecutor != null) { + threadPoolExecutor.shutdownNow(); } Ln.d("Background Service::Destroyed"); super.onDestroy(); diff --git a/remote/src/main/java/com/kelsos/mbrc/events/ui/RemoteClientMetaData.java b/remote/src/main/java/com/kelsos/mbrc/events/ui/RemoteClientMetaData.java new file mode 100644 index 000000000..0b75e1e2c --- /dev/null +++ b/remote/src/main/java/com/kelsos/mbrc/events/ui/RemoteClientMetaData.java @@ -0,0 +1,33 @@ +package com.kelsos.mbrc.events.ui; + +import android.graphics.Bitmap; + +public class RemoteClientMetaData { + private final String artist; + private final String title; + private final String album; + private final Bitmap cover; + + public RemoteClientMetaData(String artist, String title, String album, Bitmap cover) { + this.artist = artist; + this.title = title; + this.album = album; + this.cover = cover; + } + + public String getArtist() { + return artist; + } + + public String getTitle() { + return title; + } + + public String getAlbum() { + return album; + } + + public Bitmap getCover() { + return cover; + } +} diff --git a/remote/src/main/java/com/kelsos/mbrc/model/MainDataModel.java b/remote/src/main/java/com/kelsos/mbrc/model/MainDataModel.java index 6f403d87c..aa6f8462b 100644 --- a/remote/src/main/java/com/kelsos/mbrc/model/MainDataModel.java +++ b/remote/src/main/java/com/kelsos/mbrc/model/MainDataModel.java @@ -30,6 +30,7 @@ import com.kelsos.mbrc.events.ui.OnMainFragmentOptionsInflated; import com.kelsos.mbrc.events.ui.PlayStateChange; import com.kelsos.mbrc.events.ui.RatingChanged; +import com.kelsos.mbrc.events.ui.RemoteClientMetaData; import com.kelsos.mbrc.events.ui.RepeatChange; import com.kelsos.mbrc.events.ui.ScrobbleChange; import com.kelsos.mbrc.events.ui.ShuffleChange; @@ -201,6 +202,11 @@ public void setTrackInfo(String artist, String album, String title, String year) this.title = title; bus.post(new TrackInfoChange(artist, title, album, year)); updateNotification(); + updateRemoteClient(); + } + + private void updateRemoteClient() { + bus.post(new RemoteClientMetaData(artist, title, album, cover)); } @Produce public TrackInfoChange produceTrackInfo() { @@ -231,6 +237,7 @@ public void setCover(final String base64format) { cover = null; bus.post(new CoverAvailable()); updateNotification(); + updateRemoteClient(); } else { Observable.create((Subscriber subscriber) -> { byte[] decodedImage = Base64.decode(base64format, Base64.DEFAULT); @@ -248,6 +255,7 @@ public void setAlbumCover(Bitmap cover) { this.cover = cover; bus.post(new CoverAvailable(cover)); updateNotification(); + updateRemoteClient(); } @Produce public CoverAvailable produceAvailableCover() { diff --git a/remote/src/main/java/com/kelsos/mbrc/services/ProtocolHandler.java b/remote/src/main/java/com/kelsos/mbrc/services/ProtocolHandler.java index a843757d4..53a239c67 100644 --- a/remote/src/main/java/com/kelsos/mbrc/services/ProtocolHandler.java +++ b/remote/src/main/java/com/kelsos/mbrc/services/ProtocolHandler.java @@ -49,7 +49,7 @@ public void preProcessIncoming(final String incoming) { } else if (context.contains(Protocol.ProtocolTag)) { double protocolVersion; - try{ + try { protocolVersion = Double.parseDouble(node.path(Const.DATA).asText()); } catch (Exception ignore) { protocolVersion = 2.0; diff --git a/remote/src/main/java/com/kelsos/mbrc/services/RemoteSessionManager.java b/remote/src/main/java/com/kelsos/mbrc/services/RemoteSessionManager.java index 0174631b2..f3fb2db2a 100644 --- a/remote/src/main/java/com/kelsos/mbrc/services/RemoteSessionManager.java +++ b/remote/src/main/java/com/kelsos/mbrc/services/RemoteSessionManager.java @@ -1,50 +1,58 @@ package com.kelsos.mbrc.services; +import android.annotation.TargetApi; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.media.AudioManager; +import android.media.RemoteControlClient; +import android.os.Build; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import com.google.inject.Inject; import com.google.inject.Singleton; import com.kelsos.mbrc.enums.PlayState; -import com.kelsos.mbrc.events.ui.NotificationDataAvailable; import com.kelsos.mbrc.events.ui.PlayStateChange; +import com.kelsos.mbrc.events.ui.RemoteClientMetaData; import com.kelsos.mbrc.utilities.MediaButtonReceiver; import com.squareup.otto.Bus; import com.squareup.otto.Subscribe; +import roboguice.util.Ln; -@Singleton -public class RemoteSessionManager { +@Singleton public class RemoteSessionManager implements AudioManager.OnAudioFocusChangeListener { private static final long PLAYBACK_ACTIONS = PlaybackStateCompat.ACTION_PAUSE - | PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_SKIP_TO_NEXT - | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | PlaybackStateCompat.ACTION_STOP; - + | PlaybackStateCompat.ACTION_PLAY + | PlaybackStateCompat.ACTION_SKIP_TO_NEXT + | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS + | PlaybackStateCompat.ACTION_STOP; + private final AudioManager manager; private MediaSessionCompat mMediaSession; - @Inject + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Inject public RemoteSessionManager(final Context context, final Bus bus, final AudioManager manager) { + this.manager = manager; bus.register(this); - ComponentName myEventReceiver = new ComponentName(context.getPackageName(), - MediaButtonReceiver.class.getName()); + ComponentName myEventReceiver = + new ComponentName(context.getPackageName(), MediaButtonReceiver.class.getName()); Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.setComponent(myEventReceiver); - PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), - 0, mediaButtonIntent, 0); + PendingIntent mediaPendingIntent = + PendingIntent.getBroadcast(context.getApplicationContext(), 0, mediaButtonIntent, + PendingIntent.FLAG_UPDATE_CURRENT); mMediaSession = new MediaSessionCompat(context, "Session", myEventReceiver, mediaPendingIntent); - } + mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS + | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); + } public MediaSessionCompat.Token getMediaSessionToken() { return mMediaSession.getSessionToken(); } - - @Subscribe public void metadataUpdate(NotificationDataAvailable data) { + @Subscribe public void metadataUpdate(RemoteClientMetaData data) { if (mMediaSession == null) { return; } @@ -77,10 +85,96 @@ public MediaSessionCompat.Token getMediaSessionToken() { } PlaybackStateCompat playbackState = builder.build(); mMediaSession.setPlaybackState(playbackState); + ensureTransportControls(playbackState); mMediaSession.setActive(stateChange.getState() != PlayState.Stopped || stateChange.getState() != PlayState.Undefined); } + @Subscribe public void onPlayStateChange(PlayStateChange change) { + switch (change.getState()) { + case Playing: + requestFocus(); + break; + case Paused: + break; + default: + abandonFocus(); + break; + } + } + + @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + private void ensureTransportControls(PlaybackStateCompat playbackState) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH + || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + return; + } + + long actions = playbackState.getActions(); + Object remoteObj = mMediaSession.getRemoteControlClient(); + if (actions != 0 && remoteObj != null) { + + int transportControls = 0; + + if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS; + } + + if ((actions & PlaybackStateCompat.ACTION_REWIND) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_REWIND; + } + + if ((actions & PlaybackStateCompat.ACTION_PLAY) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY; + } + + if ((actions & PlaybackStateCompat.ACTION_PLAY_PAUSE) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE; + } + + if ((actions & PlaybackStateCompat.ACTION_PAUSE) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PAUSE; + } + + if ((actions & PlaybackStateCompat.ACTION_STOP) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_STOP; + } + + if ((actions & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD; + } + + if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) { + transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_NEXT; + } + + ((RemoteControlClient) remoteObj).setTransportControlFlags(transportControls); + } + } + + private boolean requestFocus() { + return AudioManager.AUDIOFOCUS_REQUEST_GRANTED == manager.requestAudioFocus(this, + AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + } + + private boolean abandonFocus() { + return AudioManager.AUDIOFOCUS_REQUEST_GRANTED == manager.abandonAudioFocus(this); + } + public void onAudioFocusChange(int focusChange) { + switch (focusChange) { + case AudioManager.AUDIOFOCUS_GAIN: + Ln.d("gained"); + break; + case AudioManager.AUDIOFOCUS_LOSS: + case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: + Ln.d("transient loss"); + break; + case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: + Ln.d("Loss can duck"); + break; + default: + } + } } diff --git a/remote/src/main/java/com/kelsos/mbrc/ui/activities/MainFragmentActivity.java b/remote/src/main/java/com/kelsos/mbrc/ui/activities/MainFragmentActivity.java index 47454e3a1..f60547c68 100644 --- a/remote/src/main/java/com/kelsos/mbrc/ui/activities/MainFragmentActivity.java +++ b/remote/src/main/java/com/kelsos/mbrc/ui/activities/MainFragmentActivity.java @@ -47,7 +47,8 @@ public class MainFragmentActivity extends RoboActionBarActivity { private boolean isMyServiceRunning(Class serviceClass) { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); - for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices( + Integer.MAX_VALUE)) { if (serviceClass.getName().equals(service.service.getClassName())) { return true; } diff --git a/remote/src/main/java/com/kelsos/mbrc/ui/fragments/MainFragment.java b/remote/src/main/java/com/kelsos/mbrc/ui/fragments/MainFragment.java index 0a03c6c37..7843bf3a1 100644 --- a/remote/src/main/java/com/kelsos/mbrc/ui/fragments/MainFragment.java +++ b/remote/src/main/java/com/kelsos/mbrc/ui/fragments/MainFragment.java @@ -106,9 +106,11 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } } - public void onStartTrackingTouch(SeekBar seekBar) { } + public void onStartTrackingTouch(SeekBar seekBar) { + } - public void onStopTrackingTouch(SeekBar seekBar) { } + public void onStopTrackingTouch(SeekBar seekBar) { + } }; @OnClick(R.id.main_button_play_pause) public void playButtonPressed(View v) { diff --git a/remote/src/main/java/com/kelsos/mbrc/utilities/MediaButtonReceiver.java b/remote/src/main/java/com/kelsos/mbrc/utilities/MediaButtonReceiver.java index 5dc43ef3b..eaa83c7c3 100644 --- a/remote/src/main/java/com/kelsos/mbrc/utilities/MediaButtonReceiver.java +++ b/remote/src/main/java/com/kelsos/mbrc/utilities/MediaButtonReceiver.java @@ -2,13 +2,58 @@ import android.content.Context; import android.content.Intent; +import android.view.KeyEvent; +import com.google.inject.Inject; +import com.kelsos.mbrc.constants.Protocol; +import com.kelsos.mbrc.constants.ProtocolEventType; +import com.kelsos.mbrc.data.UserAction; +import com.kelsos.mbrc.events.MessageEvent; +import com.squareup.otto.Bus; import roboguice.receiver.RoboBroadcastReceiver; -import roboguice.util.Ln; public class MediaButtonReceiver extends RoboBroadcastReceiver { + @Inject Bus bus; + + private void postAction(UserAction action) { + bus.post(new MessageEvent(ProtocolEventType.UserAction, action)); + } + @Override protected void handleReceive(Context context, Intent intent) { - super.handleReceive(context, intent); - Ln.d(intent.getAction()); + if (intent.getAction().equals(android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { + // Handle somehow + } else if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) { + KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT); + + if (keyEvent.getAction() != KeyEvent.ACTION_DOWN) { + return; + } + + switch (keyEvent.getKeyCode()) { + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + postAction(new UserAction(Protocol.PlayerPlayPause, true)); + break; + case KeyEvent.KEYCODE_MEDIA_PLAY: + // + break; + case KeyEvent.KEYCODE_MEDIA_PAUSE: + // + break; + case KeyEvent.KEYCODE_MEDIA_STOP: + postAction(new UserAction(Protocol.PlayerStop, true)); + break; + case KeyEvent.KEYCODE_MEDIA_NEXT: + postAction(new UserAction(Protocol.PlayerNext, true)); + break; + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + // TODO: ensure that doing this in rapid succession actually plays the + // previous song + postAction(new UserAction(Protocol.PlayerPrevious, true)); + break; + default: + break; + } + } } }