Implement bluetooth autospawn / autoplayback feature #235

This commit is contained in:
Markus Ebner 2022-09-08 18:16:41 +02:00
parent 574224ff99
commit d0f9b049de
No known key found for this signature in database
GPG key ID: D9EFBDF79351AABC
9 changed files with 79 additions and 0 deletions

View file

@ -8,6 +8,11 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Bluetooth auto-connect functionality -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" android:minSdkVersion="31" />
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<!-- Work around ExoPlayer requiring network permissions we do not use --> <!-- Work around ExoPlayer requiring network permissions we do not use -->
<uses-permission <uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" android:name="android.permission.ACCESS_NETWORK_STATE"
@ -102,6 +107,15 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- Auxio's auto-playback on BT connect receiver. -->
<receiver
android:name=".playback.system.BluetoothConnectReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
</intent-filter>
</receiver>
<!-- Auxio's one and only AppWidget. --> <!-- Auxio's one and only AppWidget. -->
<receiver <receiver
android:name=".widgets.WidgetProvider" android:name=".widgets.WidgetProvider"

View file

@ -23,6 +23,7 @@ import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import org.oxycblt.auxio.databinding.ActivityMainBinding import org.oxycblt.auxio.databinding.ActivityMainBinding
@ -73,6 +74,18 @@ class MainActivity : AppCompatActivity() {
if (!startIntentAction(intent)) { if (!startIntentAction(intent)) {
playbackModel.startAction(InternalPlayer.Action.RestoreState) playbackModel.startAction(InternalPlayer.Action.RestoreState)
} }
// Check bluetooth connect permissions if required for bt autoconnect feature
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val settings = Settings(this)
if (settings.bluetoothAutoplay) {
ActivityCompat.requestPermissions(
this,
arrayOf<String>(android.Manifest.permission.BLUETOOTH_CONNECT),
BLUETOOTH_PERMISSION_REQUEST_ID
)
}
}
} }
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
@ -141,5 +154,6 @@ class MainActivity : AppCompatActivity() {
companion object { companion object {
private const val KEY_INTENT_USED = BuildConfig.APPLICATION_ID + ".key.FILE_INTENT_USED" private const val KEY_INTENT_USED = BuildConfig.APPLICATION_ID + ".key.FILE_INTENT_USED"
private const val BLUETOOTH_PERMISSION_REQUEST_ID = 1337 * 42;
} }
} }

View file

@ -0,0 +1,33 @@
package org.oxycblt.auxio.playback.system
import android.bluetooth.BluetoothProfile
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import org.oxycblt.auxio.playback.state.InternalPlayer
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.settings.Settings
class BluetoothConnectReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == android.bluetooth.BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED) {
val newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED)
if (newState == BluetoothProfile.STATE_CONNECTED) {
val settings = Settings(context)
if (settings.bluetoothAutoplay) {
// make sure required services are up and running
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(Intent(context, PlaybackService::class.java))
} else {
context.startService(Intent(context, PlaybackService::class.java))
}
// start playback
val playbackManager = PlaybackStateManager.getInstance()
playbackManager.startAction(InternalPlayer.Action.RestoreState)
playbackManager.changePlaying(true)
}
}
}
}
}

View file

