问题描述
我在让 Google 助理为我的媒体应用播放媒体时遇到了一些问题。
我已经使用 Media Controller Tester 应用验证了播放操作正在运行。我可以通过 Google 助理使用 Open Feature Actions。
但每次我尝试使用 Play AppName
或 Play Station on AppName
之类的短语时,Google 助理都会尝试启动 TuneIn。
如果我尝试 Play music on AppName
助理启动 YouTube 音乐。
我已经尝试了文档 here 中的所有内容,并使用 UAMP 作为基础(我也看到了类似的行为)
这是我的音频服务的精简版:
class AudioService : MediabrowserServiceCompat() {
@Inject
lateinit var audioServicebrowserManager: AudioServicebrowserManager
@Inject
lateinit var schedulerProvider: RxSchedulerProvider
@Inject
lateinit var playbackPreparer: AppPlaybackPreparer
@Inject
lateinit var playbackControldispatcher: AppControldispatcher
@Inject
lateinit var audioProvider: AudioProvider
@Inject
lateinit var playbackManager: PlaybackManager
@Inject
lateinit var mediaSessionChangedCallback: MediaSessionChangedCallback
private lateinit var mediaSession: MediaSessionCompat
private lateinit var mediaSessionConnector: MediaSessionConnector
private lateinit var mediaController: MediaControllerCompat
private lateinit var audionotificationmanager: Audionotificationmanager
private lateinit var packageValidator: PackageValidator
private val disposables = Compositedisposable()
companion object {
private const val SEEK_BACKWARD_INCREMENT = 15000
private const val SEEK_FORWARD_INCREMENT = 30000
private const val MEDIA_SESSION_TAG: String = "AudioService"
internal const val MetaDATA_MEDIA_TYPE = "au.net.app.player.service.Metadata.mediaType"
internal const val MetaDATA_MEDIA_TYPE_ondemand_VIDEO = 0L
internal const val MetaDATA_MEDIA_TYPE_ondemand_AUdio = 2L
internal const val MetaDATA_MEDIA_TYPE_LIVE = 1L
val DEFAULT_PLAYBACK_STATE: PlaybackStateCompat = PlaybackStateCompat.Builder()
.setState(PlaybackStateCompat.STATE_NONE,PlaybackStateCompat.PLAYBACK_POSITION_UNKNowN,1.0f)
.build()
}
override fun onCreate() {
AndroidInjection.inject(this)
super.onCreate()
mediaSession = MediaSessionCompat(this,MEDIA_SESSION_TAG).apply {
setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)
isActive = true
}
sessionToken = mediaSession.sessionToken
mediaSessionConnector = MediaSessionConnector(mediaSession).apply {
setRewindIncrementMs(SEEK_BACKWARD_INCREMENT)
setFastForwardIncrementMs(SEEK_FORWARD_INCREMENT)
setPlaybackPreparer(playbackPreparer)
setQueueNavigator(AppQueueNavigator(mediaSession,audioProvider,this@AudioService,this))
setControldispatcher(playbackControldispatcher)
setPlayer(playbackManager.currentPlayback.playerImpl)
registerCustomCommandReceiver(playbackManager.mediaSessionCommandReceiver)
}
disposables.add(
playbackManager.currentPlaybackObservable.subscribe { currentPlayback ->
mediaSessionConnector.setPlayer(currentPlayback.playerImpl)
}
)
mediaController = MediaControllerCompat(this,mediaSession)
mediaController.registerCallback(mediaSessionChangedCallback)
try {
audionotificationmanager = Audionotificationmanager(this,mediaController)
} catch (e: remoteexception) {
throw IllegalStateException("Could not create a Medianotificationmanager",e)
}
packageValidator = PackageValidator(this,R.xml.allowed_media_browser_callers)
}
private var currentLoadChildrendisposable: disposable? = null
override fun onLoadChildren(parentId: String,result: Result<MutableList<MediabrowserCompat.MediaItem>>) {
Timber.d("""
onLoadChildren(
parentId = $parentId,result = $result
)
""".trimIndent())
}
override fun onGetRoot(clientPackageName: String,clientUid: Int,rootHints: Bundle?): browserRoot? {
Timber.d("""
onGetRoot(
clientPackageName = $clientPackageName,clientUid = $clientUid,rootHints = $rootHints
)
""".trimIndent())
}
override fun onStartCommand(intent: Intent?,flags: Int,startId: Int): Int {
super.onStartCommand(intent,flags,startId)
return START_STICKY
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
playbackManager.handleStop()
stopSelf()
}
override fun onDestroy() {
super.onDestroy()
playbackManager.handleStop()
disposables.dispose()
mediaSession.isActive = false
mediaSession.release()
}
}
模块清单(注意 - 该服务不在我的主应用模块中)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="au.net.app.player.service">
<uses-permission android:name="android.permission.INTERNET" />
<application>
<service
android:name="au.net.app.player.service.AudioService"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediabrowserService" />
</intent-filter>
</service>
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<Meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
</application>
</manifest>
在主应用清单中:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="au.net.app"
android:installLocation="auto">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:name=".AppApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:hardwareAccelerated="true"
android:theme="@style/AppTheme">
<activity
android:name=".mainscreen.MainActivity"
android:launchMode="singleTask"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Intent filters to open Feature screens -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.broWSABLE" />
<data
android:host="feature"
android:pathPattern="/.*"
android:scheme="${APP_SCHEME}" />
</intent-filter>
<!-- Declares that the app handles SEARCH intent for media playback -->
<!-- This is mandatory for Android Auto support: -->
<!-- https://stackoverflow.com/questions/31953155/android-auto-voice-cannot-perform-play-x-on-y/31976075#31976075 -->
<intent-filter>
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- required for Google Assistant integration -->
<Meta-data android:name="com.google.android.actions" android:resource="@xml/actions" />
</application>
</manifest>
我还尝试使用以下方法设置我的播放状态:
val DEFAULT_PLAYBACK_STATE: PlaybackStateCompat = PlaybackStateCompat.Builder()
.setActions(getSupportedActions())
.setState(PlaybackStateCompat.STATE_NONE,1.0f)
.build()
private fun getSupportedActions(): Long {
return PlaybackStateCompat.ACTION_PLAY or
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH or
PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
PlaybackStateCompat.ACTION_SKIP_TO_PREVIoUS or
PlaybackStateCompat.ACTION_PLAY_PAUSE
}
但我的理解是我不需要,因为 MediaSessionConnector
应该负责(因为我使用的是 ExoPlayer)。添加这个没有帮助。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)