I've just started looking at Android development and I'm creating a little application which will map the "Listen to" intent to the media player power amp (recently released api).
This app has no gui it is mearly a glue between Voice control and power amp.
I can catch the intent android.media.action.MEDIA_PLAY_FROM_SEARCH and control power amp but my issue is that in order to capture android.media.action.MEDIA_PLAY_FROM_SEARCH I must declare my app as an activity and so when I use Voice Control to send the intent my app loads on the screen. I have tried to declare the app as a receiver\service but I wasn't able to get them to capture the intent.
How can the app run hidden but still capture this intent?
Thanks, Ger.
If I understand your needs correctly, you dont actually need any Activity in your app. Just a class that extends BroadcastReceiver and implements the onRecieve(Context, Intent) method of it.
And then in your manifest you can bind that receiver to specific intents you want to listen for. You app will be started without a UI with the entry point being the BroadcastReceiver class you implement.
The manifest entries will look something like:
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="com.android.music.metachanged" />
<action android:name="com.amazon.mp3.metachanged" />
<!-- <action android:name="com.amazon.mp3.playstatechanged" /> -->
<!-- <action android:name="com.android.music.playbackcomplete" />-->
<action android:name="com.android.music.playstatechanged" />
<action android:name="com.htc.music.metachanged" />
<!-- <action android:name="com.htc.music.playbackcomplete" />-->
<!-- <action android:name="com.htc.music.playstatechanged" /> -->
<action android:name="com.sec.android.app.music.metachanged" />
<action android:name="com.nullsoft.winamp.metachanged" />
<action android:name="com.nullsoft.winamp.playstatechanged" />
</intent-filter>
</receiver>
Related
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>
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)
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.
I would like to create a custom way to enter new events to the calendar.
From what I understood it should be easy by creating an app responding to the intent being sent by the calendar app. I created the following activity in my app:
<activity android:name=".Main"
android:label="#string/app_name">
<!-- for normal launch -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.ALTERNATIVE" />
<!-- also tried DEFAULT and others -->
<data android:mimeType="vnd.android.cursor.item/event" />
</intent-filter>
</activity>
But still only the builtin dialog pops up. From what I've seen in the sources of the calendar app the Intent isn't hardcoded there.
Am I missing something obvious?
After some more digging in the source code I found out that the intent target class is hardcoded. So no way of overriding the event edit activity. ;-(
I am studying RemoteService example in Android's APISample. In the
manifest file, it declares the service like this:
My question is how can I specify the service to be 'auto-start', i.e.
it gets start whenever the phone start?
<service android:name=".app.RemoteService" android:process=":remote" >
<intent-filter>
<!-- These are the interfaces supported by the service, which
you can bind to. -->
<action
android:name="com.example.android.apis.app.IRemoteService" />
<action
android:name="com.example.android.apis.app.ISecondary" />
<!-- This is an action code you can use to select the service
without explicitly supplying the implementation class. -->
<action android:name="com.example.android.apis.app.REMOTE_SERVICE" />
</intent-filter>
</service>
First, you do not want to do that.
Second, you cannot do that directly. You will need to set up a BroadcastReceiver to watch for the BOOT_COMPLETED broadcast Intent, and have that receiver start the service.