Android Auto - Voice - Cannot perform "Play [x] on [y]" - android

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

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.

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>

Related

How to start specific activity by saying OK Google?

I would like to have two activities. FirstActivity should be started from
launcher (by tapping on icon) and SecondActivity should be started by voice
command (by saying "OK Google, start play example").
The problem is that for my current configuration only FirstActivity is
started. Also method isVoiceInteraction returns false. I also don't see any values in flags that indicates that activity was started by voice.
Here's part of AndroidManifest.xml:
<application android:label="play example">
<activity android:name="com.example.FirstActivity" android:label="play example">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.example.EXAMPLE_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.example.SecondActivity" android:label="play example">
<intent-filter>
<action android:name="com.example.EXAMPLE_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE" />
</intent-filter>
</activity>
</application>
Here it states:
To specify the text to say after "Start", specify a label attribute for the activtiy that you want to start.
But when I change label for SecondActivity it does not help.
I'm using API version 26.
How to setup configuration to handle described behavior?
AFAIK isVoiceInteraction will always return false when the application is opened using "open" voice command. However, the scenario which you described, having another activity to respond to voice commands, should've worked.
The only thing that you might have missed is to put the action android.intent.action.MAIN in the second activity.

Android Things intent for boot

When I reboot after deploying an application to Android Things the application doesn't start.
Is there a specific intent to start an application on boot?
If your Android Things device has multiple applications installed that all have this intent filter in the manifest:
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
( < DP8 used to need IOT_LAUNCHER that has been deprecated)
Then your application will not start by default, instead the Intent Chooser dialog will be shown and the system will wait for user input to select which app to run. (This happens wether or not you have an actual display plugged in. If you don't have a display it might appear as tho the device is just hanging.)
I wrote a script here: https://gist.github.com/blundell/7c0c3bb17898b28fe8122b0dc230af50 that will uninstall all applications that have the above Intent Filter so that you can start again and only have 1 application installed - therefore this application will start on boot.
With the latest version of AndroidThings the IntentChooser will not be shown anymore, however the problem can persist as one of the apps installed is selected to open and the others do not.
Add to AndroidManifest.xml
Developer Preview 0.8 and greater (New Style)
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
Before Developer Preview 0.8 (Old Style)
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.IOT_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
See Android Things Release Candidate 16 April 2018
The following intent-filter needs to be added to AndroidManifest.xml
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.IOT_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
Have you tried their demo app? Try out this first before writing your own app. This should work as expected. Later change as you want.
Just don't remove this part from the AndroidManifest.xml of your code.
<!-- Launch activity automatically on boot -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.IOT_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
To give Android Things support in app, We need to define main entry point for the system to automatically launch on boot.
While adding an intent filter for an activity must contain an intent filter that includes both CATEGORY_DEFAULT and IOT_LAUNCHER.
<application
android:label="#string/app_name">
<activity android:name=".HomeActivity">
<!-- Launch activity as default from Android Studio -->
<!-- For ease of development, this same activity should include a CATEGORY_LAUNCHER intent filter so Android Studio can launch it as the default activity when deploying or debugging. -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- Add below intent filter which enable android things support for app -->
<!-- Launch activity automatically on boot -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.IOT_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Check Home activity support for Android Things in android app.
Answer from user fishjd, help me. If that didn't work, try deleting app using adb, and reinstalling it
adb uninstall <packet>

Android App name is not displayed in the multitasking screen

I've developed a simple NFC application that reads and displays the data(NDEF Records) present in the NFC tag. I modified the Manifest file so that whenever a tag gets tapped, my app gets opened.
Now the problem is when I manually open the app and check the multitasking screen, it displays my app name i.e NFCReader but when the app gets opened itself when a tag comes in contact with the device, my app gets opened but when I check the multitasking screen, it doesn't display my app name. Instead it displays NFC Service. What should I do to overcome this issue?
I assume that you have set your activity declaration, in your manifest, to something like this:
<activity
android:name=".packagename.MainActivity"
android:alwaysRetainTaskState="true"
android:launchMode="singleTask"
android:theme="#style/AppTheme.Main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="domain.com"
android:scheme="http" />
</intent-filter>
</activity>
I think the answer to your question is the following line of code that you forgot to add:
android:launchMode="singleTask"
I invite you to read about launch modes here and here.
Please note: This answer is based on the use of Reader mode API, otherwise check this answer.
Hope this helps!

Android hidden application

I'm writing a (legal) spy program. I want to make this program hidden on the launcher (so that no icon is shown). I tried to remove <category android:name="android.intent.category.LAUNCHER" /> line from AndroidManifest.xml, but then the user can't launch the application in first start mode (configuration). Who have any ideas ?
How can I do it?
You need to make your app into a service. Here is Androids take on creating services components:
http://developer.android.com/guide/components/services.html
Found this as well on MobiWare:
When you want to track the usage of the mobile or gather some data without user knowledge,this might help you.
Step1: Create an application with No icon.
Normally,an activity is declared as follows in manifest.
<activity
android:label="#string/app_name"
android:name="org.security.tracker.Tracker-activity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Remove the Category TAG ,you wont get app icon anymore.
Now,you don't need activity anymore. so remove this segment.
BUt you might think,how the app will run without any trigger or what is the starting point of the application.
This is the solution.
<!-- Start the Service if applicable on boot -->
<receiver android:name="org.security.tracker.ServiceStarter" >
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
This triggers your code that written in Receiver there by you can run service to implement your thoughts.
<service android:name="org.security.tracker.serviceCode" />
You need to add this permission,
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Your code runs when the phone reboots only.
Step 2. Write your code
On Reboot,the recevier will fire ,there you can start your service.
class ServiceStarter extends BroadcastReceiver {
#Override
public void onReceive(Context _context, Intent _intent) {
Intent i = new Intent("com.prac.test.MyPersistingService");
i.setClass(_context, ServiceCode.class);
_context.startService(i);
}
}
You can remove the <category android:name="android.intent.category.LAUNCHER"/> from the AndroidManifest.xml file.
But remember to add <category android:name="android.intent.category.LEANBACK_LAUNCHER"/> so that Android studio will be able to compile your app (yet hidden from launcher) :) :D
remove
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
from the manifest file
The app can be hidden programmatically, Below is the code which will hide the app from the Launcher menu. this works fine android 10 as well
// App will be hidden when this method will be called from menu
private fun hideApp() {
val packageManager =packageManager
val name =ComponentName(this,MainActivity::class.java)
packageManager.setComponentEnabledSetting(name,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP)
Log.d("TAG", "hideApp: success")
}
For more information, you can check this link https://developer.android.com/reference/android/content/pm/PackageManager#setComponentEnabledSetting(android.content.ComponentName,%20int,%20int)

How to tag video player for opening video files from other apps?

I wrote a vidoeplayer and was wondering... when you click a video file from some other app, say a file browser, a list of apps appear, that can open this video file.
How do I make my player also appear on that list?
Thanks!
You have to register the Intent you want in your activity.
From API 15, you need to add CATEGORY_APP_MUSIC to your app manifest, possibly under ACTION_MAIN intent filter.
If you want to target down to API 8, also use INTENT_ACTION_MUSIC_PLAYER in the intent filter.
Here's a sample manifest part..
<activity android:name=".ui.MyActivity" >
<intent-filter>
<category android:name="android.intent.action.MAIN" /> <!-- If this is the main activity -->
<action android:name="android.intent.action.MUSIC_PLAYER" />
<action android:name="android.intent.category.APP_MUSIC" />
<data android:mimeType="video/*" /> <!-- To make sure we let Android know that we accept video -->
</intent-filter>
</activity>
Hope this helps.

Categories

Resources