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:label="Ultrasonic Download Service"
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>
<receiver android:name=".receiver.MediaButtonIntentReceiver">
@ -141,6 +133,17 @@
<action android:name="android.intent.action.MEDIA_BUTTON"/>
</intent-filter>
</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">
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED"/>

View File

@ -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()));
}
}
}

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()
{
executorService.shutdown();
if (executorService != null) executorService.shutdown();
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
public synchronized void togglePlayPause()
{

View File

@ -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;
}
}
}
};
});
}
}

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.
*/

View File

@ -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";