binding Service using AIDL vs binding using action? - android

According documentaion on Developer's forum, this is how I can bind my service using AIDL:
/* Establish a couple connections with the service, binding by interface names.This allows other applications to be installed that replace the remote service by implementingthe same interface.*/
bindService(new Intent(IRemoteService.class.getName()),mConnection, Context.BIND_AUTO_CREATE);
Now I have application A, which has Service class and AIDL interfaces.
And I have application B through which I wish to access Service class of Application A , using methods exposed ny AIDL in application A.
So I have created exactly same pacakge for AIDLs inside application B and have pasted AIDLs from App A.
But when I'm trying to bind service using above mechanism mentioned in documentation it tells me:
Unable to start service Intent { act com.example.service.MyService
} U=0: not found
In App A Service
exported="true".
Now Insted of this approach I added Intent Filter to my service in app A and tried to specify explicit intent using
intent.setClassName(String packageName, String className)
And now it is working!
So is there something I missed out while referring original documentation ? when that approached will be used?

After discusing with pskink in above comments I got the answer for this question. The anser lies in my new implementation.
Check the constructor for Intent used in above example in documentation. It tells that IRemoteService.class.getName() passed inside Intent constructor is nothing but an 'Action'. So if I want my code should be able to find the service I wish to bind then the String returned by IRemoteService.class.getName() should be mentioned as an Action inside intent filter for my service.
Two points to be considered here will be:
This won't follow standard naming convention for actions.
Starting service using Implicit intent gives waring as implicit intents with startService are not safe for obvious reason that if the same Action is used by multiple services then it will be a problem.

Related

Why use an intent to create an activity?

Folks,
This is a newbie question. I have read a few articles on intents but I am a bit confused on what the main idea behind an intent is when it comes to starting an activity. If I know that I have to create and show an activity, why can't I do something as simple as the following?
MyActivity a = new MyActivity();
a.show();
Thank you in advance for your help.
Regards,
Peter
A activity has a lifecycle and this is managed by the framework. I would say to get an extra hold of the life cycle, Android introduced a set of rules to launch a activity (startActivity). To add-on, Intent is not only to launch your activities. Intents can be used to launch other thirdparty or inbuild views/service/targets. This could be another reason why they introduced intent. Just my two cents.
Intents communicate between activities in an app and between apps.
Your example:
MyActivity a = new MyActivity();
a.show();
assumes that Android is just objects, so that instantiating an Activity and somehow showing it will make it appear. This isn't the case, though; the Android system does a lot more. The activities in your app are "floating", as it were, within the Android framework. Most of what makes an Activity tick is invisible to you. In particular, the Android-specific thread model and the way that the system communicates with Android components (like Activities) is invisible.
I won't go into most of this, but an added advantage of Intents for starting an Activity is that an Activity can add itself as a candidate for Intents that want to do a specific task. Suppose I have an app that edits images. I can easily make myself discoverable by filtering for Intents that have the action ACTION_EDIT for MIME types that I can handle. This is exactly how Android implements the list of apps that appear when you try do to something with a file.
An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.
An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed.
click here for more information.
in basic words Intent is your ears regards to Android device. Your activity can talk to Android through Intent and listen on "any change" on your phone.
It's like "grandmother" that sits outdoors next to entrance of big house and listens about all talks, gossips and notify you about.

How to get class name of the Activity which is bound to a Service?

I would like to get the class name (*.class) of an Activity which is bound to my local Service. Is there any native method which i could use to achieve this?
I tried to get that information out of the Intent I use to bind to the Service. But it seems there is no function in Intents for this.
If I wasn't blind, additionally I would like to know why there's no information about the calling Activity in an Intent?
Is there any native method which i could use to achieve this?
No, in large part because the class in question may not exist in your app, and may not even be a class.
You are welcome to package whatever identifying information you would like in the Intent, such as via an extra.
Also, if you are allowing third parties to bind to this service, you can use methods like getCallingUid() on your Binder to find out information regarding the process that bound to you.
additionally I would like to know why there's no information about the calling Activity in an Intent?
Because there is not necessarily a calling Activity. The binding engine works with C; C does not have classes, let alone activities.

Use of intents in android

I am new to android and am currently reading a book called 'Professional.Android.2.Application.Development'.
I have seen some of the code given to me to start an application development and I have noticed that most of the java code consists of intents.
I want to know why we are using intents and not events or services.
All I know about intents are that they are an abstract description of an operation to be performed.
I also want to know the importance of intents in android.
Can anyone please explain it to me as I am new and a little bit confused.
What is a Intent ?
Intent is basically a message that is passed between components (such as Activities, Services, Broadcast Receivers, and Content Providers). So, it is almost equivalent to parameters passed to API calls. The fundamental differences between API calls and intents’ way of invoking components are:
API calls are synchronous while intent-based invocations are
asynchronous.
API calls are compile time binding while intent-based calls are
run-time binding.
Of course, Intents can be made to work exactly like API calls by using what are called explicit intents, which will be explained later. But more often than not, implicit intents are the way to go and that is what is explained here.
One component that wants to invoke another has to only express its’ intent to do a job. And any other component that exists and has claimed that it can do such a job through intent-filters, is invoked by the android platform to accomplish the job. This means, both the components are not aware of each other’s existence and can still work together to give the desired result for the end-user.
This invisible connection between components is achieved through the combination of intents, intent-filters and the android platform.
This leads to huge possibilities like:
Mix and match or rather plug and play of components at runtime.
Replacing the inbuilt android applications with custom developed
applications.
Component level reuse within and across applications.
Service orientation to the most granular level, if I may say.
Here is additional description about intent, almost formal.
An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.
An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed. The primary pieces of information in an intent are:
action
The general action to be performed, such as ACTION_VIEW,
ACTION_EDIT, ACTION_MAIN, etc.
data
The data to operate on, such as a person record in the contacts
database, expressed as a Uri.
On this data structure is that the android is implemented as you read the following documentation is very helpful:
Android Intent first documentation
Android Intent second documentation
Android Intent third documentation
Android Intent Native documentation

Android remote service callbacks

(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.

Android remote bound service interface

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.

Categories

Resources