9

I'm having trouble with the Play [song] on [app] command; specifically the "app" is not being recognised by Android Auto.

I get an audio speech message back: "Not sure how to help with play song on app"

So the speech recognition is working perfectly (as song and app are as I spoke), however either the matching to the app isn't working or it is not obvious to Auto that my app can handle this.

In the simulator, search works from the Search menu option so I'm assuming my intent filters are correct.

My Manifest has the following:

    <!-- - - - - - - - - - - - - - - - - - - - - -->
    <!-- Auto -->
    <!-- - - - - - - - - - - - - - - - - - - - - -->
    <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/brand_icon_white" />
    <service android:name=".library.service.auto.MyMediaBrowserService"
        android:exported="true">
        <intent-filter>
            <action android:name="android.media.browse.MediaBrowserService"/>
        </intent-filter>
    </service>

I have tried putting the following into my service declaration or an Activity as shown in the YouTube DevByte but neither seems to work:

    <action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
    <category android:name="android.intent.category.DEFAULT" />

I would expect it to be in the Service as there are no Activities associated with the Service. I would like to know for sure where this should be.

I have probably missed something out or misunderstood something. One issue could be that the name of the application contains a number in it (eg. 1up).

juliusspencer
  • 3,008
  • 3
  • 26
  • 30

2 Answers2

10

Simply declare an intent-filter for MEDIA_PLAY_FROM_SEARCH in an Activity declaration. It is not mandatory for Android Auto to actually handle the intent, since Android Auto will call the MediaSession.Callback.onPlayFromSearch. The declaration in the manifest serves to flag your app as available to respond media voice commands. However, you might want to handle it properly, because other non-Auto environments, like Google Now, will submit voice searches via that intent.

The best way to handle the intent is by calling MediaController.TransportControls.playFromSearch, so you handle it in a consistent way no matter how the voice search was triggered.

See this snippet from uAmp AndroidManifest.xml:

    <!-- Main activity for music browsing on phone -->
    <activity
        android:name=".ui.MusicPlayerActivity"
        android:label="@string/app_name">

        [...]

        <!-- Use this intent filter to get voice searches, like "Play The Beatles" -->
        <intent-filter>
            <action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

And this is how the intent is handled:

@Override
protected void onMediaControllerConnected() {
    if (mVoiceSearchParams != null) {
        String query = mVoiceSearchParams.getString(SearchManager.QUERY);
        getMediaController().getTransportControls().playFromSearch(query, mVoiceSearchParams);
        mVoiceSearchParams = null;
    }
    getBrowseFragment().onConnected();
}

One caveat: you need to publish your app with the intent-filter and wait a few days to get it flagged and indexed for the "Play [x] on [y]" type of query. It is not instantaneous.

mangini
  • 4,179
  • 2
  • 19
  • 23
  • i'm having the same problem where google assistance dosent recognize my app and it has been a week since i published it, does the android.media.action.MEDIA_PLAY_FROM_SEARCH need to be inside an Activity so the app can be flagged? because i followed https://github.com/android/uamp/blob/master/app/src/main/AndroidManifest.xml and it's inside the service. any help will be appreciated . – Salah Hammouda Jul 06 '20 at 08:41
  • 1
    To help the next guy. I found you also have to have the android:label set in the activity with the intent filter. – user2199860 Aug 14 '20 at 01:38
5

As mangini's answer suggests, I got this working by adding only the intent filter to my main activity:

<activity
  android:name=".LandingActivity"
  android:label="@string/app_name"
  android:noHistory="true"
  android:launchMode="singleTop"
  android:theme="@style/SplashTheme">

  <!-- for the launcher -->          
  <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
    <category android:name="android.intent.category.DEFAULT"/>
  </intent-filter>

  <!-- for media search (Play X in Y) -->
  <intent-filter>
    <action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

I didn't have to add any other code. androidx.media just magically worked. When I say "Play X" while my app is running in the Android Auto foreground, my MediaSessionCompat.Callback subclass got an onPlayFromSearch callback, and when I tapped Search Results in Android Auto, my MediaBrowserServiceCompat subclass got an onSearch callback.

I also tried adding this intent-filter to my service declaration in AndroidManifest.xml, and that didn't work:

<service
  android:name=".BackgroundAudioNotificationService"
  android:exported="true">
  <intent-filter>
    <action android:name="android.media.browse.MediaBrowserService" />
    <action android:name="android.intent.action.MEDIA_BUTTON" />
    <!-- Tried to do "Play X" while running in Android Auto, and this didn't work -->
    <action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
  </intent-filter>
</service>
Heath Borders
  • 30,998
  • 16
  • 147
  • 256
  • Im facing the same issue. If apps is in foreground and u say "Play X" it works fine but if another app is in foreground for android auto and you say "Play X on Y" it doesnt work. The documentation by google is close to useless. I tried the above and it didnt work either – RamPrasadBismil Oct 29 '20 at 19:52