昨天實作了顯示功能,今天來實作切換上下一首和播放暫停的功能,在 metaChanged 時,再額外對個別的 UI 元件設定 PendingIntent,previous 按鈕設定 PendingIntent,裡面的 action 就帶入 SKIP_PREVIOUS 的事件,play 和 next 就分別帶入對應的事件。在點擊 cover 時,則是會打開 App 。
private fun setPendingIntent(remoteViews: RemoteViews, context: Context) {
remoteViews.setOnClickPendingIntent(
R.id.previous,
buildPendingIntent(context, WidgetConstants.WidgetAction.SKIP_PREVIOUS.name)
)
remoteViews.setOnClickPendingIntent(
R.id.play,
buildPendingIntent(context, WidgetConstants.WidgetAction.PLAY_PAUSE.name)
)
remoteViews.setOnClickPendingIntent(
R.id.next,
buildPendingIntent(context, WidgetConstants.WidgetAction.SKIP_NEXT.name)
)
remoteViews.setOnClickPendingIntent(R.id.cover, buildContentIntent(context))
}
可以看到這邊要送事件的目標是 MusicService,在 MusicService 就還需要再額外設定收事件,做對應的操作。
private fun buildPendingIntent(context: Context, action: String): PendingIntent? {
val intent = Intent(context, MusicService::class.java)
intent.action = action
return intent.asServicePendingIntent(context, PendingIntent.FLAG_UPDATE_CURRENT)
}
cover 點擊這邊比較單純,就是開起首頁 MainActivity。
private fun buildContentIntent(context: Context): PendingIntent {
val intent = Intent(context, MainActivity::class.java)
return PendingIntent.getActivity(
context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT
)
}
在 MusicService 內多加入 onStartCommand,收到 intent 後判斷對應的 action,播放、上一首、下一首。
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
handleIntent(intent)
return Service.START_NOT_STICKY
}
private fun handleIntent(intent: Intent?) {
intent ?: return
when (WidgetConstants.WidgetAction.values().find { it.name == intent.action }) {
WidgetConstants.WidgetAction.PLAY_PAUSE -> handlePlayPause()
WidgetConstants.WidgetAction.SKIP_NEXT -> handleSkipNext()
WidgetConstants.WidgetAction.SKIP_PREVIOUS -> handleSkipPrevious()
}
}
在 MusicService 內有 mediaSession,透過 mediaSession 可以拿到 transportControls(播放器架構實作 (3) - MediaSession 實作),可以知道現在的播放狀態,並且可以去執行下一首、上一首。
private fun handlePlayPause() {
if (mediaSession.controller.playbackState.isPlaying) {
mediaSession.controller.transportControls.pause()
} else {
mediaSession.controller.transportControls.play()
}
}
private fun handleSkipNext() {
mediaSession.controller.transportControls.skipToNext()
}
private fun handleSkipPrevious() {
mediaSession.controller.transportControls.skipToPrevious()
}
成果圖:
程式碼在這,分支名稱(day22_widget_action_function): Fancy/day22_widget_action_function