Merge pull request #447 from tzugen/rogue-session

Get rid of rogue session
This commit is contained in:
Nite 2021-05-05 09:40:09 +02:00 committed by GitHub
commit e75137372b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 85 additions and 100 deletions

View File

@ -492,13 +492,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
} }
private void setMediaButtonsEnabled(boolean enabled) { private void setMediaButtonsEnabled(boolean enabled) {
if (enabled) { lockScreenEnabled.setEnabled(enabled);
lockScreenEnabled.setEnabled(true); Util.updateMediaButtonEventReceiver();
Util.registerMediaButtonEventReceiver(getActivity(), false);
} else {
lockScreenEnabled.setEnabled(false);
Util.unregisterMediaButtonEventReceiver(getActivity(), false);
}
} }
private void setBluetoothPreferences(boolean enabled) { private void setBluetoothPreferences(boolean enabled) {

View File

@ -29,7 +29,7 @@ import org.moire.ultrasonic.util.Constants;
import org.moire.ultrasonic.util.Util; import org.moire.ultrasonic.util.Util;
/** /**
* Request media button focus when connected to Bluetooth A2DP. * Resume or pause playback on Bluetooth A2DP connect/disconnect.
* *
* @author Sindre Mehus * @author Sindre Mehus
*/ */
@ -63,7 +63,6 @@ public class BluetoothIntentReceiver extends BroadcastReceiver
if (state == android.bluetooth.BluetoothA2dp.STATE_CONNECTED) actionA2dpConnected = true; if (state == android.bluetooth.BluetoothA2dp.STATE_CONNECTED) actionA2dpConnected = true;
else if (state == android.bluetooth.BluetoothA2dp.STATE_DISCONNECTED) actionA2dpDisconnected = true; else if (state == android.bluetooth.BluetoothA2dp.STATE_DISCONNECTED) actionA2dpDisconnected = true;
boolean connected = actionA2dpConnected || actionBluetoothDeviceConnected;
boolean resume = false; boolean resume = false;
boolean pause = false; boolean pause = false;
@ -83,12 +82,6 @@ public class BluetoothIntentReceiver extends BroadcastReceiver
break; break;
} }
if (connected)
{
Timber.i("Connected to Bluetooth device %s address %s, requesting media button focus.", name, address);
Util.registerMediaButtonEventReceiver(context, false);
}
if (resume) if (resume)
{ {
Timber.i("Connected to Bluetooth device %s address %s, resuming playback.", name, address); Timber.i("Connected to Bluetooth device %s address %s, resuming playback.", name, address);

View File

@ -46,7 +46,7 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver
String intentAction = intent.getAction(); String intentAction = intent.getAction();
// If media button are turned off and we received a media button, exit // If media button are turned off and we received a media button, exit
if (!Util.getMediaButtonsPreference(context) && if (!Util.getMediaButtonsEnabled(context) &&
Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) return; Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) return;
// Only process media buttons and CMD_PROCESS_KEYCODE, which is received from the widgets // Only process media buttons and CMD_PROCESS_KEYCODE, which is received from the widgets

View File

@ -85,12 +85,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
public void onCreate() public void onCreate()
{ {
if (created) return; if (created) return;
this.externalStorageMonitor.onCreate(new Runnable() { this.externalStorageMonitor.onCreate(this::reset);
@Override
public void run() {
reset();
}
});
setJukeboxEnabled(activeServerProvider.getValue().getActiveServer().getJukeboxByDefault()); setJukeboxEnabled(activeServerProvider.getValue().getActiveServer().getJukeboxByDefault());
created = true; created = true;
@ -116,9 +111,8 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
if (currentPlayingIndex != -1) if (currentPlayingIndex != -1)
{ {
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() { MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) ->
@Override {
public void accept(MediaPlayerService mediaPlayerService) {
mediaPlayerService.play(currentPlayingIndex, autoPlayStart); mediaPlayerService.play(currentPlayingIndex, autoPlayStart);
if (localMediaPlayer.currentPlaying != null) if (localMediaPlayer.currentPlaying != null)
@ -136,8 +130,9 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
} }
} }
autoPlayStart = false; autoPlayStart = false;
} return null;
}); }
);
} }
} }
@ -149,55 +144,53 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
@Override @Override
public synchronized void play(final int index) public synchronized void play(final int index)
{ {
MediaPlayerService.executeOnStartedMediaPlayerService(context,new Consumer<MediaPlayerService>() { MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
@Override
public void accept(MediaPlayerService mediaPlayerService) {
mediaPlayerService.play(index, true); mediaPlayerService.play(index, true);
} return null;
}); }
);
} }
public synchronized void play() public synchronized void play()
{ {
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() { MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
@Override
public void accept(MediaPlayerService mediaPlayerService) {
mediaPlayerService.play(); mediaPlayerService.play();
} return null;
}); }
);
} }
public synchronized void resumeOrPlay() public synchronized void resumeOrPlay()
{ {
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() { MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
@Override
public void accept(MediaPlayerService mediaPlayerService) {
mediaPlayerService.resumeOrPlay(); mediaPlayerService.resumeOrPlay();
} return null;
}); }
);
} }
@Override @Override
public synchronized void togglePlayPause() public synchronized void togglePlayPause()
{ {
if (localMediaPlayer.playerState == PlayerState.IDLE) autoPlayStart = true; if (localMediaPlayer.playerState == PlayerState.IDLE) autoPlayStart = true;
MediaPlayerService.executeOnStartedMediaPlayerService(context,new Consumer<MediaPlayerService>() { MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
@Override
public void accept(MediaPlayerService mediaPlayerService) {
mediaPlayerService.togglePlayPause(); mediaPlayerService.togglePlayPause();
} return null;
}); }
);
} }
@Override @Override
public synchronized void start() public synchronized void start()
{ {
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() { MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
@Override
public void accept(MediaPlayerService mediaPlayerService) {
mediaPlayerService.start(); mediaPlayerService.start();
} return null;
}); }
);
} }
@Override @Override
@ -612,19 +605,14 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
final Entry song = localMediaPlayer.currentPlaying.getSong(); final Entry song = localMediaPlayer.currentPlaying.getSong();
song.setUserRating(rating); song.setUserRating(rating);
new Thread(new Runnable() new Thread(() -> {
{ try
@Override
public void run()
{ {
try MusicServiceFactory.getMusicService(context).setRating(song.getId(), rating, context);
{ }
MusicServiceFactory.getMusicService(context).setRating(song.getId(), rating, context); catch (Exception e)
} {
catch (Exception e) Timber.e(e);
{
Timber.e(e);
}
} }
}).start(); }).start();

