Reputation: 791
I'm developing an audio streaming application for Android and integrating Android Auto. I've been following these two tutorials.
Using the Desktop Head Unit, I'm able to select my media app from the media app list, but from there a ProgressBar
stays instead of giving way to the "To play something, open the menu at the top left." message seen in the Universal Music Player.
On inspection, it seems that the MediaBrowserServiceCompat
's onGetRoot()
is never invoked and thus never populating my MediaItemCompat
into the Auto app's list.
My manifest contains the following.
<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>
My automotive_app_desc.xml
is very simple, only declaring Media.
<?xml version="1.0" encoding="utf-8"?>
<automotiveApp>
<uses name="media"/>
</automotiveApp>
My MediaService
extends MediaBrowserServiceCompat
. In the onCreate()
I create and set my 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);
}
Finally, the two overridden methods from MediaBrowserServiceCompat
, of which neither is ever called.
@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);
}
}
As far as I can tell, that's everything required to get an Android Auto started, yet when I open the app on my desktop head unit, there is only a ProgressBar
greeting me, and when I open the off-screen nav drawer, there's another one. I haven't heard of that state in any material I've read. Is there something I missed?
Upvotes: 8
Views: 1820
Reputation: 11
I'm developing an Android auto but I have some problems in this part of my code, in Onbind
method of the service:
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;}
}
I have other activities bound with my service through a musicBind IBinder
, but on the other hand I have set all things to connect my app in Android auto interface but after close my app after disconnect the device from the android auto I can't stop my mediabrowserservice
compat. I think it's due to this SERVICE_INTERFACE
keeps binded the service. How can I stop or destroy this from the same servicemediabrowserservicecompat
?
Upvotes: 0
Reputation: 791
Ultimately, the issue didn't have anything to do with what I described. The aforementioned MediaService
also does other tasks that require a custom Binder
. This custom Binder
didn't call the onGetRoot()
needed for the Head Unit. As a solution, I check the Intent
action and return super.onBind()
when it's from the MediaBrowserServiceCompat
.
@Override
public IBinder onBind(Intent intent) {
if (SERVICE_INTERFACE.equals(intent.getAction())) {
return super.onBind(intent);
}
return new MediaBinder();
}
The SERVICE_INTERFACE
is a constant in MediaBrowserServiceCompat
.
Upvotes: 21