Android Auto - Voice - Cannot perform “Play [x] on [y]”

江枫思渺然 提交于 2021-02-18 22:41:14

问题


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).


回答1:


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.




回答2:


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>


来源:https://stackoverflow.com/questions/31953155/android-auto-voice-cannot-perform-play-x-on-y

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!