I have stared tirelessly at the documentation that android provides for the
MediaButtonReceiver class (https://developer.android.com/reference/kotlin/androidx/media/session/MediaButtonReceiver?hl=en)
and the guide on responding to media buttons
(https://developer.android.com/guide/topics/media-apps/mediabuttons).
Also looked around StackOverflow for people who had a similar issue to this and followed the guidelines that people provided there but I still have not found a way to solve this issue.
Receiving media key events in Service
What I'm trying to do is make my service pick up events from a volume down/up and play button from a bluetooth remote. When checking the sytem_process logs I can see that the button events are indeed getting sent to the service but the callback is not picking up on any of these events. Any clue to what the issue is? Log.d is never called on the callbacks
AndroidManifest.xml
<application
android:name=".BaseApplication"
android:allowBackup="true"
android:debuggable="true"
android:extractNativeLibs="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="HardcodedDebugMode">
<activity
android:name=".activity.MainActivity"
android:screenOrientation="reverseLandscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".receivers.OnBootReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter android:priority="999">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON"/>
</intent-filter>
</receiver>
<service android:name=".service.MyForegroundService">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
<intent-filter>
<action android:name="com.example.example.myservice.ACTION_BIND" />
</intent-filter>
</service>
</application>
</manifest>
MyService.kt
class MyForegroundService : Service() {
private val TAG = "MyForegroundService"
private lateinit var mediaSession: MediaSessionCompat
private fun getVolumeProvider(): VolumeProviderCompat? {
val audio: AudioManager = getSystemService(AUDIO_SERVICE) as AudioManager
val STREAM_TYPE: Int = AudioManager.STREAM_MUSIC
val currentVolume: Int = audio.getStreamVolume(STREAM_TYPE)
val maxVolume: Int = audio.getStreamMaxVolume(STREAM_TYPE)
val VOLUME_UP = 1
val VOLUME_DOWN = -1
return object : VolumeProviderCompat(
VOLUME_CONTROL_RELATIVE,
maxVolume,
currentVolume
) {
override fun onAdjustVolume(direction: Int) {
Log.d(TAG, "onAdjustVolume: ")
// Up = 1, Down = -1, Release = 0
// Replace with your action, if you don't want to adjust system volume
if (direction == VOLUME_UP) {
audio.adjustStreamVolume(
STREAM_TYPE,
AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE
)
} else if (direction == VOLUME_DOWN) {
audio.adjustStreamVolume(
STREAM_TYPE,
AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE
)
}
setCurrentVolume(audio.getStreamVolume(STREAM_TYPE))
}
}
}
private val callback = object : MediaSessionCompat.Callback() {
override fun onMediaButtonEvent(mediaButtonIntent: Intent): Boolean {
val keyEvent = mediaButtonIntent.extras?.get(Intent.EXTRA_KEY_EVENT)
Log.d(TAG, "onMediaButtonEvent: $keyEvent")
return super.onMediaButtonEvent(mediaButtonIntent)
}
override fun onPlay() {
Log.d(TAG, "onPlay: ")
super.onPlay()
}
override fun onCommand(command: String?, extras: Bundle?, cb: ResultReceiver?) {
Log.d(TAG, "onCommand: ")
super.onCommand(command, extras, cb)
}
}
override fun onCreate() {
super.onCreate()
mediaSession = MediaSessionCompat(applicationContext, "MyForegroundService")
mediaSession.setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
)
mediaSession.setPlaybackToRemote(getVolumeProvider())
mediaSession.setCallback(callback)
mediaSession.setActive(true)
}
override fun onBind(intent: Intent?): IBinder? {
return binder
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
MediaButtonReceiver.handleIntent(mediaSession, intent)
return START_STICKY
}
private fun startForeground() {
// ...
startForeground(1, notification)
}
override fun onDestroy() {
super.onDestroy()
mediaSession.release()
stopForeground(true)
}
}