Fixed handling Bluetooth intents while Ultrasonic isn't running

This commit is contained in:
Nite 2020-09-29 11:09:24 +02:00
parent c805005b02
commit 75a9c60889
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
8 changed files with 143 additions and 66 deletions

View File

@ -126,14 +126,6 @@
android:name=".service.MediaPlayerService" android:name=".service.MediaPlayerService"
android:label="Ultrasonic Download Service" android:label="Ultrasonic Download Service"
android:exported="false"> android:exported="false">
<intent-filter>
<action android:name="org.moire.ultrasonic.CMD_TOGGLEPAUSE"/>
<action android:name="org.moire.ultrasonic.CMD_PLAY"/>
<action android:name="org.moire.ultrasonic.CMD_PAUSE"/>
<action android:name="org.moire.ultrasonic.CMD_NEXT"/>
<action android:name="org.moire.ultrasonic.CMD_PREVIOUS"/>
<action android:name="org.moire.ultrasonic.CMD_STOP"/>
</intent-filter>
</service> </service>
<receiver android:name=".receiver.MediaButtonIntentReceiver"> <receiver android:name=".receiver.MediaButtonIntentReceiver">
@ -141,6 +133,17 @@
<action android:name="android.intent.action.MEDIA_BUTTON"/> <action android:name="android.intent.action.MEDIA_BUTTON"/>
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receiver.UltrasonicIntentReceiver">
<intent-filter>
<action android:name="org.moire.ultrasonic.CMD_TOGGLEPAUSE"/>
<action android:name="org.moire.ultrasonic.CMD_PLAY"/>
<action android:name="org.moire.ultrasonic.CMD_RESUME_OR_PLAY"/>
<action android:name="org.moire.ultrasonic.CMD_PAUSE"/>
<action android:name="org.moire.ultrasonic.CMD_NEXT"/>
<action android:name="org.moire.ultrasonic.CMD_PREVIOUS"/>
<action android:name="org.moire.ultrasonic.CMD_STOP"/>
</intent-filter>
</receiver>
<receiver android:name=".receiver.BluetoothIntentReceiver"> <receiver android:name=".receiver.BluetoothIntentReceiver">
<intent-filter> <intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED"/> <action android:name="android.bluetooth.device.action.ACL_CONNECTED"/>

View File

@ -94,13 +94,13 @@ public class BluetoothIntentReceiver extends BroadcastReceiver
if (resume) if (resume)
{ {
Log.i(TAG, String.format("Connected to Bluetooth device %s address %s, resuming playback.", name, address)); 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) if (pause)
{ {
Log.i(TAG, String.format("Disconnected from Bluetooth device %s address %s, requesting pause.", name, address)); 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()));
} }
} }
} }

View File

@ -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<MediaPlayerLifecycleSupport> 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.
}
}
}

View File

@ -89,7 +89,7 @@ public class Downloader
public void stop() public void stop()
{ {
executorService.shutdown(); if (executorService != null) executorService.shutdown();
Log.i(TAG, "Downloader stopped"); Log.i(TAG, "Downloader stopped");
} }

View File

