(I have a remote service with an AIDL interface that is used by several client apps. I would like to add an asynchronous method to the interface for calls that take some time, but I need the solution to be secure, meaning that only my applications can communicate with the service. The client applications are signed with the same signature as the service app. Currently the apps just bind to the service and call a single interface method to perform various operations.
One option is broadcasting an Intent from the service when the operation is complete and using a BroadcastReceiver in the client application, but (Question #1) can this be done in a way that ensures only my apps can receive the Intent? setPackage() seems to do this, but I need to support Gingerbread devices, which seems to rule out that approach according to the answer here: setPackage for intent in gingerbread
So it seems I need to add a second .aidl interface with the callback interface for the service to use, implemented by the client. I have seen examples that use listeners here, but I am not sure what the difference is versus the client just passing in the second interface object as an argument (as used in the IScript / IScriptResult example from this answer: Service call backs to activity in android)
Question #2, what is the benefit of using a listener here vs. a callback method?
A callback method/listener is the right thing to do. (As CommonsWare says, it's pretty much the same thing). I would say it's much simpler than fiddling around with BroadcastReceivers, since you're already using aidl.
Something like this:
IAsyncThing.aidl:
package com.my.thingy;
import com.my.thingy.IAsyncThingListener;
interface IAsyncThing {
void doSomething(IAsyncThingListener listener);
}
IAsyncThingListener.aidl:
package com.my.thingy;
import com.my.thingy.IAsyncThingListener;
interface IAsyncThingListener {
void onAsyncThingDone(int resultCodeIfYouLike);
}
You can enforce that only your apps can bind to the service by using a signature-level permission on your service (see the note on 'service permissions' here: http://developer.android.com/guide/topics/security/permissions.html). Specifically:
Declare a permission in your service's AndroidManifest.xml. Ensure it is signature level.
Add that permission in your service tag
In all the other apps, use uses-permission to use it.
A couple of other things to bear in mind:
In the caller, you'll need to subclass IAsyncThingListener.Stub. Your calling application code may already be subclassing something else, so that means you'd have to use an extra (probably inner) class to receive the completion notification. I mention this only because this might be the answer to question #2 - which I don't fully understand.
If the service is potentially in different processes from the caller, each should register for death notification of the other using IBinder.linkToDeath.
Related
I have a singleton class with the "block/allow logic" for my VPN tunnel. Packets sent into the tunnel are not emitted, applications are allowed to bypass based on an allowance list, therefore it can behave as a simple implementation of a firewall.
What I want to do is, when I change the Set<String> of blocked application packagenames, I would like the service thread to run vpnservice.builder.establish() again, using this blocked application set.
An obvious choice for this - in case an "ordinary" foreground service if the service extends LifecycleService, as shown here. However, my service has to extend android.net.VpnService, which does not implement LifecycleOwner. A possible implementation (with some modifications needed) is shown here.
My questions are:
Is there a better, cleaner, more elegant way for my VPN service to observe changes in my blockedPackageName Collection, in my singleton class?
If there is not another way, will implementing LifecycleOwner work in the way I expect it (how I described it, basically)?
If(2), is it enough to add lifecycle.handleLifecycleEvent(Lifecycle.Event.XXXX); in my service's onCreate and onDestroy methods (see below)? Do these do anything apart from preventing memory leaks?
//MyVpnService class
#Override
public void onDestroy() {
Log.i(TAG, "Destroyed.");
stopVpn();
//what is the purpose of this line for my goals?
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
P.S.: I read the official documentation with regards to Lifecycle components, but I could not find enough code examples for my cases to make the matter more clear.
The best solution I find was to send a broadcast with a custom intent from the singleton class, and signing up a broadcast receiver for this intent in the vpnservice class on start.
For sending a broadcast from any class, you need context - lucky for me, I already needed context in my singleton, for which context.getApplicationContext() works fine without leaking.
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.
I'm wondering, why ActivityRecognitionClient has no method to request updates with standard java listener as parameter? More strange, that in the same time, LocationСlient has such method and it works good.
Official example for Activity Recognition looks terrible. A lot of coupled and boilerplate code. It looks like IntentService is sole variant for handling updates from ActivityRecognitionClient. It's extremely uncomfortable.
#Guys from Android Team, why it happens?
As Developer I hope to see requestActivityUpdates(interval, listener) method in next version of Google Play Services.
For now, does anyone know, is it possible to use BroadcastReceiver for handling updates from ActivityRecognitionClient?
I'm wondering, why ActivityRecognitionClient has no method to request updates with standard java listener as parameter?
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.
Beyond that, quoting the documentation for requestActivityUpdates():
A common use case is that an application wants to monitor activities in the background and perform an action when a specific activity is detected. To do this without needing a service that is always on in the background consuming resources, detected activities are delivered via an intent. The application specifies a PendingIntent callback (typically an IntentService) which will be called when activities are detected.
It looks like IntentService is sole variant for handling updates from ActivityRecognitionClient.
It's not.
For now, does anyone know, is it possible to use BroadcastReceiver for handling updates from ActivityRecognitionClient?
There are several types of PendingIntent, created from various factory methods. The sample shows using getService() to create a PendingIntent that will call startService(). You are welcome to use any other PendingIntent, such as one from getBroadcast(), which will call sendBroadcast().
I am facing this kind of problem:
I have a remote (different process) bound service which defines an IntentFilter with action String.
My client binds to it using the same action String in its bindService(..) call.
Now when I implement another service with completely different AIDL interface but with the same IntentFilter defined, install this service and remove the old one:
my client is still able to bind
my client is even able to call the desired method (say void print(Payload)) the client side does not complain, nor the server
side
My question: is there a way how to check at runtime the interface the remote service is implementing?
The only possible way I've found is to check the ComponentName in the ServiceConnection.
This has however one implication:
I will not be able to exchange the implementation of the service in the future.
Or am I missing something?
As I understand you want to do one of two things:
a) Connect to a service which implements required interface (and you don't care how the service is implemented)
In this case, you use intent filters. And in such case, each service should have different internt filter. Generally speaking, when you are defining the same intent filter you are saying that these two services are compatible (and they aren't, because of different AIDL's).
So, you should have different intent filters here.
b) Connect to a very particular service (It's not substitutable by any other service).
In such case, when you do bindService, you should specify expilicit component name in the intent, which you pass to bindService.
I know that an activity can communicate with a local service using the IBinder interface; I am trying to find a way for communication between two services.
Specifically, I have my main service starting an IntentService to handle file uploads. I want this IntentService to inform back to the main service once it is done uploading, and before it dies.
Any ideas about how this would happen?
You have to use BroadcastReceiver to receive intents, and when you want to communicate simply make an Intent with appropriate values.
This way you should be able to make a 2-way communication between any component.
In Android, there is a special way of completing tasks like yours. Look at AIDL (it's not well documented in official docs, but there are some extra sources on the web). This is a way of implementing two-way communication between any components placed in separate processes. In comparison to BroadcastReceivers, using this you'd get direct calls and callbacks, that will be less dirty than relying on something would come from somewhere in BroadcastReceiver.
To reach the needed effect, you'll have to define an interface for a callback and an interface for performing actions (with a callback supplied, or register/unregister methods). Than, after you received some command using the second interface, you should perform the job and post back the result through callback. To reach the asynchronous completion add a key work "oneway" before method signature (return type). To separate in and out params (if you need it), use "in", "out" and "inout" keywords near params.
As it comes to restrictions, only primitives, arrays and parcelables (and parcelable arrays) might be transferred between processes.
To control your callbacks lifecycle and operations atomicity, use RemoteCallbacksList for storing registered callbacks and notifying recipients using the duplicate of your list got from beginBroadcast.
If you have any troubles, you're free to ask here.