From 046916221d1e78160b4036dee7e1d1f94647e16c Mon Sep 17 00:00:00 2001 From: Nite Date: Fri, 25 Sep 2020 19:03:53 +0200 Subject: [PATCH 1/5] Started implementing Bluetooth connection settings --- .../ultrasonic/fragment/SettingsFragment.java | 16 ++++++++++++++++ .../ultrasonic/receiver/A2dpIntentReceiver.java | 11 ++--------- .../receiver/BluetoothIntentReceiver.java | 10 +++++----- .../org/moire/ultrasonic/util/Constants.java | 6 ++++++ ultrasonic/src/main/res/values/strings.xml | 7 ++++++- ultrasonic/src/main/res/xml/settings.xml | 6 ++++++ 6 files changed, 41 insertions(+), 15 deletions(-) diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java index c5179d6b..c89575f5 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java @@ -64,6 +64,8 @@ public class SettingsFragment extends PreferenceFragment private EditTextPreference sharingDefaultGreeting; private TimeSpanPreference sharingDefaultExpiration; private PreferenceCategory serversCategory; + private Preference resumeOnBluetoothDevice; + private Preference pauseOnBluetoothDevice; private SharedPreferences settings; @@ -110,6 +112,8 @@ public class SettingsFragment extends PreferenceFragment sharingDefaultGreeting = (EditTextPreference) findPreference(Constants.PREFERENCES_KEY_DEFAULT_SHARE_GREETING); sharingDefaultExpiration = (TimeSpanPreference) findPreference(Constants.PREFERENCES_KEY_DEFAULT_SHARE_EXPIRATION); serversCategory = (PreferenceCategory) findPreference(Constants.PREFERENCES_KEY_SERVERS_KEY); + resumeOnBluetoothDevice = findPreference(Constants.PREFERENCES_KEY_RESUME_ON_BLUETOOTH_DEVICE); + pauseOnBluetoothDevice = findPreference(Constants.PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE); sharingDefaultGreeting.setText(Util.getShareGreeting(getActivity())); setupClearSearchPreference(); @@ -199,6 +203,18 @@ public class SettingsFragment extends PreferenceFragment }); } + private void setupBluetoothDevicePreferences() { + resumeOnBluetoothDevice.setSummary(settings.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, + FileUtil.getDefaultMusicDirectory(getActivity()).getPath())); + + resumeOnBluetoothDevice.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + return true; + } + }); + } + private void setupClearSearchPreference() { Preference clearSearchPreference = findPreference(Constants.PREFERENCES_KEY_CLEAR_SEARCH_HISTORY); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java index 52274108..1479f57b 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java @@ -19,17 +19,10 @@ public class A2dpIntentReceiver extends BroadcastReceiver @Override public void onReceive(Context context, Intent intent) { - if (mediaPlayerControllerLazy.getValue().getCurrentPlaying() == null) - { - return; - } + if (mediaPlayerControllerLazy.getValue().getCurrentPlaying() == null) return; Entry song = mediaPlayerControllerLazy.getValue().getCurrentPlaying().getSong(); - - if (song == null) - { - return; - } + if (song == null) return; Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE); 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 fa1c61c4..abee751e 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java @@ -34,7 +34,6 @@ import org.moire.ultrasonic.util.Util; */ public class BluetoothIntentReceiver extends BroadcastReceiver { - private static final String TAG = BluetoothIntentReceiver.class.getSimpleName(); @Override @@ -43,9 +42,10 @@ public class BluetoothIntentReceiver extends BroadcastReceiver int state = intent.getIntExtra("android.bluetooth.a2dp.extra.SINK_STATE", -1); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String action = intent.getAction(); - String name = device != null ? device.getName() : "None"; + String name = device != null ? device.getName() : "Unknown"; + String address = device != null ? device.getAddress() : "Unknown"; - Log.d(TAG, String.format("Sink State: %d; Action: %s; Device: %s", state, action, name)); + Log.d(TAG, String.format("Sink State: %d; Action: %s; Device: %s; Address: %s", state, action, name, address)); boolean actionConnected = false; boolean actionDisconnected = false; @@ -64,13 +64,13 @@ public class BluetoothIntentReceiver extends BroadcastReceiver if (connected) { - Log.i(TAG, "Connected to Bluetooth device, requesting media button focus."); + Log.i(TAG, String.format("Connected to Bluetooth device %s address %s, requesting media button focus.", name, address)); Util.registerMediaButtonEventReceiver(context, false); } if (disconnected) { - Log.i(TAG, "Disconnected from Bluetooth device, requesting pause."); + Log.i(TAG, String.format("Disconnected from Bluetooth device %s address %s, requesting pause.", name, address)); context.sendBroadcast(new Intent(Constants.CMD_PAUSE)); } } 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 4008f7b5..792d33ab 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java @@ -131,6 +131,12 @@ public final class Constants public static final String PREFERENCES_KEY_USE_FIVE_STAR_RATING = "use_five_star_rating"; public static final String PREFERENCES_KEY_CATEGORY_NOTIFICATIONS = "notificationsCategory"; public static final String PREFERENCES_KEY_FIRST_RUN_EXECUTED = "firstRunExecuted"; + public static final String PREFERENCES_KEY_RESUME_ON_BLUETOOTH_DEVICE = "resumeOnBluetoothDevice"; + public static final String PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE = "pauseOnBluetoothDevice"; + + public static final String PREFERENCE_VALUE_ALL = "all"; + public static final String PREFERENCE_VALUE_A2DP = "a2dp"; + public static final String PREFERENCE_VALUE_DISABLED = "disabled"; // Number of free trial days for non-licensed servers. public static final int FREE_TRIAL_DAYS = 30; diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index a44798b3..f01e8e34 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -254,7 +254,7 @@ 5 songs Unlimited Resume on headphones insertion - App will resume paused playback on headphones insertion into device. + App will resume paused playback on wired headphones insertion into device. Keeping the screen on while downloading improves download speed. Keep Screen On Remember to set up your Last.fm user and password on the Subsonic server @@ -400,6 +400,11 @@ albumArt Multiple Years http://example.com + Resume when a bluetooth device is connected + Pause when a bluetooth device is disconnected + All bluetooth devices + Only A2dp devices + Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. Warning diff --git a/ultrasonic/src/main/res/xml/settings.xml b/ultrasonic/src/main/res/xml/settings.xml index 3baa16ac..51d61dfb 100644 --- a/ultrasonic/src/main/res/xml/settings.xml +++ b/ultrasonic/src/main/res/xml/settings.xml @@ -106,6 +106,12 @@ a:title="@string/settings.playback.resume_play_on_headphones_plug.title" a:summary="@string/settings.playback.resume_play_on_headphones_plug.summary" /> + + Date: Mon, 28 Sep 2020 17:12:36 +0200 Subject: [PATCH 2/5] Added resume and pause settings for bluetooth device connection / disconnection --- ultrasonic/src/main/AndroidManifest.xml | 2 +- .../ultrasonic/fragment/SettingsFragment.java | 81 ++++++++++++++++++- .../receiver/BluetoothIntentReceiver.java | 47 ++++++++--- .../org/moire/ultrasonic/util/Constants.java | 6 +- .../java/org/moire/ultrasonic/util/Util.java | 12 +++ ultrasonic/src/main/res/values-de/strings.xml | 6 ++ ultrasonic/src/main/res/values-es/strings.xml | 6 ++ ultrasonic/src/main/res/values-fr/strings.xml | 6 ++ ultrasonic/src/main/res/values-hu/strings.xml | 10 ++- ultrasonic/src/main/res/values-nl/strings.xml | 6 ++ ultrasonic/src/main/res/values-pl/strings.xml | 6 ++ .../src/main/res/values-pt-rBR/strings.xml | 6 ++ ultrasonic/src/main/res/values-pt/strings.xml | 6 ++ ultrasonic/src/main/res/values/arrays.xml | 5 ++ ultrasonic/src/main/res/values/strings.xml | 6 +- 15 files changed, 190 insertions(+), 21 deletions(-) diff --git a/ultrasonic/src/main/AndroidManifest.xml b/ultrasonic/src/main/AndroidManifest.xml index 5c9a7d61..4957fe6d 100644 --- a/ultrasonic/src/main/AndroidManifest.xml +++ b/ultrasonic/src/main/AndroidManifest.xml @@ -146,7 +146,7 @@ - + = Build.VERSION_CODES.O) { @@ -204,15 +210,84 @@ public class SettingsFragment extends PreferenceFragment } private void setupBluetoothDevicePreferences() { - resumeOnBluetoothDevice.setSummary(settings.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, - FileUtil.getDefaultMusicDirectory(getActivity()).getPath())); + final int resumeSetting = Util.getResumeOnBluetoothDevice(getActivity()); + final int pauseSetting = Util.getPauseOnBluetoothDevice(getActivity()); + + resumeOnBluetoothDevice.setSummary(bluetoothDevicePreferenceToString(resumeSetting)); + pauseOnBluetoothDevice.setSummary(bluetoothDevicePreferenceToString(pauseSetting)); resumeOnBluetoothDevice.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - return true; + showBluetoothDevicePreferenceDialog( + R.string.settings_playback_resume_on_bluetooth_device, + Util.getResumeOnBluetoothDevice(getActivity()), + new Consumer() { + @Override + public void accept(Integer choice) { + SharedPreferences.Editor editor = resumeOnBluetoothDevice.getEditor(); + editor.putInt(Constants.PREFERENCES_KEY_RESUME_ON_BLUETOOTH_DEVICE, choice); + editor.commit(); + resumeOnBluetoothDevice.setSummary(bluetoothDevicePreferenceToString(choice)); + } + }); + return true; } }); + + pauseOnBluetoothDevice.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + showBluetoothDevicePreferenceDialog( + R.string.settings_playback_pause_on_bluetooth_device, + Util.getPauseOnBluetoothDevice(getActivity()), + new Consumer() { + @Override + public void accept(Integer choice) { + SharedPreferences.Editor editor = pauseOnBluetoothDevice.getEditor(); + editor.putInt(Constants.PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE, choice); + editor.commit(); + pauseOnBluetoothDevice.setSummary(bluetoothDevicePreferenceToString(choice)); + } + }); + return true; + } + }); + } + + private void showBluetoothDevicePreferenceDialog(@StringRes int title, int defaultChoice, final Consumer onChosen) { + final int[] choice = {defaultChoice}; + new AlertDialog.Builder(getActivity()).setTitle(title) + .setSingleChoiceItems(R.array.bluetoothDeviceSettingNames, defaultChoice, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + choice[0] = i; + } + }) + .setNegativeButton(R.string.common_cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.cancel(); + } + }) + .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + onChosen.accept(choice[0]); + dialogInterface.dismiss(); + } + }) + .create().show(); + } + + private String bluetoothDevicePreferenceToString(int preferenceValue) { + switch (preferenceValue) { + case Constants.PREFERENCE_VALUE_ALL: return getString(R.string.settings_playback_bluetooth_all); + case Constants.PREFERENCE_VALUE_A2DP: return getString(R.string.settings_playback_bluetooth_a2dp); + case Constants.PREFERENCE_VALUE_DISABLED: return getString(R.string.settings_playback_bluetooth_disabled); + default: return ""; + } } private void setupClearSearchPreference() { 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 abee751e..5c70c13c 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/BluetoothIntentReceiver.java @@ -19,6 +19,7 @@ package org.moire.ultrasonic.receiver; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -39,28 +40,50 @@ public class BluetoothIntentReceiver extends BroadcastReceiver @Override public void onReceive(Context context, Intent intent) { - int state = intent.getIntExtra("android.bluetooth.a2dp.extra.SINK_STATE", -1); + int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String action = intent.getAction(); String name = device != null ? device.getName() : "Unknown"; String address = device != null ? device.getAddress() : "Unknown"; - Log.d(TAG, String.format("Sink State: %d; Action: %s; Device: %s; Address: %s", state, action, name, address)); + Log.d(TAG, String.format("A2DP State: %d; Action: %s; Device: %s; Address: %s", state, action, name, address)); - boolean actionConnected = false; - boolean actionDisconnected = false; + boolean actionBluetoothDeviceConnected = false; + boolean actionBluetoothDeviceDisconnected = false; + boolean actionA2dpConnected = false; + boolean actionA2dpDisconnected = false; if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { - actionConnected = true; + actionBluetoothDeviceConnected = true; } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) || BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) { - actionDisconnected = true; + actionBluetoothDeviceDisconnected = true; } - boolean connected = state == android.bluetooth.BluetoothA2dp.STATE_CONNECTED || actionConnected; - boolean disconnected = state == android.bluetooth.BluetoothA2dp.STATE_DISCONNECTED || actionDisconnected; + if (state == android.bluetooth.BluetoothA2dp.STATE_CONNECTED) actionA2dpConnected = true; + else if (state == android.bluetooth.BluetoothA2dp.STATE_DISCONNECTED) actionA2dpDisconnected = true; + + boolean connected = actionA2dpConnected || actionBluetoothDeviceConnected; + boolean resume = false; + boolean pause = false; + + switch (Util.getResumeOnBluetoothDevice(context)) + { + case Constants.PREFERENCE_VALUE_ALL: resume = actionA2dpConnected || actionBluetoothDeviceConnected; + break; + case Constants.PREFERENCE_VALUE_A2DP: resume = actionA2dpConnected; + break; + } + + switch (Util.getPauseOnBluetoothDevice(context)) + { + case Constants.PREFERENCE_VALUE_ALL: pause = actionA2dpDisconnected || actionBluetoothDeviceDisconnected; + break; + case Constants.PREFERENCE_VALUE_A2DP: pause = actionA2dpDisconnected; + break; + } if (connected) { @@ -68,7 +91,13 @@ public class BluetoothIntentReceiver extends BroadcastReceiver Util.registerMediaButtonEventReceiver(context, false); } - if (disconnected) + 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)); + } + + 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)); 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 792d33ab..3b330ec3 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java @@ -134,9 +134,9 @@ public final class Constants public static final String PREFERENCES_KEY_RESUME_ON_BLUETOOTH_DEVICE = "resumeOnBluetoothDevice"; public static final String PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE = "pauseOnBluetoothDevice"; - public static final String PREFERENCE_VALUE_ALL = "all"; - public static final String PREFERENCE_VALUE_A2DP = "a2dp"; - public static final String PREFERENCE_VALUE_DISABLED = "disabled"; + public static final int PREFERENCE_VALUE_ALL = 0; + public static final int PREFERENCE_VALUE_A2DP = 1; + public static final int PREFERENCE_VALUE_DISABLED = 2; // Number of free trial days for non-licensed servers. public static final int FREE_TRIAL_DAYS = 30; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java index c6c1525d..50a3d6bc 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java @@ -1447,4 +1447,16 @@ public class Util editor.apply(); return true; } + + public static int getResumeOnBluetoothDevice(Context context) + { + SharedPreferences preferences = getPreferences(context); + return preferences.getInt(Constants.PREFERENCES_KEY_RESUME_ON_BLUETOOTH_DEVICE, Constants.PREFERENCE_VALUE_DISABLED); + } + + public static int getPauseOnBluetoothDevice(Context context) + { + SharedPreferences preferences = getPreferences(context); + return preferences.getInt(Constants.PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE, Constants.PREFERENCE_VALUE_A2DP); + } } diff --git a/ultrasonic/src/main/res/values-de/strings.xml b/ultrasonic/src/main/res/values-de/strings.xml index fa71dfd4..caf340dc 100644 --- a/ultrasonic/src/main/res/values-de/strings.xml +++ b/ultrasonic/src/main/res/values-de/strings.xml @@ -396,6 +396,12 @@ 12 Album Cover Mehrere Jahre + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices + Only A2dp devices + Disabled + Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. Warning Ultrasonic needs read/write permission to the music cache directory. Cache directory was reset to its default value. diff --git a/ultrasonic/src/main/res/values-es/strings.xml b/ultrasonic/src/main/res/values-es/strings.xml index 6b001c61..68ed5111 100644 --- a/ultrasonic/src/main/res/values-es/strings.xml +++ b/ultrasonic/src/main/res/values-es/strings.xml @@ -397,6 +397,12 @@ 12 Caratula del Álbum Múltiples años + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices + Only A2dp devices + Disabled + Ultrasonic no puede acceder a la caché de los ficheros de música. La ubicación de la caché se restableció a la ruta predeterminada. Atención Ultrasonic necesita permiso de lectura / escritura para el directorio caché de música. El directorio caché se restableció a su valor predeterminado. diff --git a/ultrasonic/src/main/res/values-fr/strings.xml b/ultrasonic/src/main/res/values-fr/strings.xml index 0d9f6962..fdfc39e5 100644 --- a/ultrasonic/src/main/res/values-fr/strings.xml +++ b/ultrasonic/src/main/res/values-fr/strings.xml @@ -397,6 +397,12 @@ 12 albumArt Multiple Years + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices + Only A2dp devices + Disabled + Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. Warning Ultrasonic needs read/write permission to the music cache directory. Cache directory was reset to its default value. diff --git a/ultrasonic/src/main/res/values-hu/strings.xml b/ultrasonic/src/main/res/values-hu/strings.xml index 8147adaa..cfe49083 100644 --- a/ultrasonic/src/main/res/values-hu/strings.xml +++ b/ultrasonic/src/main/res/values-hu/strings.xml @@ -229,7 +229,7 @@ Korlátlan Max. bitráta - Wi-Fi kapcsolat Dalok max. találati száma - Telefon irányítása a bluetooth eszköz, vagy a fülhallgató vezérlőgombjaival. + Telefon irányítása a Bluetooth eszköz, vagy a fülhallgató vezérlőgombjaival. Média vezérlőgombok Hálózati időtúllépés 105 másodperc @@ -396,7 +396,13 @@ 11 12 albumArt - Multiple Years + Több év + Folytatás Bluetooth eszköz csatlakozásakor + Szünet Bluetooth eszköz kikapcsolásakor + Minden Bluetooth eszköz + Csak A2dp eszközök + Kikapcsolva + Az Ultrasonic nem éri el a zenei fájl gyorsítótárat. A gyorsítótár helye visszaállítva az alapbeállításra. Figyelem Az Ultrasonic működéséhez írás/olvasás hozzáférés szükséges a zenei fájl gyorsítótárhoz. A gyorsítótár helye visszaállítva az alapbeállításra. diff --git a/ultrasonic/src/main/res/values-nl/strings.xml b/ultrasonic/src/main/res/values-nl/strings.xml index e51f879b..97a43337 100644 --- a/ultrasonic/src/main/res/values-nl/strings.xml +++ b/ultrasonic/src/main/res/values-nl/strings.xml @@ -397,6 +397,12 @@ 12 Albumhoes Meerdere jaren + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices + Only A2dp devices + Disabled + Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. Warning Ultrasonic needs read/write permission to the music cache directory. Cache directory was reset to its default value. diff --git a/ultrasonic/src/main/res/values-pl/strings.xml b/ultrasonic/src/main/res/values-pl/strings.xml index 2b857769..2769dd48 100644 --- a/ultrasonic/src/main/res/values-pl/strings.xml +++ b/ultrasonic/src/main/res/values-pl/strings.xml @@ -397,6 +397,12 @@ ponieważ api Subsonic nie wspiera nowego sposobu autoryzacji dla użytkowników 12 Okładka Z różnych lat + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices + Only A2dp devices + Disabled + Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. Warning Ultrasonic needs read/write permission to the music cache directory. Cache directory was reset to its default value. diff --git a/ultrasonic/src/main/res/values-pt-rBR/strings.xml b/ultrasonic/src/main/res/values-pt-rBR/strings.xml index 61293cc1..92310141 100644 --- a/ultrasonic/src/main/res/values-pt-rBR/strings.xml +++ b/ultrasonic/src/main/res/values-pt-rBR/strings.xml @@ -397,6 +397,12 @@ 12 albumArt Múltiplos Anos + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices + Only A2dp devices + Disabled + Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. Warning Ultrasonic needs read/write permission to the music cache directory. Cache directory was reset to its default value. diff --git a/ultrasonic/src/main/res/values-pt/strings.xml b/ultrasonic/src/main/res/values-pt/strings.xml index 4ef98706..43574ee8 100644 --- a/ultrasonic/src/main/res/values-pt/strings.xml +++ b/ultrasonic/src/main/res/values-pt/strings.xml @@ -397,6 +397,12 @@ 12 albumArt Múltiplos Anos + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices + Only A2dp devices + Disabled + Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. Warning Ultrasonic needs read/write permission to the music cache directory. Cache directory was reset to its default value. diff --git a/ultrasonic/src/main/res/values/arrays.xml b/ultrasonic/src/main/res/values/arrays.xml index af24917f..fc178dea 100644 --- a/ultrasonic/src/main/res/values/arrays.xml +++ b/ultrasonic/src/main/res/values/arrays.xml @@ -291,5 +291,10 @@ 11 12 + + @string/settings.playback.bluetooth_all + @string/settings.playback.bluetooth_a2dp + @string/settings.playback.bluetooth_disabled + \ No newline at end of file diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index f01e8e34..6607b34c 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -400,9 +400,9 @@ albumArt Multiple Years http://example.com - Resume when a bluetooth device is connected - Pause when a bluetooth device is disconnected - All bluetooth devices + Resume when a Bluetooth device is connected + Pause when a Bluetooth device is disconnected + All Bluetooth devices Only A2dp devices Disabled From 75a9c60889c24fd5ecdfc1ed2ad8b8e759ca0904 Mon Sep 17 00:00:00 2001 From: Nite Date: Tue, 29 Sep 2020 11:09:24 +0200 Subject: [PATCH 3/5] Fixed handling Bluetooth intents while Ultrasonic isn't running --- ultrasonic/src/main/AndroidManifest.xml | 19 +-- .../receiver/BluetoothIntentReceiver.java | 4 +- .../receiver/UltrasonicIntentReceiver.java | 39 ++++++ .../moire/ultrasonic/service/Downloader.java | 2 +- .../service/MediaPlayerControllerImpl.java | 10 ++ .../service/MediaPlayerLifecycleSupport.java | 122 ++++++++++-------- .../service/MediaPlayerService.java | 12 ++ .../org/moire/ultrasonic/util/Constants.java | 1 + 8 files changed, 143 insertions(+), 66 deletions(-) create mode 100644 ultrasonic/src/main/java/org/moire/ultrasonic/receiver/UltrasonicIntentReceiver.java 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"; From f6e61b548403d0b1e9c4c505245d519e6990e137 Mon Sep 17 00:00:00 2001 From: Nite Date: Tue, 29 Sep 2020 13:58:15 +0200 Subject: [PATCH 4/5] Clarified strings for options --- ultrasonic/src/main/res/values-de/strings.xml | 2 +- ultrasonic/src/main/res/values-es/strings.xml | 10 +++++----- ultrasonic/src/main/res/values-fr/strings.xml | 2 +- ultrasonic/src/main/res/values-hu/strings.xml | 2 +- ultrasonic/src/main/res/values-nl/strings.xml | 2 +- ultrasonic/src/main/res/values-pl/strings.xml | 2 +- ultrasonic/src/main/res/values-pt-rBR/strings.xml | 2 +- ultrasonic/src/main/res/values-pt/strings.xml | 2 +- ultrasonic/src/main/res/values/strings.xml | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ultrasonic/src/main/res/values-de/strings.xml b/ultrasonic/src/main/res/values-de/strings.xml index caf340dc..a0575548 100644 --- a/ultrasonic/src/main/res/values-de/strings.xml +++ b/ultrasonic/src/main/res/values-de/strings.xml @@ -399,7 +399,7 @@ Resume when a Bluetooth device is connected Pause when a Bluetooth device is disconnected All Bluetooth devices - Only A2dp devices + Only audio (A2DP) devices Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. diff --git a/ultrasonic/src/main/res/values-es/strings.xml b/ultrasonic/src/main/res/values-es/strings.xml index 68ed5111..fa244ae8 100644 --- a/ultrasonic/src/main/res/values-es/strings.xml +++ b/ultrasonic/src/main/res/values-es/strings.xml @@ -397,11 +397,11 @@ 12 Caratula del Álbum Múltiples años - Resume when a Bluetooth device is connected - Pause when a Bluetooth device is disconnected - All Bluetooth devices - Only A2dp devices - Disabled + Reanudar al conectar un dispositivo Bluetooth + Pausar al desconectar un dispositivo Bluetooth + Todos los dispositivos Bluetooth + Solo dispositivos de audio (A2DP) + Deshabilitado Ultrasonic no puede acceder a la caché de los ficheros de música. La ubicación de la caché se restableció a la ruta predeterminada. Atención diff --git a/ultrasonic/src/main/res/values-fr/strings.xml b/ultrasonic/src/main/res/values-fr/strings.xml index fdfc39e5..ffb4d850 100644 --- a/ultrasonic/src/main/res/values-fr/strings.xml +++ b/ultrasonic/src/main/res/values-fr/strings.xml @@ -400,7 +400,7 @@ Resume when a Bluetooth device is connected Pause when a Bluetooth device is disconnected All Bluetooth devices - Only A2dp devices + Only audio (A2DP) devices Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. diff --git a/ultrasonic/src/main/res/values-hu/strings.xml b/ultrasonic/src/main/res/values-hu/strings.xml index cfe49083..8e15af77 100644 --- a/ultrasonic/src/main/res/values-hu/strings.xml +++ b/ultrasonic/src/main/res/values-hu/strings.xml @@ -400,7 +400,7 @@ Folytatás Bluetooth eszköz csatlakozásakor Szünet Bluetooth eszköz kikapcsolásakor Minden Bluetooth eszköz - Csak A2dp eszközök + Csak audio (A2DP) eszközök Kikapcsolva Az Ultrasonic nem éri el a zenei fájl gyorsítótárat. A gyorsítótár helye visszaállítva az alapbeállításra. diff --git a/ultrasonic/src/main/res/values-nl/strings.xml b/ultrasonic/src/main/res/values-nl/strings.xml index 97a43337..dfa04395 100644 --- a/ultrasonic/src/main/res/values-nl/strings.xml +++ b/ultrasonic/src/main/res/values-nl/strings.xml @@ -400,7 +400,7 @@ Resume when a Bluetooth device is connected Pause when a Bluetooth device is disconnected All Bluetooth devices - Only A2dp devices + Only audio (A2DP) devices Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. diff --git a/ultrasonic/src/main/res/values-pl/strings.xml b/ultrasonic/src/main/res/values-pl/strings.xml index 2769dd48..b2896d75 100644 --- a/ultrasonic/src/main/res/values-pl/strings.xml +++ b/ultrasonic/src/main/res/values-pl/strings.xml @@ -400,7 +400,7 @@ ponieważ api Subsonic nie wspiera nowego sposobu autoryzacji dla użytkowników Resume when a Bluetooth device is connected Pause when a Bluetooth device is disconnected All Bluetooth devices - Only A2dp devices + Only audio (A2DP) devices Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. diff --git a/ultrasonic/src/main/res/values-pt-rBR/strings.xml b/ultrasonic/src/main/res/values-pt-rBR/strings.xml index 92310141..8fb726ab 100644 --- a/ultrasonic/src/main/res/values-pt-rBR/strings.xml +++ b/ultrasonic/src/main/res/values-pt-rBR/strings.xml @@ -400,7 +400,7 @@ Resume when a Bluetooth device is connected Pause when a Bluetooth device is disconnected All Bluetooth devices - Only A2dp devices + Only audio (A2DP) devices Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. diff --git a/ultrasonic/src/main/res/values-pt/strings.xml b/ultrasonic/src/main/res/values-pt/strings.xml index 43574ee8..0ce98f5d 100644 --- a/ultrasonic/src/main/res/values-pt/strings.xml +++ b/ultrasonic/src/main/res/values-pt/strings.xml @@ -400,7 +400,7 @@ Resume when a Bluetooth device is connected Pause when a Bluetooth device is disconnected All Bluetooth devices - Only A2dp devices + Only audio (A2DP) devices Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index 6607b34c..e3c5ca39 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -403,7 +403,7 @@ Resume when a Bluetooth device is connected Pause when a Bluetooth device is disconnected All Bluetooth devices - Only A2dp devices + Only audio (A2DP) devices Disabled Ultrasonic can\'t access the music file cache. Cache location was reset to the default path. From 6355a7ed80ff6ac421ecdf41fc45333b8f49986b Mon Sep 17 00:00:00 2001 From: Nite Date: Tue, 29 Sep 2020 14:13:49 +0200 Subject: [PATCH 5/5] Fixed missing Intent in AndroidManifest --- ultrasonic/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/ultrasonic/src/main/AndroidManifest.xml b/ultrasonic/src/main/AndroidManifest.xml index 98132a26..515a6f3d 100644 --- a/ultrasonic/src/main/AndroidManifest.xml +++ b/ultrasonic/src/main/AndroidManifest.xml @@ -142,6 +142,7 @@ +