Android 汽车应用从不调用 GetRoot

Android Auto app never calls onGetRoot

我正在为 Android 开发音频流应用程序并集成 Android Auto。我一直在关注这两个教程。

Android Developer Training

PTR Android Blog

使用桌面音响主机,我可以从媒体应用程序列表中 select 我的媒体应用程序,但是 ProgressBar 会保留下来,而不是让位给 "To play something, open the menu at the top left." 在 Universal Music Player.

中看到的消息

经检查,MediaBrowserServiceCompatonGetRoot() 似乎从未被调用,因此从未将我的 MediaItemCompat 填充到 Auto 应用程序的列表中。

我的清单包含以下内容。

<manifest package="com.app.audio"
      xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<application
    android:name="com.app.audio.AudioApp"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">


    <activity
        android:name="com.app.audio.presentation.home.HomeActivity"
        android:label="@string/app_name"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>

            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

    <activity
        android:name="com.app.audio.presentation.weather.WeatherActivity"
        android:screenOrientation="userPortrait"/>

    <activity android:name="com.app.audio.presentation.settings.SettingsActivity"/>

    <activity android:name="com.app.audio.presentation.alarm.AlarmActivity"/>

    <activity android:name="com.app.audio.presentation.sleep.SleepActivity"/>

    <receiver android:name="com.app.audio.audio.AudioIntentReceiver">
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON"/>
            <action android:name="android.media.AUDIO_BECOMING_NOISY"/>
        </intent-filter>
    </receiver>

    <receiver android:name="com.app.audio.presentation.alarm.AlarmReceiver"></receiver>

    <receiver android:name="com.app.audio.presentation.sleep.SleepReceiver"></receiver>

    <service
        android:name="com.app.audio.data.service.media.MediaService"
        android:exported="true">
        <intent-filter>
            <action android:name="android.media.browse.MediaBrowserService"/>
        </intent-filter>
    </service>

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version"/>

    <meta-data
        android:name="com.google.android.gms.car.application"
        android:resource="@xml/automotive_app_desc"/>

    <meta-data
        android:name="com.google.android.gms.car.notification.SmallIcon"
        android:resource="@drawable/ic_launcher"/>
</application>

我的automotive_app_desc.xml很简单,只声明Media。

<?xml version="1.0" encoding="utf-8"?>
<automotiveApp>
    <uses name="media"/>
</automotiveApp>

我的 MediaService 扩展 MediaBrowserServiceCompat。在 onCreate() 我创建并设置了我的 MediaSessionCompat.

@Override
public void onCreate() {
    super.onCreate();
    //...
    mediaSession = new MediaSessionCompat(
            this,
            SESSION_TAG,
            mediaIntentReceiver,
            null
    );

    mediaSession.setFlags(
            MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                    MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

    mediaSession.setCallback(new MediaSessionCompat.Callback() {
        @Override
        public void onPlay() {
            super.onPlay();
            play(selectedStream);
        }

        @Override
        public void onPause() {
            super.onPause();
            pause();
        }

        @Override
        public void onStop() {
            super.onStop();
            stop();
        }

        @Override
        public void onSkipToNext() {
            super.onSkipToNext();
            playNextStation();
        }

        @Override
        public void onSkipToPrevious() {
            super.onSkipToPrevious();
            playPreviousStation();
        }
    });

    mediaSession.setActive(true);
    setSessionToken(mediaSession.getSessionToken());
    updatePlaybackState(ACTION_STOP);
}

最后,来自 MediaBrowserServiceCompat 的两个重写方法,其中一个都没有被调用。

@Nullable
@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
    return new BrowserRoot(ROOT_ID, null);
}

@Override
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
    List<MediaBrowserCompat.MediaItem> items = getMediaItemsById(parentId);
    if (items != null) {
        result.sendResult(items);
    }
}

据我所知,这就是启动 Android Auto 所需的一切,但是当我在桌面主机上打开该应用程序时,只有 ProgressBar 问候我,当我打开屏幕外的导航抽屉时,还有另一个。在我读过的任何 material 中,我都没有听说过这种状态。我错过了什么吗?

最终,问题与我描述的没有任何关系。前面提到的 MediaService 还执行其他需要自定义 Binder 的任务。此自定义 Binder 没有调用 Head Unit 所需的 onGetRoot()。作为解决方案,我检查了 Intent 操作和 return super.onBind() 当它来自 MediaBrowserServiceCompat.

@Override
public IBinder onBind(Intent intent) {
    if (SERVICE_INTERFACE.equals(intent.getAction())) {
        return super.onBind(intent);
    }
    return new MediaBinder();
}

SERVICE_INTERFACEMediaBrowserServiceCompat中的常量。

我正在开发一个 Android 汽车,但是我的这部分代码在服务的 Onbind 方法中有一些问题:

public IBinder onBind(Intent arg0) {
    Log.i("TAG", "OnBind");
    // TODO Auto-generated method stub
    if (SERVICE_INTERFACE.equals(arg0.getAction())) {
        Log.i("TAG", "SERVICE_INTERFACE");
        registerReceiver(receiver, filter);
        return super.onBind(arg0);
    } else { 
        Log.i("Musica Service", "musicBind");
        return musicBind;}
}

我有其他活动通过 musicBind IBinder 与我的服务绑定,但另一方面,我已设置所有内容以在 Android 自动界面中连接我的应用程序,但在断开连接后关闭我的应用程序来自 android auto 的设备 我无法停止我的 mediabrowserservice 兼容。我认为这是由于此 SERVICE_INTERFACE 保持绑定服务。我怎样才能从同一个 servicemediabrowserservicecompat 停止或销毁它?