diff --git a/ultrasonic/src/main/AndroidManifest.xml b/ultrasonic/src/main/AndroidManifest.xml
index 4957fe6d..98132a26 100644
--- a/ultrasonic/src/main/AndroidManifest.xml
+++ b/ultrasonic/src/main/AndroidManifest.xml
@@ -126,14 +126,6 @@
android:name=".service.MediaPlayerService"
android:label="Ultrasonic Download Service"
android:exported="false">
-
-
-
-
-
-
-
-
@@ -141,6 +133,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java
index 5c70c13c..a9791d67 100644
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java
+++ b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java
@@ -94,13 +94,13 @@ public class BluetoothIntentReceiver extends BroadcastReceiver
if (resume)
{
Log.i(TAG, String.format("Connected to Bluetooth device %s address %s, resuming playback.", name, address));
- context.sendBroadcast(new Intent(Constants.CMD_PLAY));
+ context.sendBroadcast(new Intent(Constants.CMD_RESUME_OR_PLAY).setPackage(context.getPackageName()));
}
if (pause)
{
Log.i(TAG, String.format("Disconnected from Bluetooth device %s address %s, requesting pause.", name, address));
- context.sendBroadcast(new Intent(Constants.CMD_PAUSE));
+ context.sendBroadcast(new Intent(Constants.CMD_PAUSE).setPackage(context.getPackageName()));
}
}
}
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/UltrasonicIntentReceiver.java b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/UltrasonicIntentReceiver.java
new file mode 100644
index 00000000..7b8ba2ec
--- /dev/null
+++ b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/UltrasonicIntentReceiver.java
@@ -0,0 +1,39 @@
+package org.moire.ultrasonic.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import org.moire.ultrasonic.service.MediaPlayerLifecycleSupport;
+
+import kotlin.Lazy;
+
+import static org.koin.java.KoinJavaComponent.inject;
+
+public class UltrasonicIntentReceiver extends BroadcastReceiver
+{
+ private static final String TAG = UltrasonicIntentReceiver.class.getSimpleName();
+ private Lazy lifecycleSupport = inject(MediaPlayerLifecycleSupport.class);
+
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ String intentAction = intent.getAction();
+ Log.i(TAG, String.format("Received Ultrasonic Intent: %s", intentAction));
+
+ try
+ {
+ lifecycleSupport.getValue().receiveIntent(intent);
+
+ if (isOrderedBroadcast())
+ {
+ abortBroadcast();
+ }
+ }
+ catch (Exception x)
+ {
+ // Ignored.
+ }
+ }
+}
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java
index ce016bd1..64823cfd 100644
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java
+++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java
@@ -89,7 +89,7 @@ public class Downloader
public void stop()
{
- executorService.shutdown();
+ if (executorService != null) executorService.shutdown();
Log.i(TAG, "Downloader stopped");
}
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java
index bbe29d7e..26c95f45 100644
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java
+++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java
@@ -170,6 +170,16 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
});
}
+ public synchronized void resumeOrPlay()
+ {
+ MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer() {
+ @Override
+ public void accept(MediaPlayerService mediaPlayerService) {
+ mediaPlayerService.resumeOrPlay();
+ }
+ });
+ }
+
@Override
public synchronized void togglePlayPause()
{
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java
index 7a53cbe0..ef7c18d8 100644
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java
+++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java
@@ -81,17 +81,6 @@ public class MediaPlayerLifecycleSupport
// React to media buttons.
Util.registerMediaButtonEventReceiver(context, true);
- // Register the handler for outside intents.
- IntentFilter commandFilter = new IntentFilter();
- commandFilter.addAction(Constants.CMD_PLAY);
- commandFilter.addAction(Constants.CMD_TOGGLEPAUSE);
- commandFilter.addAction(Constants.CMD_PAUSE);
- commandFilter.addAction(Constants.CMD_STOP);
- commandFilter.addAction(Constants.CMD_PREVIOUS);
- commandFilter.addAction(Constants.CMD_NEXT);
- commandFilter.addAction(Constants.CMD_PROCESS_KEYCODE);
- context.registerReceiver(intentReceiver, commandFilter);
-
mediaPlayerController.onCreate();
if (autoPlay) mediaPlayerController.preload();
@@ -120,7 +109,6 @@ public class MediaPlayerLifecycleSupport
downloader.getCurrentPlayingIndex(), mediaPlayerController.getPlayerPosition());
mediaPlayerController.clear(false);
context.unregisterReceiver(headsetEventReceiver);
- context.unregisterReceiver(intentReceiver);
mediaPlayerController.onDestroy();
created = false;
Log.i(TAG, "LifecycleSupport destroyed");
@@ -128,19 +116,33 @@ public class MediaPlayerLifecycleSupport
public void receiveIntent(Intent intent)
{
- Log.i(TAG, "Received intent");
- if (intent != null && intent.getExtras() != null)
- {
- KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
- if (event != null)
- {
- handleKeyEvent(event);
+ if (intent == null) return;
+ String intentAction = intent.getAction();
+ if (intentAction == null || intentAction.isEmpty()) return;
+
+ Log.i(TAG, String.format("Received intent: %s", intentAction));
+
+ if (intentAction.equals(Constants.CMD_PROCESS_KEYCODE)) {
+ if (intent.getExtras() != null) {
+ KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
+ if (event != null) {
+ handleKeyEvent(event);
+ }
}
}
+ else
+ {
+ handleUltrasonicIntent(intentAction);
+ }
}
+ /**
+ * The Headset Intent Receiver is responsible for resuming playback when a headset is inserted
+ * and pausing it when it is removed.
+ * Unfortunately this Intent can't be registered in the AndroidManifest, so it works only
+ * while Ultrasonic is running.
+ */
private void registerHeadsetReceiver() {
- // Pause when headset is unplugged.
final SharedPreferences sp = Util.getPreferences(context);
final String spKey = context
.getString(R.string.settings_playback_resume_play_on_headphones_plug);
@@ -255,43 +257,53 @@ public class MediaPlayerLifecycleSupport
}
/**
- * This receiver manages the intent that could come from other applications.
+ * This function processes the intent that could come from other applications.
*/
- private BroadcastReceiver intentReceiver = new BroadcastReceiver()
+ private void handleUltrasonicIntent(final String intentAction)
{
- @Override
- public void onReceive(Context context, Intent intent)
- {
- String action = intent.getAction();
- if (action == null) return;
- Log.i(TAG, "intentReceiver.onReceive: " + action);
+ final boolean isRunning = created;
+ // If Ultrasonic is not running, do nothing to stop or pause
+ if (!isRunning && (intentAction.equals(Constants.CMD_PAUSE) ||
+ intentAction.equals(Constants.CMD_STOP))) return;
- switch(action)
- {
- case Constants.CMD_PLAY:
- mediaPlayerController.play();
- break;
- case Constants.CMD_NEXT:
- mediaPlayerController.next();
- break;
- case Constants.CMD_PREVIOUS:
- mediaPlayerController.previous();
- break;
- case Constants.CMD_TOGGLEPAUSE:
- mediaPlayerController.togglePlayPause();
- break;
- case Constants.CMD_STOP:
- // TODO: There is a stop() function, shouldn't we use that?
- mediaPlayerController.pause();
- mediaPlayerController.seekTo(0);
- break;
- case Constants.CMD_PAUSE:
- mediaPlayerController.pause();
- break;
- case Constants.CMD_PROCESS_KEYCODE:
- receiveIntent(intent);
- break;
+ boolean autoStart = (intentAction.equals(Constants.CMD_PLAY) ||
+ intentAction.equals(Constants.CMD_RESUME_OR_PLAY) ||
+ intentAction.equals(Constants.CMD_TOGGLEPAUSE) ||
+ intentAction.equals(Constants.CMD_PREVIOUS) ||
+ intentAction.equals(Constants.CMD_NEXT));
+
+ // We can receive intents when everything is stopped, so we need to start
+ onCreate(autoStart, new Runnable() {
+ @Override
+ public void run() {
+ switch(intentAction)
+ {
+ case Constants.CMD_PLAY:
+ mediaPlayerController.play();
+ break;
+ case Constants.CMD_RESUME_OR_PLAY:
+ // If Ultrasonic wasn't running, the autoStart is enough to resume, no need to call anything
+ if (isRunning) mediaPlayerController.resumeOrPlay();
+ break;
+ case Constants.CMD_NEXT:
+ mediaPlayerController.next();
+ break;
+ case Constants.CMD_PREVIOUS:
+ mediaPlayerController.previous();
+ break;
+ case Constants.CMD_TOGGLEPAUSE:
+ mediaPlayerController.togglePlayPause();
+ break;
+ case Constants.CMD_STOP:
+ // TODO: There is a stop() function, shouldn't we use that?
+ mediaPlayerController.pause();
+ mediaPlayerController.seekTo(0);
+ break;
+ case Constants.CMD_PAUSE:
+ mediaPlayerController.pause();
+ break;
+ }
}
- }
- };
+ });
+ }
}
\ No newline at end of file
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java
index 3fc6de35..5b64ddc6 100644
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java
+++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java
@@ -361,6 +361,18 @@ public class MediaPlayerService extends Service
}
}
+ public synchronized void resumeOrPlay()
+ {
+ if (localMediaPlayer.playerState == PAUSED || localMediaPlayer.playerState == COMPLETED || localMediaPlayer.playerState == STOPPED)
+ {
+ start();
+ }
+ else if (localMediaPlayer.playerState == IDLE)
+ {
+ play();
+ }
+ }
+
/**
* Plays either the current song (resume) or the first/next one in queue.
*/
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java
index 3b330ec3..07355b94 100644
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java
+++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java
@@ -63,6 +63,7 @@ public final class Constants
// Names for Intent Actions
public static final String CMD_PROCESS_KEYCODE = "org.moire.ultrasonic.CMD_PROCESS_KEYCODE";
public static final String CMD_PLAY = "org.moire.ultrasonic.CMD_PLAY";
+ public static final String CMD_RESUME_OR_PLAY = "org.moire.ultrasonic.CMD_RESUME_OR_PLAY";
public static final String CMD_TOGGLEPAUSE = "org.moire.ultrasonic.CMD_TOGGLEPAUSE";
public static final String CMD_PAUSE = "org.moire.ultrasonic.CMD_PAUSE";
public static final String CMD_STOP = "org.moire.ultrasonic.CMD_STOP";