Android multiple services matching intent - android

In Android, if I send an intent from my app using implicit intent, and there are two services which have a matching intent filter, which service will get invoked ?
I know for activities, the user will be asked a choice through a pop up window. How does Android make the decision in case of services ?
Thanks.

Quoting myself:
In addition, what happens if there are two (or more) services installed on the device that claim to support the same <intent-filter>, but have different package names? You might think that this would fail on install, as happens with providers with duplicate authorities. Alas, it does not. Instead, once again, the first one in “wins”.
So, if we have BadService and GoodService, both responding to the same <intent-filter>, and a client app tries to communicate to GoodService via the explicit Intent matching that <intent-filter>, it might actually be communicating with BadService, simply because BadService was installed first. The user is oblivious to this.
Moral of this story: don't use implicit Intents with services.

They will look to the priority :
<intent-filter android:icon="drawable resource"
android:label="string resource"
android:priority="integer" >
. . .
</intent-filter>

I arrived here because I am using Braze (was appboy) to deliver FCM messages to my app using their AppboyFirebaseMessagingService class. I now need to deliver custom events coming from my backend to my app. At first I thought I should build a new service and add it to the AndroidManifest next to the Braze service. Turns out that won't work as described by #CommonsWare.
What does work is to make a new MyFirebaseMessagingService class that is a subclass of AppboyFirebaseMessagingService and mention the MyFirebaseMessagingService in the AndroidManifest. This way both classes will see all messages. I'll have to add logic to filter for just my messages and ignore the Braze messages.

Related

Determine intent filters associated with a service

We removed an SDK from our Android app (all class and method references) and pushed it to the play store, but forgot to remove the declaration for it from the manifest:
<service android:name="com.radiumone.emitter.location.LocationService"/>
Today we have one crash through Crittercism that didn't happen in regression testing in which an attempt is made to load this service. My research suggests the only way this could happen is if the service is exported by default, and that can only happen if the service contains intent-filters. Is this true, and if so, how do I find the intent-filters associated with a service? I can't find any contained in my AndroidManifest.xml; where else should I look?
Is this true
In an unmodified application, yes.
how do I find the intent-filters associated with a service?
They would be child elements of the <service> element in your manifest. If your element is as it is shown in the question, you have no <intent-filter> elements, and your service is not exported.
I can't find any contained in my AndroidManifest.xml; where else should I look?
There is no place else to look.
Today we have one crash through Crittercism that didn't happen in regression testing in which an attempt is made to load this service.
You may wish to ask a separate Stack Overflow question where you provide more details about the crash, to try to get our help in confirming your belief that somebody else is attempting to start or bind to your service. Perhaps you are misinterpreting the results.

Permissions for a WearableListenerService

