【发布时间】:2020-11-20 17:49:01
【问题描述】:
我一直在不知疲倦地盯着 android 提供的文档
MediaButtonReceiver 类 (https://developer.android.com/reference/kotlin/androidx/media/session/MediaButtonReceiver?hl=en)
以及响应媒体按钮的指南
(https://developer.android.com/guide/topics/media-apps/mediabuttons).
还查看了 StackOverflow 中遇到类似问题并遵循人们提供的指南的人,但我仍然没有找到解决此问题的方法。
Receiving media key events in Service
我想做的是让我的服务从蓝牙遥控器的音量调低/调高和播放按钮中获取事件。检查 sytem_process 日志时,我可以看到按钮事件确实被发送到服务,但回调没有收到任何这些事件。有什么线索吗? Log.d 永远不会在回调中调用
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)
}
}
【问题讨论】:
-
按照这篇文章stackoverflow.com/questions/57709401/…的答案解决了这个问题
标签: android kotlin bluetooth android-service android-mediasession