@ -170,6 +170,16 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
}); });
} }
public synchronized void resumeOrPlay()
{
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
@Override
public void accept(MediaPlayerService mediaPlayerService) {
mediaPlayerService.resumeOrPlay();
}
});
}
@Override @Override
public synchronized void togglePlayPause() public synchronized void togglePlayPause()
{ {

View File

@ -81,17 +81,6 @@ public class MediaPlayerLifecycleSupport
// React to media buttons. // React to media buttons.
Util.registerMediaButtonEventReceiver(context, true); 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(); mediaPlayerController.onCreate();
if (autoPlay) mediaPlayerController.preload(); if (autoPlay) mediaPlayerController.preload();
@ -120,7 +109,6 @@ public class MediaPlayerLifecycleSupport
downloader.getCurrentPlayingIndex(), mediaPlayerController.getPlayerPosition()); downloader.getCurrentPlayingIndex(), mediaPlayerController.getPlayerPosition());
mediaPlayerController.clear(false); mediaPlayerController.clear(false);
context.unregisterReceiver(headsetEventReceiver); context.unregisterReceiver(headsetEventReceiver);
context.unregisterReceiver(intentReceiver);
mediaPlayerController.onDestroy(); mediaPlayerController.onDestroy();
created = false; created = false;
Log.i(TAG, "LifecycleSupport destroyed"); Log.i(TAG, "LifecycleSupport destroyed");
@ -128,19 +116,33 @@ public class MediaPlayerLifecycleSupport
public void receiveIntent(Intent intent) public void receiveIntent(Intent intent)
{ {
Log.i(TAG, "Received intent"); if (intent == null) return;
if (intent != null && intent.getExtras() != null) String intentAction = intent.getAction();
{ if (intentAction == null || intentAction.isEmpty()) return;
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
if (event != null) Log.i(TAG, String.format("Received intent: %s", intentAction));
{
handleKeyEvent(event); 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() { private void registerHeadsetReceiver() {
// Pause when headset is unplugged.
final SharedPreferences sp = Util.getPreferences(context); final SharedPreferences sp = Util.getPreferences(context);
final String spKey = context final String spKey = context
.getString(R.string.settings_playback_resume_play_on_headphones_plug); .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 final boolean isRunning = created;
public void onReceive(Context context, Intent intent) // If Ultrasonic is not running, do nothing to stop or pause
{ if (!isRunning && (intentAction.equals(Constants.CMD_PAUSE) ||
String action = intent.getAction(); intentAction.equals(Constants.CMD_STOP))) return;
if (action == null) return;
Log.i(TAG, "intentReceiver.onReceive: " + action);
switch(action) boolean autoStart = (intentAction.equals(Constants.CMD_PLAY) ||
{ intentAction.equals(Constants.CMD_RESUME_OR_PLAY) ||
case Constants.CMD_PLAY: intentAction.equals(Constants.CMD_TOGGLEPAUSE) ||
mediaPlayerController.play(); intentAction.equals(Constants.CMD_PREVIOUS) ||
break; intentAction.equals(Constants.CMD_NEXT));
case Constants.CMD_NEXT:
mediaPlayerController.next(); // We can receive intents when everything is stopped, so we need to start
break; onCreate(autoStart, new Runnable() {
case Constants.CMD_PREVIOUS: @Override
mediaPlayerController.previous(); public void run() {
break; switch(intentAction)
case Constants.CMD_TOGGLEPAUSE: {
mediaPlayerController.togglePlayPause(); case Constants.CMD_PLAY:
break; mediaPlayerController.play();
case Constants.CMD_STOP: break;
// TODO: There is a stop() function, shouldn't we use that? case Constants.CMD_RESUME_OR_PLAY:
mediaPlayerController.pause(); // If Ultrasonic wasn't running, the autoStart is enough to resume, no need to call anything
mediaPlayerController.seekTo(0); if (isRunning) mediaPlayerController.resumeOrPlay();
break; break;
case Constants.CMD_PAUSE: case Constants.CMD_NEXT:
mediaPlayerController.pause(); mediaPlayerController.next();
break; break;
case Constants.CMD_PROCESS_KEYCODE: case Constants.CMD_PREVIOUS:
receiveIntent(intent); mediaPlayerController.previous();
break; 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;
}
} }
} });
}; }
} }

View File

@ -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. * Plays either the current song (resume) or the first/next one in queue.
*/ */

View File

@ -63,6 +63,7 @@ public final class Constants
// Names for Intent Actions // Names for Intent Actions
public static final String CMD_PROCESS_KEYCODE = "org.moire.ultrasonic.CMD_PROCESS_KEYCODE"; 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_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_TOGGLEPAUSE = "org.moire.ultrasonic.CMD_TOGGLEPAUSE";
public static final String CMD_PAUSE = "org.moire.ultrasonic.CMD_PAUSE"; public static final String CMD_PAUSE = "org.moire.ultrasonic.CMD_PAUSE";
public static final String CMD_STOP = "org.moire.ultrasonic.CMD_STOP"; public static final String CMD_STOP = "org.moire.ultrasonic.CMD_STOP";