@ -135,6 +135,10 @@ class Settings(private val context: Context, private val callback: Callback? = n
val headsetAutoplay: Boolean val headsetAutoplay: Boolean
get() = inner.getBoolean(context.getString(R.string.set_key_headset_autoplay), false) get() = inner.getBoolean(context.getString(R.string.set_key_headset_autoplay), false)
/** Whether a connected bluetooth device should cause Auxio to spawn and start playback */
val bluetoothAutoplay: Boolean
get() = inner.getBoolean(context.getString(R.string.set_key_bluetooth_autoplay), false)
/** The current ReplayGain configuration */ /** The current ReplayGain configuration */
val replayGainMode: ReplayGainMode val replayGainMode: ReplayGainMode
get() = get() =

View file

@ -17,6 +17,8 @@
package org.oxycblt.auxio.settings package org.oxycblt.auxio.settings
import android.app.Activity
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
@ -44,6 +46,8 @@ import org.oxycblt.auxio.util.isNight
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.auxio.util.systemBarInsetsCompat
import java.security.Permission
import java.util.jar.Manifest
/** /**
* The actual fragment containing the settings menu. Inherits [PreferenceFragmentCompat]. * The actual fragment containing the settings menu. Inherits [PreferenceFragmentCompat].

View file

@ -57,6 +57,8 @@
<string name="set_audio">Audio</string> <string name="set_audio">Audio</string>
<string name="set_headset_autoplay">Kopfhörer: automatische Wiedergabe</string> <string name="set_headset_autoplay">Kopfhörer: automatische Wiedergabe</string>
<string name="set_headset_autoplay_desc">Beginne die Wiedergabe immer, wenn Kopfhörer verbunden sind (funktioniert nicht auf allen Geräten)</string> <string name="set_headset_autoplay_desc">Beginne die Wiedergabe immer, wenn Kopfhörer verbunden sind (funktioniert nicht auf allen Geräten)</string>
<string name="set_bluetooth_autoplay">Bluetooth: automatische Wiedergabe</string>
<string name="set_bluetooth_autoplay_desc">Auxio starten und Wiedergabe fortführen, sobald ein Bluetooth Audio fähiges Gerät verbunden wurde</string>
<string name="set_replay_gain">ReplayGain-Strategie</string> <string name="set_replay_gain">ReplayGain-Strategie</string>
<string name="set_pre_amp">ReplayGain-Prälautverstärkung</string> <string name="set_pre_amp">ReplayGain-Prälautverstärkung</string>
<string name="set_pre_amp_desc">Während der Musikwiedergabe, trifft die Prälautverstärkung dem aktuellem Abgleich zu</string> <string name="set_pre_amp_desc">Während der Musikwiedergabe, trifft die Prälautverstärkung dem aktuellem Abgleich zu</string>

View file

@ -15,6 +15,7 @@
<string name="set_key_alt_notif_action" translatable="false">KEY_ALT_NOTIF_ACTION</string> <string name="set_key_alt_notif_action" translatable="false">KEY_ALT_NOTIF_ACTION</string>
<string name="set_key_headset_autoplay" translatable="false">auxio_headset_autoplay</string> <string name="set_key_headset_autoplay" translatable="false">auxio_headset_autoplay</string>
<string name="set_key_bluetooth_autoplay" translatable="false">auxio_bluetooth_autoplay</string>
<string name="set_key_replay_gain" translatable="false">auxio_replay_gain</string> <string name="set_key_replay_gain" translatable="false">auxio_replay_gain</string>
<string name="set_key_pre_amp" translatable="false">auxio_pre_amp</string> <string name="set_key_pre_amp" translatable="false">auxio_pre_amp</string>
<string name="set_key_pre_amp_with" translatable="false">auxio_pre_amp_with</string> <string name="set_key_pre_amp_with" translatable="false">auxio_pre_amp_with</string>

View file

@ -180,6 +180,8 @@
<string name="set_audio">Audio</string> <string name="set_audio">Audio</string>
<string name="set_headset_autoplay">Headset autoplay</string> <string name="set_headset_autoplay">Headset autoplay</string>
<string name="set_headset_autoplay_desc">Always start playing when a headset is connected (may not work on all devices)</string> <string name="set_headset_autoplay_desc">Always start playing when a headset is connected (may not work on all devices)</string>
<string name="set_bluetooth_autoplay">Bluetooth autoplay</string>
<string name="set_bluetooth_autoplay_desc">A connected bluetooth audio device causes Auxio to spawn and start playback</string>
<string name="set_replay_gain">ReplayGain strategy</string> <string name="set_replay_gain">ReplayGain strategy</string>
<string name="set_replay_gain_track">Prefer track</string> <string name="set_replay_gain_track">Prefer track</string>
<string name="set_replay_gain_album">Prefer album</string> <string name="set_replay_gain_album">Prefer album</string>

View file

@ -74,6 +74,11 @@
app:summary="@string/set_headset_autoplay_desc" app:summary="@string/set_headset_autoplay_desc"
app:title="@string/set_headset_autoplay" /> app:title="@string/set_headset_autoplay" />
<SwitchPreferenceCompat
app:key="@string/set_key_bluetooth_autoplay"
app:summary="@string/set_bluetooth_autoplay_desc"
app:title="@string/set_bluetooth_autoplay" />
<org.oxycblt.auxio.settings.ui.IntListPreference <org.oxycblt.auxio.settings.ui.IntListPreference
app:defaultValue="@integer/replay_gain_dynamic" app:defaultValue="@integer/replay_gain_dynamic"
app:entries="@array/entries_replay_gain" app:entries="@array/entries_replay_gain"