Skip to content

Commit db4ac84

Browse files
committed
android: fix ear detection when none are in use and either or both are worn
Music would start playing when neither are in ear, but even one is worn. This happens even when the music was not playing when they were removed (or, connected first)
1 parent 9b96218 commit db4ac84

2 files changed

Lines changed: 29 additions & 33 deletions

File tree

android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,39 +1468,36 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
14681468
) {
14691469
connectAudio(this@AirPodsService, device)
14701470
justEnabledA2dp = true
1471-
val bluetoothAdapter =
1472-
this@AirPodsService.getSystemService(
1473-
BluetoothManager::class.java
1474-
).adapter
1475-
bluetoothAdapter.getProfileProxy(
1476-
this@AirPodsService,
1477-
object : BluetoothProfile.ServiceListener {
1478-
override fun onServiceConnected(
1479-
profile: Int,
1480-
proxy: BluetoothProfile
1481-
) {
1482-
if (profile == BluetoothProfile.A2DP) {
1483-
val connectedDevices =
1484-
proxy.connectedDevices
1485-
if (connectedDevices.isNotEmpty()) {
1486-
MediaController.sendPlay()
1487-
}
1471+
val a2dpConnectionStateReceiver = object : BroadcastReceiver() {
1472+
override fun onReceive(context: Context, intent: Intent) {
1473+
if (intent.action == "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED") {
1474+
val state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED)
1475+
val previousState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED)
1476+
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
1477+
1478+
Log.d("MediaController", "A2DP state changed: $previousState -> $state for device: ${device?.address}")
1479+
1480+
if (state == BluetoothProfile.STATE_CONNECTED &&
1481+
previousState != BluetoothProfile.STATE_CONNECTED &&
1482+
device?.address == this@AirPodsService.device?.address) {
1483+
1484+
Log.d("MediaController", "A2DP connected, sending play command")
1485+
MediaController.sendPlay()
1486+
MediaController.iPausedTheMedia = false
1487+
1488+
context.unregisterReceiver(this)
14881489
}
1489-
bluetoothAdapter.closeProfileProxy(
1490-
profile,
1491-
proxy
1492-
)
14931490
}
1494-
1495-
override fun onServiceDisconnected(
1496-
profile: Int
1497-
) {
1498-
}
1499-
},
1500-
BluetoothProfile.A2DP
1501-
)
1502-
1491+
}
1492+
}
1493+
val a2dpIntentFilter = IntentFilter("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED")
1494+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
1495+
registerReceiver(a2dpConnectionStateReceiver, a2dpIntentFilter, RECEIVER_EXPORTED)
1496+
} else {
1497+
registerReceiver(a2dpConnectionStateReceiver, a2dpIntentFilter)
1498+
}
15031499
} else if (newInEarData == listOf(false, false)) {
1500+
MediaController.sendPause(force = true)
15041501
disconnectAudio(this@AirPodsService, device)
15051502
}
15061503

android/app/src/main/java/me/kavishdevar/librepods/utils/MediaController.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ object MediaController {
8282
if (configs != null && !iPausedTheMedia) {
8383
Log.d("MediaController", "Seems like the user changed the state of media themselves, now I won't play until the ear detection pauses it.")
8484
handler.postDelayed({
85-
iPausedTheMedia = !audioManager.isMusicActive
8685
userPlayedTheMedia = audioManager.isMusicActive
8786
}, 7) // i have no idea why android sends an event a hundred times after the user does something.
8887
}
@@ -98,9 +97,9 @@ object MediaController {
9897

9998
@Synchronized
10099
fun sendPause(force: Boolean = false) {
101-
Log.d("MediaController", "Sending pause with iPausedTheMedia: $iPausedTheMedia, userPlayedTheMedia: $userPlayedTheMedia")
100+
Log.d("MediaController", "Sending pause with iPausedTheMedia: $iPausedTheMedia, userPlayedTheMedia: $userPlayedTheMedia, isMusicActive: ${audioManager.isMusicActive}, force: $force")
102101
if ((audioManager.isMusicActive && !userPlayedTheMedia) || force) {
103-
iPausedTheMedia = true
102+
iPausedTheMedia = if (force) audioManager.isMusicActive else true
104103
userPlayedTheMedia = false
105104
audioManager.dispatchMediaKeyEvent(
106105
KeyEvent(

0 commit comments

Comments
 (0)