Android Inter-process communication

Source: Internet
Author: User

If you want to do IPC communication, write a aidl interface, write a service subclass, and then implement the Aidl interface as IBinder back to the activity interface layer.
If you do not want to write the Aidl interface file, just single-threaded communication with the service we can use the Android-written Messenger class to handle, as well as the message delivered to the service to communicate.
What is aidl:
AIDL is an acronym for Android Interface Definition language, which is a description language of the Android internal process communication interface, through which we can define the communication interface between processes
Icp:interprocess communication: Internal process communication.
In Android, each application has its own process, which is not supported across process memory sharing when it is necessary to pass objects between different processes. Therefore, to pass objects, the object needs to be parsed into a data format that the operating system can understand to achieve the purpose of cross-premises object access. In Java EE, the use of RMI to pass objects by serialization. In Android, it is implemented using the Aidl (Android Interface definition Language: Interface Definition Language) approach.
1. Create a file with the extension aidl in the Java package directory of Android project. The syntax of the file is similar to Java code, but slightly different.
2. If the contents of the Aidl file are correct, ADT will automatically generate a Java interface file (*.java).
3. Create a service class (a subclass of services).
4. Implement the Java interface generated by the Aidl file.
5. Configure the Aidl service in the Androidmanifest.xml file, especially note that the attribute value Android:name in the,<action> tag is the ID of the client to reference the service, which is the parameter value of the intent class.

