Are there any drawbacks to using intents as a form of message passing between two apps that I control?
I have two apks which will always exist on the device together. And, I'd like to use explicit intents to pass messages back and forth as opposed to creating and managing two separate services. Using explicit intents just seems like an easier to manage approach than services.
Communication between applications can expose certain rich, but if you really need to do this way, you can only customizing permissions that your applications will have knowledge. Then you can use BroadcasrReceiver to exchange messages securely using custom permissions.
Defining their permission:
<permission android:name="com.yourapp.PERMISSION"
android:protectionLevel="signature"
android:label="#string/permission_label"
android:description="#string/permission_desc">
</permission>
By setting
<receiver android:name=".MyReceiver"
android:permission="com.yourapp.PERMISSION">
<intent-filter>
<action android:name="com.yourapp.ACTION" />
</intent-filter>
</receiver>
In addition to these permissions you can also set them their purchases Activities, Services, ContentProvider.
Edited
Integration between existing processes in Android (Inter-Process Communication), the AIDL (Android Interface Definition Language).
AIDL is particularly useful when different applications need to
communicate among themselves to exchange information through a
well-defined interface with support for multithreading. Unlike the use
of Messenger with Bound Services with AIDL you are required to create
a file. AIDL containing the declaration of the integration interface,
which helps the client applications to know which operations are
available as well as their respective arguments and returns.
You can use intents to pass data between two apps..however I see once drawback(not too big)-you need to take care that those intents dont get exposed to others.Some malicious app can use the same intents to send bad data something similar to Denial-of-service attacks.
Just to add-if the interactions are in background you can use broadcast receivers too.
Also if the apps are always going to be together why are you not packing them as single app.If you are using parcelables, your flow might break if there are two different incompatible versions of the parcelable.(if you add a field to a object in new version of an app,the other app is still not updated,the app might crash).
Although the discussion here seems really good, at #André.C.S's suggestion, I will add my 2 cents.
Intents are a simple and effective way of passing messages between processes. One of Android's key features, the ability to call another application as a function (Activity.startActivityForResult), depends on it.
As everyone here has already pointed out, intents, whether fired at BroadcastReceivers, Services or Activities, have security issues. If you decide to use them, you will need to protect them. Andre's description of how to use permissions to do that is spot on. You must treat the method that catches the intent as if it were a web service and verify parameters, etc. accordingly.
Finally, Intents, while simple, are really not appropriate for high-bandwidth IPC. If you will be exchanging messages with the other app at a rate measured in milli-seconds, you will want to look into AIDL and a bound service. By my measurements, they are between 1 and 2 orders of magnitude faster.
Incidentally, you might consider running both applications in the same process. There are manifest application attributes that allow that. If you did that, using explicit intents would be easy and your apps would be much safer.
Edited to point out extremely embarrassing error
So, taking my own advice, I tried it. To my horror, as several people have tried to point out, explicit intents can be used across processes.
I am eating a large helping of crow, with humble pie for dessert.
An explicit intent contains a ComponentName object, not an explicit reference to a class object, as I claimed. A ComponentName contains a package name and a class name. The former is, typically, derived from the current context and thus is local to the current process. It is possible, however, to construct an intent with a package name that is an arbitrary string.
I stand corrected.
Related
I found three ways to share data across applications.
1.Content Provider
2.SharedUserId-When you declare the same shared user id for more than one application, they can reach each other's resources (data fields, views, etc.). provided applications are signed with same certificate.
3.Global Process-Put a component of one application in separate process by using android:process attribute and naming process starting with lowercase letter and another component of another appication in separate process with same name as the separate process of first application.Now these components can share data.
I am confused what to use when or which is more efficient?
I found three ways to share data across applications.
#2 and #3 are the same, insofar as #3 (shared process) requires #2 (sharedUserId).
You also missed all other forms of standard Android IPC, including:
starting activities
starting services
binding to services
sending broadcasts
I am confused what to use when
Ordinary app developers should use #1 (ContentProvider) or one of the other standard Android IPC mechanisms that I outlined above. You have no control over when users update apps, and using formal IPC enforces a clear separation between the apps, forcing you to think through things like API contracts, API versioning, and related concerns.
sharedUserId and shared processes are really there for device manufacturers, where apps are pre-installed and then updated in unison via a firmware update. Personally, I recommend to device manufacturers that they too use standard IPC, for most scenarios. For example, if App A modifies App B's files directly, how does App B find out? What if App B then overwrites App A's changes, because App B did not know about those changes? In many other areas of computer programming, we have gotten away from having multiple processes from multiple apps work with each others files directly.
which is more efficient?
Efficiency should not be an issue in this case, as you should be using any of these techniques infrequently. If you have two apps that need to communicate with each other frequently, then you really have one app, and you should implement it that way.
I've written a library starting a service in the background. It runs perfectly in all applications.
In order to reduce the RAM usage, I want to avoid running multiple services for different applications. Actually, it's pretty enough to use only one service to get things done.
Firstly, I've written an AIDL file to make IPC between applications/libraries. Defined the service as exported/enabled with signature permission. Since all applications are the exactly the same service, it's not possible to check if any one is up or down. While binding the service to check the condition of the service, it always creates and destroys the own service because of the nature of BIND_AUTO_CREATE flag. That's why not possible to get any kind of info from the exported service if it's really up and running.
Then, I tried to define a Content Provider to the manifest of the library. My aim is to share the service info through it. It's really good mechanism to communicate between exported service and application main process. But it is not usable for multiple instances. Because applications which gets the content provider info from the library use the same authority and so it's not possible to install the second one. It gives an DUPLICATE_PROVIDER_AUTHORITY error.
What's your suggestion about the issue? Is there any option to create a master/slave mechanism? Is it possible to make the service singleton for the application uses the library project?
P.S: Tried broadcast and shared preferences techniques. But they're not effective to listen the callback from the exported service.
You need to put the Service in an APK of its own. It needs to have its own unique package name (in the manifest) which is different from the package names of any of the applications that use it. This is how you make the Service behave as a singleton. Now you can use AIDL and bind to the Service in order to have two-way communication.
Note that in more recent versions of Android, it has become necessary to start a Service using an explicit Intent (ie: the Component must be explicitly specified, you can't use just an ACTION).
Alternative 1:
If the use case permits I think you should not implement the Service.
Make your client implement a service a call your library code. This
is how MediaPlayer and other default android APIs work.
Alternative 2:
Host the service in a separate app..and download the app when the
first call is made from any client. From here onwards there will be
single service handling all the client request.This is how some APIs like adobe
air/ MDM solutions from Airwatch works.
There is no good way you can control a component which is running in other app,unless using broadcast receivers and all.
My Application has an Activity for the UI and a Service for background polling fun. Seems like standard fare.
Can AlarmManager trigger the Service Intent without Activity OnCreate being called?
Is there any benefit to putting the Activity & Service into different Applications? Would this create 2 apk's and make it impossible to put into Market as one app? Can you put 2 applications into one manifest somehow?
Regarding communication between the two:
-If Activity & Service are part of the same Application - can't I just store common objects (like User object) at the Application scope for the 2 to share?
-It seems like I don't even need to bother with AIDL - the two could just have weak references to each other at the Application scope as well - and they can call methods on each other that way? Or should they pub/sub each other with some kind of Observer Pattern or BroadcastListener thing?
Can AlarmManager trigger the Service Intent without Activity OnCreate being called?
Yes.
Is there any benefit to putting the Activity & Service into different Applications?
IMHO, no.
Would this create 2 apk's and make it impossible to put into Market as one app?
Yes.
Can you put 2 applications into one manifest somehow?
From a pure XML standpoint, there is room in the manifest for more than one <application> element. However, AFAIK, only one is supported.
If Activity & Service are part of the same Application - can't I just store common objects (like User object) at the Application scope for the 2 to share?
For very quick things, yes. However, bear in mind that your service may get shut down (by Android, by user, etc.), after which your process may get terminated, and your Application object goes poof. I'd use this for light caching only.
It seems like I don't even need to bother with AIDL
Correct -- that is only needed for inter-process service binding.
the two could just have weak references to each other at the Application scope as well
I wouldn't do that in a million years. Please use the platform responsibly. There are plenty of ways for activities and services to communicate yet remain loosely coupled (or, in the case of the local binding pattern, tightly-coupled in an Android-aware fashion).
Or should they pub/sub each other with some kind of Observer Pattern or BroadcastListener thing?
Something along those lines would be preferable. While the activity and the service may be co-resident in the same process at the same time, they are not designed to be directly linked to one another.
I'm writing an app, that has a somewhat modular system. It has a core app, and some apps, that consist of a single Service, that implements the desired interface. I followed the guide to create the IPC communication. But now I need to get all the services, installed on the system, that my core app can wotk with. How do I do this? I mean, is there any way to mark my Service apps with some kind of a tag, and then filter results, presented by the PackageManager#getInstalledPackages() based on that tag value? What's the common practice of doing so?
Create a custom Intent to which your activities will respond. You can then use PackageManager.queryIntentServices to get your list of matching services. You can get the package info, etc. from the information embedded in the ResolveInfos.
Ideally you'd actually use these intents for invoking the services, but you could always just use them as identification tags and fall back on the binding mechanism you were using before.
I've been working with Android for well over a year now, but I still have trouble determining when different types of messaging/communication between processes/threads should be used. I'm mainly talking about broadcasting Intents, using AIDL for services, using Handlers to send messages and socket communication.
Many of these tools can be used to accomplish similar tasks, but which is better suited to particular situations?
This is a pretty open ended question, but let me take a shot at describing how I see the intra/inter application communication working best.
One of the key aspects of Android messaging is the concept of all application components being loosely bound. Because all applications run in a separate process, and one 'app' may actually consist of several applications (responsible for providing different Activities or Services), the messaging techniques are all based around the idea of marshaling messages across process boundaries.
Intents
The preferred technique for messaging, always try to use an Intent whenever possible. It is the most 'native' way to transfer messages within Android.
Advantages
Using Intents for messaging maintains the loose binding of application components, letting you transfer messages seamlessly between several applications. Intents are used heavily within the core system to start Activities and Services, and to broadcast and receive system events.
Using extras Bundles you can include key/value pairs of primitives as payload data within Intents to easily pass information from one application component to another - even if those components are running in different processes.
Disadvantages
Because Intents are designed to go between processes, the extras payload only supports primitive types. If you need to send an object using an Intent you'll need to deconstruct it into primitives at one end and reconstruct it at the other.
Application Class
If you only want to communicate within a single application running in a single process this is a handy solution.
Advantages
By extending the Application class (and implementing it as a Singleton) you get an object that will exist whenever any of your application components exist, providing a centralized place to store and transfer complex object data between application components.
Disadvantages
This technique limits your messaging to components within a single application.
Service Binding, IPC, and AIDL
Binding to a service lets you access its methods and exchange objects with it. AIDL is a way of defining how to serialize an object into OS primitives so that it can be marshalled across process boundaries if the Service you're binding to is running in a separate application.
Advantages
When you bind to a Service you have access to it as though it was an object within the calling class. That means you can execute methods on the Service and exchange rich objects with it.
Note that if you're binding to a Service in a different application process you'll need to create the AIDL definitions that tell Android how to seralize / deserialize any objects you want to pass between applications.
Disadvantages
Creating the AIDL classes for IPC is a bit of extra work, and binding creates additional dependencies between Services and Activities which can make it harder for the kernel to clean up resources when other applications are being starved.
Marshelling messages across process boundaries is expensive though. So if you're not executing methods on a Service, using binding and IPC is probably overkill - see if you can achieve the same thing using Intents.
Sockets
If you're resorting to sockets to communicate within or between applications running on a single device, it's either because there's no other way or you've missed a trick somewhere. If your messages are leaving the device then sockets are a good, fast, alternative. If you're staying on the device chances are Intents or IPC is going to be a better option.
It all depends on the use case and kind of your application. If the application is running all the time better to go with AIDL approach as it is most secure way to communicate. If application need not run all the time, then you can go with either broadcast intent or pending intent approach to communicate between applications.
My 2 cents
I have not used local sockets.
Seems like overkill since you have to
generate and parse the data.
Intents are for either things that
other apps might want to do (launch
me in a compose window or to pick
something out)
AIDL/Parcels/Handlers for having a
GUI talk to a headless process that
is running constantly. Depending on
the app a lot of the actual data
transfer might happen using a content
provider but I tend to have some data
that needs to be transferred outside
of that channel.
This is a good article I found helpful in trying to find a substitute for Cocoa's NSUserDefaults class:
http://developer.android.com/guide/appendix/faq/framework.html