Fixed handling Bluetooth intents while Ultrasonic isn't running
This commit is contained in:
parent
c805005b02
commit
75a9c60889
|
@ -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"/>
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
}
|
||||||
}
|
}
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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";
|
||||||
|
|
Loading…
Reference in New Issue