Aidl is an interface definition language that constrains two inter-process communication rules for the compiler to generate code that implements two interprocess communication (IPC) on Android devices. The communication information between processes is first converted to the AIDL protocol message and then sent to the other party, and the other party receives the AIDL protocol message before converting it into the corresponding object. Since the communication between the processes requires two-way conversion, Android uses the proxy class behind the two-way transformation of information, the proxy class is generated by the Android compiler, the developer is transparent.
The following four steps are generally required to implement process communication:
Suppose a application needs to communicate with the B application, invoke the download (String path) method in the B application, and the B application provides service to the a application. The following four steps are required:
First, in the B application to create the *.aidl file, the definition of aidl file and interface definition is very similar, such as: Under the Com.robert.aidl package to create a idownloadservice.aidl file, the contents are as follows:
Package com.robert.aidl;
Interface Idownloadservice {
void Download (String path);
}
Aidl uses simple syntax to declare an interface, describe its methods, and the parameters and return values of its methods. These parameters and return values can be any type, or even an interface generated by other aidl. The basic data types for the Java programming language (int, long, char, Boolean, etc.), string and Charsequence, the collection interface type list and map, do not require an import statement. If you need to use other Aidl interface types in Aidl, import is required, even under the same package structure. Aidl allows you to pass a class that implements the Parcelable interface, requiring import. It is important to note that for non-basic data types, also not string and charsequence types, directional indications are required, including in, out, and InOut, In means set by the client, out is set by the server, InOut is both configurable Aidl only supports interface methods, and static variables cannot be exposed.
When you finish creating the Aidl file, the Idownloadservice.java interface file is generated synchronously in the project's Gen directory. An abstract class of stub is generated in the interface file, including the method defined by Aidl and some other helper methods. A notable concern is Asinterface (IBinder ibinder), which returns an instance of the interface type, and for remote service invocation, the object returned to the client by the remote service is the proxy object, and the client is onserviceconnected (componentname Name, the IBinder service) method refers to the object when it cannot be strongly turned into an instance of an interface type, but instead uses Asinterface (IBinder ibinder) for type conversion.
There are a few things to keep in mind when writing Aidl files:
1. The interface name and the Aidl file name are the same.
2. Interfaces and methods without the access modifier public,private,protected and so on, nor with Final,static.
3.Aidl default supported type package session Java primitive Type (int, long, Boolean, etc.) and (String, List, Map, charsequence), the import declaration is not required when using these types. The element types in list and map must be aidl supported types. If you use a custom type as a parameter or return value, the custom type must implement the Parcelable interface.
4. Custom types and other interface types generated by Aidl in the Aidl profile, you should explicitly import even if the class and the defined package are in the same package.
5. All non-Java primitive type parameters in the Aidl file must be prefixed with an in, out, InOut flag to indicate whether the parameter is an input parameter, an output parameter, or an input/output parameter.
6.Java The original type is marked in by default and cannot be a different token.
Second, in the B application to achieve the Aidl file generation interface (this example is Idownloadservice), but not directly implement the interface, but through the inheritance of the interface stub to implement, and implement the Code of the interface method. The contents are as follows:
public class Servicebinder extends Idownloadservice.stub {
@Override
public void Download (String path) throws RemoteException {
LOG.I ("Downloadservice", Path);
}
}
Third, create a service (services) in the B application, and return the object that implements the Aidl interface in the Onbind (Intent Intent) method of the service. The contents are as follows:
public class Downloadservice extends Service {
Private Servicebinder Servicebinder = new Servicebinder ();
@Override
Public IBinder Onbind (Intent Intent) {
return servicebinder;
}
public class Servicebinder extends Idownloadservice.stub {
@Override
public void Download (String path) throws RemoteException {
LOG.I ("Downloadservice", Path);
}
}
}
Other applications can use implicit intent to access the service, the intent of the action can be customized, the Androidmanifest.xml configuration code is as follows:
<service android:name= ". Downloadservice ">
<intent-filter>
<action android:name= "Com.robert.process.aidl.DownloadService"/>
</intent-filter>
</service>
Iv. Copy the package of the Aidl file in the B application together with the Aidl file to the client a application, the Gen directory of a application generates Idownloadservice.java interface files for aidl files synchronously, and then can communicate with the B application in a application. The code is as follows:
public class Clientactivity extends Activity {
Private Idownloadservice Downloadservice;
@Override
public void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
This.bindservice (New Intent ("Com.robert.process.aidl.DownloadService"), This.serviceconnection, Bind_auto_create) ;//bind to service
}
@Override
protected void OnDestroy () {
Super.ondestroy ();
This.unbindservice (serviceconnection);//Cancellation Service
}
Private Serviceconnection serviceconnection = new Serviceconnection () {
@Override
public void onserviceconnected (componentname name, IBinder service) {
Downloadservice = IDownloadService.Stub.asInterface (service);
try {
Downloadservice.download ("http://www.itcast.cn");
} catch (RemoteException e) {
LOG.E ("Clientactivity", e.tostring ());
}
}
@Override
public void onservicedisconnected (componentname name) {
Downloadservice = null;
}
};
}
Aidl default supported type package session Java base type (int, long, Boolean, etc.) and (String, List, Map, charsequence) If you want to pass a custom type This implementation is as follows
1. Create a custom type and implement the Parcelable interface to enable it to support the Parcelable protocol. For example: Create Person.java under the Com.robert.domain package:
Package com.robert.domain;
Import Android.os.Parcel;
Import android.os.Parcelable;
public class person implements Parcelable
Private Integer ID;
private String name;
Public person () {}
Public person (Integer ID, String name) {
This.id = ID;
THIS.name = name;
}
Public Integer getId () {
return ID;
}
public void SetId (Integer id) {
This.id = ID;
}
Public String GetName () {
return name;
}
public void SetName (String name) {
THIS.name = name;
}
@Override
public int describecontents () {
return 0;
}
@Override
public void Writetoparcel (Parcel dest, int flags) {//writes data from Javanbean to Parcel
Dest.writeint (this.id);
Dest.writestring (this.name);
}
Add a static member named Creator that implements the Parcelable.creator interface
public static final parcelable.creator<person> Creator = new Parcelable.creator<person> () {
@Override
Public person Createfromparcel (Parcel source) {//reads data from Parcel, returns the person object
return new Person (Source.readint (), source.readstring ());
}
@Override
Public person[] NewArray (int size) {
return new Person[size];
}
};
}
2. Create a Aidl file under the package that contains the custom type to declare the custom type with the name of the file with the custom type.
Package com.robert.domain;
Parcelable person;
3. Using the custom type in the interface Aidl file requires an explicit import with import, this example creates a Ipersonservice.aidl file under the Com.robert.aidl package, as follows:
Package com.robert.aidl;
Import Com.robert.domain.Person;
Interface Ipersonservice {
void save (in person person);
}
4. The interface that implements the Aidl file generation (in this case, ipersonservice), but does not implement the interface directly, but is implemented by inheriting the stub of the interface and implementing the code of the interface method. The contents are as follows:
public class Servicebinder extends Ipersonservice.stub {
@Override
public void Save (person person) throws RemoteException {
LOG.I ("Personservice", Person.getid () + "=" + Person.getname ());
}
}
5. Create a service (services) that returns an object that implements the Aidl interface in the Onbind (Intent Intent) method of the service. The contents are as follows:
public class Personservice extends Service {
Private Servicebinder Servicebinder = new Servicebinder ();
@Override
Public IBinder Onbind (Intent Intent) {
return servicebinder;
}
public class Servicebinder extends Ipersonservice.stub {
@Override
public void Save (person person) throws RemoteException {
LOG.I ("Personservice", Person.getid () + "=" + Person.getname ());
}
}
}
Other applications can use implicit intent to access the service, the intent of the action can be customized, the Androidmanifest.xml configuration code is as follows:
<service android:name= ". Personservice ">
<intent-filter>
<action android:name= "Com.robert.process.aidl.PersonService"/>
</intent-filter>
</service>
6. Copy the Aidl file in the application to the SRC directory of the client application with the package, and generate the Ipersonservice.java interface file for the Aidl file synchronously in the Gen directory of the client application. Next, copy the custom type file and type declaration Aidl file and the package to the SRC directory of the client application.
Finally, the communication with the remote service can be implemented in the client application, with the following code:
public class Clientactivity extends Activity {
Private Ipersonservice Personservice;
@Override
public void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
This.bindservice (New Intent ("Com.robert.process.aidl.PersonService"), This.serviceconnection, bind_auto_create); /bind to Service
}
@Override
protected void OnDestroy () {
Super.ondestroy ();
This.unbindservice (serviceconnection);//Cancellation Service
}
Private Serviceconnection serviceconnection = new Serviceconnection () {
@Override
public void onserviceconnected (componentname name, IBinder service) {
Personservice = IPersonService.Stub.asInterface (service);
try {
Personservice.save (New person ("liming"));
} catch (RemoteException e) {
LOG.E ("Clientactivity", e.tostring ());
}
}
@Override
public void onservicedisconnected (componentname name) {
Personservice = null;
}
};
}
Differences between local and AIDL services:
The local service does not support Onbind (), which returns null from Onbind (), and this type of service can only be accessed by the application component that hosts the service. You can call StartService () to invoke the local service. AIDL services can be used by components in the same process and components of other applications at the same time. This type of service defines a contract for itself and its client in the Aidl file. The service implements the Aidl contract, while the client binds to the AIDL definition. The service implements the contract by returning the implementation of the Aidl interface from the Onbind () method. The client binds to the Aidl service by calling Bindservice () and calls Unbindservice () to disconnect from the service.

