Skip to content

Commit 66eaa98

Browse files
committed
improve media control logic
1 parent 9fea483 commit 66eaa98

File tree

4 files changed

+62
-10
lines changed

4 files changed

+62
-10
lines changed

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ class AirPodsService: Service() {
459459
)
460460
var justEnabledA2dp = false
461461
earReceiver = object : BroadcastReceiver() {
462+
@SuppressLint("NewApi")
462463
override fun onReceive(context: Context, intent: Intent) {
463464
val data = intent.getByteArrayExtra("data")
464465
if (data != null && earDetectionEnabled) {
@@ -516,15 +517,41 @@ class AirPodsService: Service() {
516517
disconnectAudio(this@AirPodsService, device)
517518
}
518519

520+
if (inEarData.contains(false) && newInEarData == listOf(
521+
true,
522+
true
523+
)
524+
) {
525+
Log.d("AirPods Parser", "User put in both AirPods from just one.")
526+
MediaController.userPlayedTheMedia = false
527+
}
528+
if (newInEarData.contains(false) && inEarData == listOf(
529+
true,
530+
true
531+
)
532+
) {
533+
Log.d("AirPods Parser", "User took one of two out.")
534+
MediaController.userPlayedTheMedia = false
535+
}
536+
537+
if (newInEarData.sorted() == inEarData.sorted()) {
538+
return
539+
}
540+
519541
inEarData = newInEarData
520542

521543
if (inEar == true) {
522544
if (!justEnabledA2dp) {
523545
justEnabledA2dp = false
546+
// if (audioManager.activePlaybackConfigurations.any { it.audioDeviceInfo?.address == device.address }) {
524547
MediaController.sendPlay()
548+
MediaController.iPausedTheMedia = false
549+
// }
525550
}
526551
} else {
527-
MediaController.sendPause()
552+
// if (audioManager.activePlaybackConfigurations.any { it.audioDeviceInfo?.address == device.address }) {
553+
MediaController.sendPause()
554+
// }
528555
}
529556
}
530557
}

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

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,43 @@
2020
package me.kavishdevar.aln.utils
2121

2222
import android.media.AudioManager
23+
import android.media.AudioPlaybackConfiguration
24+
import android.os.Handler
25+
import android.os.Looper
2326
import android.util.Log
2427
import android.view.KeyEvent
2528

2629
object MediaController {
27-
private var initialVolume: Int? = null // Nullable to track the unset state
28-
private lateinit var audioManager: AudioManager // Declare AudioManager
30+
private var initialVolume: Int? = null
31+
private lateinit var audioManager: AudioManager
32+
var iPausedTheMedia = false
33+
var userPlayedTheMedia = false
2934

30-
// Initialize the singleton with the AudioManager instance
3135
fun initialize(audioManager: AudioManager) {
3236
this.audioManager = audioManager
37+
audioManager.registerAudioPlaybackCallback(cb, null)
38+
}
39+
40+
val cb = object : AudioManager.AudioPlaybackCallback() {
41+
override fun onPlaybackConfigChanged(configs: MutableList<AudioPlaybackConfiguration>?) {
42+
super.onPlaybackConfigChanged(configs)
43+
Log.d("MediaController", "Playback config changed, iPausedTheMedia: $iPausedTheMedia")
44+
if (configs != null && !iPausedTheMedia) {
45+
Log.d("MediaController", "Seems like the user changed the state of media themselves, now I won't `play` until the ear detection pauses it.")
46+
Handler(Looper.getMainLooper()).postDelayed({
47+
iPausedTheMedia = !audioManager.isMusicActive
48+
userPlayedTheMedia = audioManager.isMusicActive
49+
}, 7) // i have no idea why, but android sends a pause event a hundred times after the user does something.
50+
}
51+
}
3352
}
3453

3554
@Synchronized
3655
fun sendPause() {
37-
if (audioManager.isMusicActive) {
56+
Log.d("MediaController", "Sending pause with iPausedTheMedia: $iPausedTheMedia, userPlayedTheMedia: $userPlayedTheMedia")
57+
if (audioManager.isMusicActive && !userPlayedTheMedia) {
58+
iPausedTheMedia = true
59+
userPlayedTheMedia = false
3860
audioManager.dispatchMediaKeyEvent(
3961
KeyEvent(
4062
KeyEvent.ACTION_DOWN,
@@ -52,7 +74,10 @@ object MediaController {
5274

5375
@Synchronized
5476
fun sendPlay() {
55-
if (!audioManager.isMusicActive) {
77+
Log.d("MediaController", "Sending play with iPausedTheMedia: $iPausedTheMedia")
78+
if (iPausedTheMedia) {
79+
Log.d("MediaController", "Sending play and setting userPlayedTheMedia to false")
80+
userPlayedTheMedia = false
5681
audioManager.dispatchMediaKeyEvent(
5782
KeyEvent(
5883
KeyEvent.ACTION_DOWN,
@@ -76,8 +101,7 @@ object MediaController {
76101
Log.d("MediaController", "Initial Volume Set: $initialVolume")
77102
audioManager.setStreamVolume(
78103
AudioManager.STREAM_MUSIC,
79-
audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) * 1 / 12, // Set to a lower volume when speaking starts
80-
0
104+
audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) * 1 / 12, 0
81105
)
82106
}
83107
Log.d("MediaController", "Initial Volume: $initialVolume")
@@ -91,4 +115,5 @@ object MediaController {
91115
initialVolume = null // Reset to null after restoring the volume
92116
}
93117
}
118+
94119
}

android/gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[versions]
22
accompanistPermissions = "0.36.0"
3-
agp = "8.7.2"
3+
agp = "8.7.3"
44
hiddenapibypass = "4.3"
55
kotlin = "2.0.0"
66
coreKtx = "1.15.0"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Mon Oct 07 22:30:36 IST 2024
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
4-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
4+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
55
zipStoreBase=GRADLE_USER_HOME
66
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)