I created a service that is bound by other applications through AIDL, and I add it to the manifest as follows:
<service android:name=".MyService">
<intent-filter>
<action android:name="org.example.android.myservicedemo.IService" />
</intent-filter>
</service>
where IService is the AIDL interface.
In this way, Eclipse show me the warning Exported service does not require permission. If I remove the intent-filter, the warning disappear, but obviously the applications are unable to bind to the service.
What does this warning mean?
I had the same issue when I updated SDK to version 20. I removed it adding android:exported property android:exported="false" like so:
<service android:name=".MyService"
android:exported="false">
<intent-filter>
<action android:name="org.example.android.myservicedemo.IService" />
</intent-filter>
</service>
See this doc
If you want to restrict you activity usage to your own application, then you should add exported=false to your activity's manifest statement.
If you want to allow other applications to use it (explicitly through its class name or, better, by using an intent with a data type or action) then you have two choices :
restrict those applications by using a permission
allow all applications to use it, then you can add tools:ignore="ExportedActivity" to your activity's manifest statement.
--
Same reasonning applies to a service, with tools:ignore="ExportedService" and content providers with tools:ignore="ExportedContentProvider".
As Jens said, "It means that other (arbitrary) applications the user has on his phone can bind to your Service and call whatever method they please that is exposed through your AIDL interface."
Related
Our android system supports multiple user feature. I'd like to start my server from other apps, like app1, app2 with command startService(intent).
Per google's document at https://source.android.com/devices/tech/admin/multiuser-apps.html.
I need to set android:singleUser="true" to make sure my service only running in one instance in multiple user android system. but when I startservice in other app, I got below exception:
Not allowed to start service Intent { act=com.xx.xxx.action.Start pkg=com.xx.xxx (has extras) } without permission not exported from uid 1000
it seemed android:exported="true" was disabled by android:singleUser="true". if I didn't add android:singleUser="true", it worked fine, but there are more than one instance of my service running in background.
My question is how can I make my service only running in one single instance with startService(intent) from other apps?
My Manifest.xml is configured as below:
<application
android:name=".App"
android:label="#string/app_name"
android:directBootAware="true"
android:multiprocess="false"
android:persistent="true">
<service
android:name=".MyService"
android:singleUser="true"
android:exported="true"
android:permission="com.xx.permission.xx">
<intent-filter>
<action android:name="com.xx.xx.action.xx" />
</intent-filter>
</service>
</Application>
Thanks so much.
Yes, Need to declare app as system app. also use bindServiceAsUser() with System UserHandler.
As the documentation you linked says: "only system apps can currently use this feature". If it's feasible for your product, make your app a system app.
You need the INTERACT_ACROSS_USERS_FULL permission at allow binding to a single instance service from a non primary user. It is a signature only permission so your app needs to be signed with the platform keys.
make android:exported and android:singleUser to true
add permission INTERACT_ACROSS_USERS
make sure you app is privileged. so you should make your app system signature
In my Android application in manifest file i have following receiver and service declaration:
<receiver
android:name="com.google.android.gms.analytics.AnalyticsReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.gms.analytics.ANALYTICS_DISPATCH" />
</intent-filter>
</receiver>
<service
android:name="com.google.android.gms.analytics.AnalyticsService"
android:enabled="true"
android:exported="false" />
To be honest it's quite old app and I don't remember why I've put that there. It was probably taken from Google Analytics docs. But now I can't find any up-to-date information about it.
What is more Android Studio shows me warning with that receiver:
Receiver does not require permission
Exported receivers (receivers
which either set exported=true or contain an intent-filter and do not
specify exported=false) should define a permission that an entity must
have in order to launch the receiver or bind to it. Without this, any
application can use this receiver.
Do I really need that receiver and service in my code? What is this responsible for? Is it still actual?
If you are using the latest version of Google Analytics, no, you do not need to manually specify the service and receiver in your manifest file.
Here is the Google Analytics getting start guide for Android. Note that if you are upgrading from a significantly older version, you may have additional work to perform elsewhere to upgrade. You should read through the entire guide to ensure that your app is still configured properly.
My receiver is declared in this way:
<receiver android:name=".receiverName"
android:enabled="true"/>
And here's my service:
<service android:name=".serviceName"
android:enabled="true"/>
But I was wondering: to make them work must I add an <intent-filter> in each one?
to make them work must I add an <intent-filter> in each one?
That depends on what you are using them for.
An <intent-filter> is to allow other apps, or sometimes the operating system, to communicate with your components. That is why you have an <activity> with an <intent-filter> for the MAIN action and the LAUNCHER category — home screen launchers know to look for those and give the user the ability to display those activities.
So, if your plan is to use the service purely within your own app, you do not need an <intent-filter>. The same thing holds true for your receiver. If, on the other hand, you are expecting other apps to start the service, bind to the service, or send you a broadcast, then you will want an <intent-filter>.
Background
I'm trying to develop a really simple in call app to replace the stock version. Basically, I just want to answer incoming calls and present the user with a really simple customized UI. There is no need for outgoing calls or any fancy stuff.
Searching the web I've found package android.telecom.incallservice (available in API 23). This service is implemented by any app that wishes to provide the user-interface for managing phone calls.
It seems promising but I'm having trouble getting it to work. I've created simple service extending InCallService and declared it in my manifest as described by the docs. However, I would expect to be able to change the default phone app in the settings to my own, but I can only find the stock phone app.
Code
This is the manifest declaration from the docs. I've replaced BIND_IN_CALL_SERVICE with BIND_INCALL_SERVICE since I guess this is a typo.
<service android:name="your.package.YourInCallServiceImplementation" android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
</service>
Questions
Is it even possible for third-party app to replace the default in call app?
Are there any sample implementations using this API out there I may use as a reference? I've found the google implementation, but this is a system app which makes use of some permissions that are not available for other apps (ex: android.permission.MODIFY_PHONE_STATE).
Am I correct in the assumption that after providing a correct InCallService manifest registration and a stub implementation I could expect to find my app under Default Apps -> Phone? Do I need to declare something else?
Thanks.
Is it even possible for third-party app to replace the default in call app?
Yes, starting with API 23 it is possible.
Are there any sample implementations using this API out there I may use as a reference? I've found the google implementation, but this is a system app which makes use of some permissions that are not available for other apps (ex: android.permission.MODIFY_PHONE_STATE).
The only one I'm aware of, is the sample I created https://github.com/arekolek/simple-phone that was already mentioned in the other answer as well.
Am I correct in the assumption that after providing a correct InCallService manifest registration and a stub implementation I could expect to find my app under Default Apps -> Phone? Do I need to declare something else?
Actually, no.
Like mentioned in another answer on the topic, you don't need InCallService at all to appear on that list.
What you need though, is to register an activity with two intent filters, one with a tel Uri scheme, and one with an empty scheme (having just one of them is not enough):
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DIAL" />
</intent-filter>
It is vaguely mentioned in the docs, and stated explicitly in AOSP code.
That is enough to appear on that list. Only then, to provide the UI for the call, will you actually need the InCallService.
According to the docs and as you comment yourself, you need to add this in your manifest:
<service android:name="your.package.YourInCallServiceImplementation"
android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
</service>
android:name must be replaced by the class that implements this service.
<activity android:name="your.package.YourDialerActivity">
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
android:name must be replaced by the class that implements the main activity for your own dialer implementation.
Here you can find more information about this:
https://developer.android.com/guide/topics/connectivity/telecom/selfManaged
And here's a sample project that you can use as a guide:
https://github.com/arekolek/simple-phone
And this: https://stackoverflow.com/a/49835987/1916449
I am tracking my installs with two methods like you can see here in my manifest:
<receiver
android:name="com.google.android.gms.tagmanager.InstallReferrerReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
<receiver
android:name=".tracking.ReferralReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
The second receiver generates a lint warning the first not. Does that mean that Google knows that for their InstallReferrerReceiver and know that it is safe to let it exported?
PS: I know I can use tools:ignore="ExportedReceiver".
The INSTALL_REFERRER intent is broadcasted when an app is installed from the Google Play Store.
android:exported="true" means that the receiver is allowed to receive broadcast intents from other applications. You do want this, or you will not be able to receive the event which is sent by another app (the system or the Play Store app, I'm not sure).
However, if you check the documentation for android:exported, its default value is true if it has at least one <intent-filter>, otherwise it is false.
So to sum up, you need android:exported="true" to catch the event. But omitting this property would be also OK, since the default value is true for your receivers (but it's safer to have it).
About the Lint warning: It recognizes the name, and that's why it knows that the first version is safe.