I am attempting to create a system where I have certain factory-basic functionality.
I intend 3rd party developers to be able to extend this functionality with their own code.
This is intended to work by firing off a Broadcast in certain situations where I would like a 3rd party App to receive data that it can use.
This system works, but the issue I have is that since version 3.1, the App needs to be run by a user in order to enable BroadcastReceivers. I was hoping that I could let these plugins exist without a launcher / default Activity, so that users do not need to clog their launcher with icons for plugins. Extra Activities would be defined for settings, but that would be called from my App-ecosystem.
tl;dr:
How can I enable a BroadcastReceiver in a newly installed App with as little user intervention as possible (ideally, without being located in the Launcher).
AFAIK, the Android 3.1+ limitation is for implicit Intents. Explicit Intents -- where you set the ComponentName of the receiver -- should work without issue.
So, the question now becomes: how are you really communicating with multiple plugins?
If your intention was to send a single broadcast that everyone can receive, that will trip over the Android 3.1 issue. You would need to directly invoke some component in the third-party app yourself to enable it, such as starting one of its activities from your UI via an explicit Intent, or sending a broadcast to one of its components directly via an explicit Intent.
If your intention was to send a broadcast specifically to individual plugins, then you already have some sort of way of discovering plugins (e.g., monitoring added packages and looking for a component with certain <meta-data>). In that case, you can arrange to derive the explicit Intent to use (e.g., it's the component with the <meta-data>) and should be able to broadcast to it explicitly.
If you are finding that explicit Intents do not work due to the Android 3.1 "stopped state" limitation, please let me know, as I would want to do some more investigation.
oh, I was not aware of this new security feature. What a bummer...
but now that I understood the details of the question, I'll sugest an answer, but not sure it will work, you'll have to test it for yourself.
Maybe you can on your app receive the PACKAGE_ADDED broadcast, on this Receiver, you'll query the package manager for this newly added package and check if it have an intent-filter for your broadcast, if it does, then your app should explicitly launch some component of that 3rd party app, so it can be 'initialised' by the 3.1 system restriction.
That might mean that you'll need to change the interaction with your 3rd party developers so they have a standard component your app can always fire, but it does seem like a feasible work-around.
Related
I have a device management application, which essentially runs as a service in the background from boot. I'd like to start this application immediately after installation. How do I achieve this?
You cannot do this -- there is no way to automatically start your service merely because it was installed.
The application must first be invoked by the user through some sort of activity. Or, you are going to need to hook into some relevant broadcast Intent via the manifest, so you can get control when one of those events occur and kick off your service that way. Or, you are going to need to ask the user to reboot so your BOOT_COMPLETED Intent filter can get control.
There was a hole - the Android Analytics SDK used to send an intent right after installation - but that got closed (producing lots of confusion, of course).
But the final answer, I believe, is here:
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
This seems to suggest that, as of 3.1, Google made the decision that apps are in a stopped state until the user explicitly activates them, e.g. by launching app or placing widget.
This means that the strategy of listening of a common broadcast (i.e. to get your app launched surreptitiously) won't work either.
My company has some android apps on Google Play that are occasionally targeted by malicious automated tools that scan and launch all activities in the apps. (I was able to detect these scans because they generate a lot of crash reports.) What I find most worrisome about these scans is that they are able to make explicit intent calls to non-exported activities. That is, they are calling activities have the exported attribute set to false and don't have <intent-filter>s.
Are there any additional steps I can take to prevent non-exported activities from being invoked outside my app? Are there any other security measures that I should take?
One other interesting tidbit about these scans. They all seem to be run from an emulator. Perhaps they have some mechanism to make the intents look like they are coming from inside my app. If this is the case, is there some way I can protect against that?
I'm currently working on a productivity app. One of the features includes obtaining an information about apps that are started by the user
For example I would like to obtain information that the user has started the Youtube app or listen for a specific Intent being sent without registrating a BroadcastReceiver
Is this even possible?
You cannot intercept intents sent to other apps by extending the BroadcastReceiver abstract class for obvious security reasons. So, basically, this is not allowed using conventional features (or APIs) of the Android SDK. There might be some hacks out there that could work, but they're all hacks at the end of the day which are not guaranteed to work, for example there are some articles proposing to read the system's log, it used to work in older api levels but not anymore...see some references below and make sure you read the comments as well...
Android, Detect when other apps are launched
Detect when user launches a new application on an Android device
In simple words, you can't do that. Note, that having root is a complete different story
I'm looking for technical input on Android User Profiles (both full & restricted). More specifically I would like to understand:
Whether it is possible to create an app which runs across all profiles, i.e. is not stopped, paused, restarted when switching user profile. My focus is NOT limited to activities, but I'm also interested in knowing whether a system-app/service could be created that does this and if so how.
What life-cycle is maintained for services of the non-active users. I get the impression that (at least some) services of APKs of a user get started the moment it gets activated in the lock screen (even without unlocking) and then are allowed to keep on running. But what will happen in low-memory conditions? Will a service of a non-active user also receive broadcast intents? Can such a service interact with the user and if so how?
In general: can someone point me to any technical information on the Android profiles features? There's a lot of articles on how it "looks" to the user, but I could find very little (apart from info on the pm and am command-line tools' options) on how it really works technically.
Thanks in advance!
Whether it is possible to create an app which runs across all profiles, i.e. is not stopped, paused, restarted when switching user profile. My focus is NOT limited to activities, but I'm also interested in knowing whether a system-app/service could be created that does this and if so how.
Default Android behaviors
By default, an Android application runs in a specific Android user workspace, it does not run for all Android users.
It means that when the user starts an application, it is started for the current Android user only.
When the application is launched from another Android user, Android will recreate a new instance of your application. As Android users can run in the background it means that you can have several instances of the same aplication running in parallel.
All the Android components of you application (ie. Services, Activities, BroadcastReceivers and ContentProviders) will be re-instantiated.
Most of the time it's the wanted behavior, but it can be a problem for some applications that do system-level handlings that have to be done once for the whole system, without
taking into account Android users (ex: a JobService doing some handling on Bluetooth events).
Define a singleton component/application
For each component of your app which is not an Activity, you have the possibility to specify that you want it to run as a singleton (ie. only one instance will be created for all Android users.).
To do so, the property android:singleUser=”true” must be added to the attributes of the component in the AndroidManifest.xml of the application.
<!-- Declare a singleUser service in the AndroidManifest.xml -->
<service
android:name=".MySingleUserService"
android:singleUser="true" />
Any singleUser component will always run under the system Android user (ie. the user 0) which can't be stopped by Android, even if you're application is currently running for another Android user.
To be able to use the property android:singleUser=”true”:
your app has to be a system application (either in system/app/ or system/priv-app/).
you app has to be signed by the platform certificate (by specifying LOCAL_CERTIFICATE := platform in its Android.mk).
your app must declare the use of the following permission in its AndroidManifest.xml.
<!-- Permission needed to use android:singleUser. -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
Additional remarks
If your app only contains singleUser components, the entire app will become singleUser (ie. only one instance of your app will run for the entire system).
android:singleUser=”true” forces android:exported=”false” for your component (except if your app is privleged).
If a component of your application wants to communicate with a singleUser component of the same app via Intents, the default Android APIs can't be used because Intents do not cross Android users.
In that case, you have to use the multi-user Intent exchanges dedicated APIs which are suffixed by AsUser (ex: sendBroadcastAsUser(), startServiceAsUser(), etc.) and which allow to specify the destination Android user (UserHandle.SYSTEM in that case). Note that one of the following permissions must be used:
<!-- Permission needed to send intents to components of the SAME app running in another Android user. -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
<!-- Permission needed to send intents to components of ANOTHER app running in another Android user. -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
What life-cycle is maintained for services of the non-active users. I get the impression that (at least some) services of APKs of a user get started the moment it gets activated in the lock screen (even without unlocking) and then are allowed to keep on running. But what will happen in low-memory conditions? Will a service of a non-active user also receive broadcast intents? Can such a service interact with the user and if so how?
As I've mentionned above, an Android user can continue to run in the background even if they are not the active one (at least until Android 10). If resources are low, Android can stop any Android user which is not the system user (ie. stop all their running applications). So a Service can continue to run on an Android user which is currently running in the background until the user is stopped.
As I've also mentioned above, Intents do not cross Android users. So if you have a BroadcastReceiver registered in the user 10 and that an Intent is sent from the user 11, it won't be received by your BroadcastReceiver. The only exception is if you use the AsUser Intent exchanges APIs to send it.
Also note that an Intent with the action BOOT_COMPLETED is sent whenever a new Android user is started. It is only sent to the components of the starting Android user.
Sources
Unfortunately, there is few Android online documentation about multi-user systems. Here are the only articles about it (if youd don't find answers there, I suggest you to directly look into the AOSP source code):
Building Multiuser-Aware Apps
Supporting Multiple Users
Manage multiple users
I have a device management application, which essentially runs as a service in the background from boot. I'd like to start this application immediately after installation. How do I achieve this?
You cannot do this -- there is no way to automatically start your service merely because it was installed.
The application must first be invoked by the user through some sort of activity. Or, you are going to need to hook into some relevant broadcast Intent via the manifest, so you can get control when one of those events occur and kick off your service that way. Or, you are going to need to ask the user to reboot so your BOOT_COMPLETED Intent filter can get control.
There was a hole - the Android Analytics SDK used to send an intent right after installation - but that got closed (producing lots of confusion, of course).
But the final answer, I believe, is here:
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
This seems to suggest that, as of 3.1, Google made the decision that apps are in a stopped state until the user explicitly activates them, e.g. by launching app or placing widget.
This means that the strategy of listening of a common broadcast (i.e. to get your app launched surreptitiously) won't work either.