We use handler all in one process, we can use another way,
The Android.os.Messenger of the Android system makes it easy to use handler across processes.
Service side:
public class Messengertestservice extends Service {

Protected static final String TAG = "Messengertestservice";

Private Handler Mhandler = new Handler () {
@Override
public void Handlemessage (Message msg) {
Switch (msg.what) {
Case 1:
LOG.D (TAG, "received message");
Gets the messenger in the client message for the callback
Final Messenger callback = Msg.replyto;
try {
Callback
Callback.send (Message.obtain (null, 0));
} catch (RemoteException e) {
TODO auto-generated Catch block
E.printstacktrace ();
}
Break
}
}
};

@Override
Public IBinder Onbind (Intent Intent) {
return new Messenger (Mhandler). Getbinder ();
}

}

Client
public class Mainactivity extends Activity {

Protected static final String TAG = "mainactivity";
Messenger Messenger;
Messenger reply;

@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Reply = new Messenger (handler);
Intent Intent = new Intent ();
Intent.setclassname ("Test.messenger", "Test.messenger.MessengerTestService");

Binding Service
Bindservice (Intent, New Serviceconnection () {

@Override
public void onservicedisconnected (componentname name) {

}

@Override
public void onserviceconnected (componentname name, IBinder service) {
Toast.maketext (Mainactivity.this, "bind success", 0). Show ();
Messenger = new Messenger (service);
}
}, Context.bind_auto_create);

}
public void SendMessage (View v) {
Message msg = Message.obtain (null, 1);
Set the call back to Messenger
Msg.replyto = reply;
try {
Messenger.send (msg);
} catch (RemoteException e) {
E.printstacktrace ();
}
}
Private Handler Handler = new Handler () {

@Override
public void Handlemessage (Message msg) {
LOG.D (TAG, "callback succeeded");
}

};
}

The client binds the server side, obtaining the binder object for remote Messenger. By invoking Messenger's send function, you can send the message to the server's handler.
At the same time, if you need a server callback client, you can set ReplyTo in the Send message, and the server can send messages to the client.
Now let's look at the source of Messenger.
constructor function
Public Messenger (Handler target) {
Mtarget = Target.getimessenger ();
}
Handler.getimessenger () returns a IMessenger binder object whose send method will invoke the SendMessage method of Handler.
public void Send (Message message) throws RemoteException {
Mtarget.send (message);

}







Android Inter-process communication

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.