View File

@ -76,9 +76,6 @@ public class MediaPlayerLifecycleSupport
registerHeadsetReceiver(); registerHeadsetReceiver();
// React to media buttons.
Util.registerMediaButtonEventReceiver(context, true);
mediaPlayerController.onCreate(); mediaPlayerController.onCreate();
if (autoPlay) mediaPlayerController.preload(); if (autoPlay) mediaPlayerController.preload();

View File

@ -31,7 +31,6 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
@ -53,8 +52,8 @@ import org.moire.ultrasonic.R;
import org.moire.ultrasonic.data.ActiveServerProvider; import org.moire.ultrasonic.data.ActiveServerProvider;
import org.moire.ultrasonic.domain.*; import org.moire.ultrasonic.domain.*;
import org.moire.ultrasonic.domain.MusicDirectory.Entry; import org.moire.ultrasonic.domain.MusicDirectory.Entry;
import org.moire.ultrasonic.receiver.MediaButtonIntentReceiver;
import org.moire.ultrasonic.service.DownloadFile; import org.moire.ultrasonic.service.DownloadFile;
import org.moire.ultrasonic.service.MediaPlayerService;
import java.io.*; import java.io.*;
import java.security.MessageDigest; import java.security.MessageDigest;
@ -678,31 +677,16 @@ public class Util
return Bitmap.createScaledBitmap(bitmap, size, getScaledHeight(bitmap, size), true); return Bitmap.createScaledBitmap(bitmap, size, getScaledHeight(bitmap, size), true);
} }
public static void registerMediaButtonEventReceiver(Context context, boolean isService) // Trigger an update on the MediaSession. Depending on the preference it will register
// or deregister the MediaButtonReceiver.
public static void updateMediaButtonEventReceiver()
{ {
if (getMediaButtonsPreference(context)) MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
{ if (mediaPlayerService != null) {
if (isService) mediaButtonsRegisteredForService = true; mediaPlayerService.updateMediaButtonReceiver();
else mediaButtonsRegisteredForUI = true;
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.registerMediaButtonEventReceiver(new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()));
} }
} }
public static void unregisterMediaButtonEventReceiver(Context context, boolean isService)
{
if (isService) mediaButtonsRegisteredForService = false;
else mediaButtonsRegisteredForUI = false;
// Do not unregister while there is an active part of the app which needs the control
if (mediaButtonsRegisteredForService || mediaButtonsRegisteredForUI) return;
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.unregisterMediaButtonEventReceiver(new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()));
Timber.i("MediaButtonEventReceiver unregistered.");
}
public static MusicDirectory getSongsFromSearchResult(SearchResult searchResult) public static MusicDirectory getSongsFromSearchResult(SearchResult searchResult)
{ {
MusicDirectory musicDirectory = new MusicDirectory(); MusicDirectory musicDirectory = new MusicDirectory();
@ -1055,7 +1039,7 @@ public class Util
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_INCREMENT_TIME, "5")); return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_INCREMENT_TIME, "5"));
} }
public static boolean getMediaButtonsPreference(Context context) public static boolean getMediaButtonsEnabled(Context context)
{ {
SharedPreferences preferences = getPreferences(context); SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_MEDIA_BUTTONS, true); return preferences.getBoolean(Constants.PREFERENCES_KEY_MEDIA_BUTTONS, true);

View File

@ -178,7 +178,7 @@ class NavigationActivity : AppCompatActivity() {
super.onResume() super.onResume()
setMenuForServerSetting() setMenuForServerSetting()
Util.registerMediaButtonEventReceiver(this, false)
// Lifecycle support's constructor registers some event receivers so it should be created early // Lifecycle support's constructor registers some event receivers so it should be created early
lifecycleSupport.onCreate() lifecycleSupport.onCreate()
@ -188,7 +188,6 @@ class NavigationActivity : AppCompatActivity() {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
Util.unregisterMediaButtonEventReceiver(this, false)
nowPlayingEventDistributor.unsubscribe(nowPlayingEventListener) nowPlayingEventDistributor.unsubscribe(nowPlayingEventListener)
themeChangedEventDistributor.unsubscribe(themeChangedEventListener) themeChangedEventDistributor.unsubscribe(themeChangedEventListener)
imageLoaderProvider.clearImageLoader() imageLoaderProvider.clearImageLoader()
@ -310,7 +309,6 @@ class NavigationActivity : AppCompatActivity() {
private fun exit() { private fun exit() {
lifecycleSupport.onDestroy() lifecycleSupport.onDestroy()
Util.unregisterMediaButtonEventReceiver(this, false)
finish() finish()
} }

View File

@ -119,7 +119,6 @@ class LocalMediaPlayer(
}.start() }.start()
wakeLock.setReferenceCounted(false) wakeLock.setReferenceCounted(false)
Util.registerMediaButtonEventReceiver(context, true)
Timber.i("LocalMediaPlayer created") Timber.i("LocalMediaPlayer created")
} }
@ -146,7 +145,7 @@ class LocalMediaPlayer(
if (nextPlayingTask != null) { if (nextPlayingTask != null) {
nextPlayingTask!!.cancel() nextPlayingTask!!.cancel()
} }
Util.unregisterMediaButtonEventReceiver(context, true)
wakeLock.release() wakeLock.release()
} catch (exception: Throwable) { } catch (exception: Throwable) {
Timber.w(exception, "LocalMediaPlayer onDestroy exception: ") Timber.w(exception, "LocalMediaPlayer onDestroy exception: ")

View File

@ -12,6 +12,7 @@ import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.app.Service import android.app.Service
import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
@ -22,7 +23,6 @@ import android.support.v4.media.session.PlaybackStateCompat
import android.view.KeyEvent import android.view.KeyEvent
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import java.util.ArrayList
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
import org.moire.ultrasonic.activity.NavigationActivity import org.moire.ultrasonic.activity.NavigationActivity
@ -33,6 +33,7 @@ import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X1
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X2 import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X2
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X3 import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X3
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X4 import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X4
import org.moire.ultrasonic.receiver.MediaButtonIntentReceiver
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.FileUtil import org.moire.ultrasonic.util.FileUtil
@ -792,7 +793,8 @@ class MediaPlayerService : Service() {
mediaSession = MediaSessionCompat(applicationContext, "UltrasonicService") mediaSession = MediaSessionCompat(applicationContext, "UltrasonicService")
mediaSessionToken = mediaSession!!.sessionToken mediaSessionToken = mediaSession!!.sessionToken
// mediaController = new MediaControllerCompat(getApplicationContext(), mediaSessionToken);
updateMediaButtonReceiver()
mediaSession!!.setCallback(object : MediaSessionCompat.Callback() { mediaSession!!.setCallback(object : MediaSessionCompat.Callback() {
override fun onPlay() { override fun onPlay() {
@ -838,10 +840,39 @@ class MediaPlayerService : Service() {
) )
} }
fun updateMediaButtonReceiver() {
if (Util.getMediaButtonsEnabled(applicationContext)) {
registerMediaButtonEventReceiver()
} else {
unregisterMediaButtonEventReceiver()
}
}
fun registerMediaButtonEventReceiver() {
val component = ComponentName(packageName, MediaButtonIntentReceiver::class.java.name)
val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
mediaButtonIntent.component = component
val pendingIntent = PendingIntent.getBroadcast(
this,
INTENT_CODE_MEDIA_BUTTON,
mediaButtonIntent,
PendingIntent.FLAG_CANCEL_CURRENT
)
mediaSession?.setMediaButtonReceiver(pendingIntent)
}
fun unregisterMediaButtonEventReceiver() {
mediaSession?.setMediaButtonReceiver(null)
}
companion object { companion object {
private const val NOTIFICATION_CHANNEL_ID = "org.moire.ultrasonic" private const val NOTIFICATION_CHANNEL_ID = "org.moire.ultrasonic"
private const val NOTIFICATION_CHANNEL_NAME = "Ultrasonic background service" private const val NOTIFICATION_CHANNEL_NAME = "Ultrasonic background service"
private const val NOTIFICATION_ID = 3033 private const val NOTIFICATION_ID = 3033
private const val INTENT_CODE_MEDIA_BUTTON = 161
private var instance: MediaPlayerService? = null private var instance: MediaPlayerService? = null
private val instanceLock = Any() private val instanceLock = Any()
@ -872,7 +903,7 @@ class MediaPlayerService : Service() {
@JvmStatic @JvmStatic
fun executeOnStartedMediaPlayerService( fun executeOnStartedMediaPlayerService(
context: Context, context: Context,
taskToExecute: Consumer<MediaPlayerService?> taskToExecute: (MediaPlayerService?) -> Unit
) { ) {
val t: Thread = object : Thread() { val t: Thread = object : Thread() {
@ -882,7 +913,7 @@ class MediaPlayerService : Service() {
Timber.e("ExecuteOnStarted.. failed to get a MediaPlayerService instance!") Timber.e("ExecuteOnStarted.. failed to get a MediaPlayerService instance!")
return return
} }
taskToExecute.accept(instance) taskToExecute(instance)
} }
} }
t.start() t.start()