I've implemented a WearableListenerService in both my main app and the companion Wear app. In the manifests, the service needs to be declared as android:exported="true" (or not declared at all and left to default to true) since it's started by Google Play Services. An exported service with no permissions can be called by any app on the system, but I can't find the correct permission to add to the service declaration to secure it. I've looked through the permissions on both the phone and the Wear device with pm list permissions but I don't see anything that looks like what I need.
Is there a permission that I can/should add to secure my services?
If not, is it a good idea to manually secure the service by checking the package name of the caller?
The best way to see how to implement a WearableListenerService on Android Wear is to look at one of the existing samples provided by the SDK. If you look at the DataLayer sample included at $SDK/samples/android-20/wearable/DataLayer it has a full implementation of what you are wanting to do.
If you look in the AndroidManifest.xml for the wearable side, you can see it has the following:
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<service
android:name=".DataLayerListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
For your security concerns ... When we declare a service in manifest and add a filter to it, it automatically becomes an exported service. So in general, other apps can bind to that service. In case of WearableListenerService, there is a security check that happens in the framework to make sure that the agent binding to that is Google Play Services so no one else can really bind to that service, unless the app developer exposes other intent filters in which case the intention is for others to access it.
So if you implement your code in the same way as the Wear SDK samples, your app should be secure and you do not need to worry about any extra permissions, etc.
Is there a permission that I can/should add to secure my services?
If not, is it a good idea to manually secure the service by checking the package name of the caller?
You don't need to worry about securing your WearableListenerService implementation with permissions or caller package checks. As #Wayne pointed in his answer: there is a security check that happens in the framework. This check is done in the WearableListenerService base class. You can find further security analysis of the Wearable SDK in the following article:
https://labs.mwrinfosecurity.com/blog/android-wear-security-analysis. Here is the quote from it:
The method pr() first checks if com.google.android.gms is Google
signed and then calls cU() to check if the calling process UID is for
the package com.google.android.gms (the Google Play Service package).
If the class is further decompiled, it can be seen that this security
check happens in each method exposed in WearableListenerService.
Unfortunately currently Lint checker produces false positive warning for the wearable listener service declaration whenever it doesn't contain BIND_LISTENER filter (which inclusion produces other warning since it's now deprecated and should be avoided):
Exported services should define a permission that an entity must have in order to launch the service or bind to it. Without this, any application can use this service.
This is certainly a bug in the security detector code (it just wasn't updated when BIND_LISTENER intent became deprecated). I've opened an issue regarding this on the Android bug tracker. Meanwhile to get rid of the warning one needs to add tools:ignore="ExportedService" to its wearable listener service declaration.

how to prevent other app to bind to my service

I can find the way to setup Bound Services in android AIP Guides!
This demo allows any app to bind to it.But what I want is only my apk can communicate with the service I code.Is there any way to do it? How to?
Thanks!
Services are not exported by default, meaning they can only be called/bound by your application. Unless you add android:exported="true" to your service's manifest entry, only your app will be able to bind to the service.
Service.onBind() receives intent that was used to bind to your service. One approach is to add an permission extra to the aforementioned intent, check for its value in Service.onBind(), and deny any bind requests in case of invalid permission value.

How to get all intent filters for application (with root)

I am working on a system application and I need to know programmatically what intents an application is capable of handling. I have seen other questions related to this, but none of them seem to have an answer but also do not seem to be concerned with system privileges.
PackageManager only seems to provide methods to query activities for a given intent. I can not find a way to get intents for a given activity.
For example, if I have an activity which has intent filters defined as such:
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.USER_PRESENT"/>
</intent-filter>
And I know the activities class name and package name, I would like to find out from the package manager (or any other source) what intents it can handle (in this case, BOOT_COMPLETED and USER_PRESENT).
Good question. I don't think it's possible to find out the intents that an app can handle. Some standard activity actions and broadcast actions are listed at http://developer.android.com/reference/android/content/Intent.html. If you are writing your own app that's having it's own intent filters, then i don't think other apps will know what intents your app can handle because there is no way to publish them or announce them to the world, i believe.
But what is possible is that you can make a call for a particular intent and if that returns null, then you know for sure that there are no apps on the device that can handle that particular intent.
HTH.
So after just asking this question, I found this wonderful answer here:
Android — How to I get a list of all available intent filters?
Which leads to this 5 year old issue
So it doesn't seem like there is any way to do what I want to do at the moment. If it becomes available, I would love to know.
you could try a decompiler, such as "DexDump" (available on GooglePlay), and retrieve the "AndroidManifest.xml" of the application you want to know about.

How do you get an Android app to automatically run after download and installation?

I'm looking at the description for the Plan B app here: https://play.google.com/store/apps/details?id=com.lookout.labs.planb. It says it will start automatically after installation. How do you configure an app to do this?
Register to receive common intents. One especially suitable for your purpose is:
"android.intent.action.PACKAGE_ADDED"
You might also listen for other intents such as BOOT_COMPLETED, etc.
Edit: According to another Stack Overflow answer, You can't run your own application immediately after it's installed. You must register for other intents as I suggested. Something to note is that you app will require user permission to receive the BOOT_COMPLETED intent.
Update: As pointed out by zapl, post 4.0 you cannot do anything after install now until the user explicitly launches your app.

Categories

Resources