Aidl, parcelable, and remote services for Android service learning

Source: Internet
Author: User

Role of aidl
Because each application runs in its own process space and can run another service process from the application UI, objects are often transferred between different processes. On the Android platform, a process generally cannot access the memory space of another process. Therefore, to perform a conversation, you need to break down the object into basic units that the operating system can understand and orderly pass through the process boundary.
It is tedious to implement this data transmission process through code. Android provides the aidl tool to handle this task.
Aidl (Android Interface Definition Language) is an IDL Language used to generate code for interprocess communication (IPC) between two processes on the Android device. If you want to call operations on objects in another process (such as service) in a process (such as activity), you can use aidl to generate serializable parameters.
The aidl IPC Mechanism is interface-oriented, like com or CORBA, but more lightweight. It uses a proxy class to transmit data on the client and the implementation end.
Select aidl application scenariosThe official document reminds us that it is necessary to use aidl: Only you allow the client to access your service from different applications for inter-process communication, and want to process multithreading in your service. 
If you do not need to perform concurrent communication (IPC) between different applications, you can create your interface by implementing a binder; or if you want to implement IPC, but do not need to process multiple threads, then implement your interface using a messenger. Before using aidl, you must understand how to bind Service -- bindservice. Before designing the aidl interface, we should note that calling the aidl interface is a direct method call, not in our imagination. What is the difference between a call from a local or remote process? In particular, the following situations (reference the original text and do not translate it to avoid translation errors ):
  • Callmade from the local process are executed in the same thread that is making the call. if this is your main UI thread, that thread continues to execute in the aidl interface. if it is another thread, that is the one that executes your code in the service.
    Thus, if only local threads are accessing the service, you can completely control which threads are executing in it (but if that is the case, then you shouldn't be using aidl at all, but shoshould instead create the interface by implementing
    A binder ).
  • Callfrom a remote process are dispatched from a thread pool the Platform maintains inside of your own process. you must be prepared for Incoming callfrom unknown threads, with multiple callhappening at the same time. in other words, an implementation
    Of an aidl interface must be completely thread-safe.
  • TheonewayKeyword modifies the behavior of remote CILS. When used, a remote call does not block; it simply sends the transaction
    Data and immediately returns. The implementation of the interface eventually since es this as a regular call fromBinderThread
    Pool as a normal remote call. IfonewayIs used with a local call, there is no impact and the call is still synchronous.

Define the aidl InterfaceThe aidl interface file is nothing special to the common interface content, but its extension is. aidl. Save it in the src directory. If other applications require IPC, the SRC of those applications will also carry this file. Android SDK tools automatically generates an ibinder interface file in the gen directory. Service must implement this ibinder interface as appropriate. Then the client program can bind the service and call the method from ibinder during IPC. Each aidl file can only define one interface, and can only be an interface declaration and method declaration. 1. Create a. aidl File 
Aidl uses a simple syntax to declare an interface and describe the parameters and return values of its methods and methods. These parameters and return values can be of any type, or even interfaces generated by other aidl. The import statements are not required for the basic data types (INT, long, Char, Boolean, etc.), string, and charsequence of the Java programming language. If you want to use other aidl Interface Types in aidl, You need to import them, even in the same package structure. Aidl allows passing classes that implement the parcelable interface. Import is required.
Note that for non-basic data types, which are not string and charsequence types, direction indication is required, including in, out, And inout. In indicates that the data is set by the client, the out parameter is set by the server, and the inout parameter is set by both. Aidl only supports interface methods and does not expose static variables.
For example (imyservice. aidl ):
package com.demo; import com.demo.Person; interface IMyService {         void savePersonInfo(in Person person);         List<Person> getAllPerson(); }

2. Implementation InterfaceCreate a class to implement the aidl interface just now:
public class RemoteService extends Service {         private LinkedList<Person> personList = new LinkedList<Person>();                  @Override         public IBinder onBind(Intent intent) {                 return mBinder;         }         private final IMyService.Stub mBinder = new IMyService.Stub() {                 @Override                 public void savePersonInfo(Person person) throws RemoteException {                         if (person != null ){                                 personList.add(person);                         }                 }                 @Override                 public List<Person> getAllPerson() throws RemoteException {                         return personList;                 }         }; }

Here we can see that there is a class named imyservice. stub. To view the source code of the Java file generated by the aidl file, you can find such a piece of code:/** local-side IPC implementation stub class .*/
Public static abstract class stub extends android. OS. binder implements COM. demo. imyservice's original stub class is inherited from the binder class. That is to say, the remoteservice class is no different from the normal service class, but the returned ibinder object is special. It is a binder that implements the aidl interface. Next we will discuss the passed data bean-person class, which is a serialized class. Here we use the parcelable interface for serialization, which is a serialization class provided by android that is more efficient than serializable. Parcelable needs to implement three functions:
1) Void writetoparcel (parcel DEST, int flags)Write the data to be serialized and stored into the external provided parcel object DeST. After reading the code on the internet, I guess that the order of reading parcel data must be the same as the write order here. Otherwise, the data may be read incorrectly. I have not tried it!
2) Describecontents ()I don't know what it is for. It's okay to return 0 directly.
3) Static final parcelable. creator Object CreatorThe Creator name is fixed, and its corresponding interface has two methods:
Createfromparcel (parcel source) is used to create a JavaBean instance from the source.

Newarray (INT size) creates an array of T type and size. It can only be a single sentence (return New T [size. It is estimated that this method is used for external class deserialization of this class array.
Carefully observe the Code of the Person class and the content mentioned above:

public class Person implements Parcelable {         private String name;         private String telNumber;         private int age;         public Person() {}         public Person(Parcel pl){                 name = pl.readString();                 telNumber = pl.readString();                 age = pl.readInt();         }         public String getName() {                 return name;         }         public void setName(String name) {                 this .name = name;         }         public String getTelNumber() {                 return telNumber;         }         public void setTelNumber(String telNumber) {                 this .telNumber = telNumber;         }         public int getAge() {                 return age;         }         public void setAge(int age) {                 this .age = age;         }         @Override         public int describeContents() {                 return 0;         }         @Override         public void writeToParcel(Parcel dest, int flags) {                 dest.writeString(name);                 dest.writeString(telNumber);                 dest.writeInt(age);         }         public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {                 @Override                 public Person createFromParcel(Parcel source) {                         return new Person(source);                 }                 @Override                 public Person[] newArray(int size) {                         return new Person[size];                 }         }; }

Then create the person. aidl file. Note that the parcelable and the previously implemented parcelable interfaces start with the letter P, in lowercase and in upper case: Package com. Demo;

Parcelable person;

For the implementation of the aidl interface, the official also reminds us: 1. the caller cannot guarantee the execution in the main thread. Therefore, from the beginning of the call, multi-thread processing needs to be considered and thread safety should be ensured; 2. IPC calls are synchronized. If you know that an IPC service takes several milliseconds to complete, you should avoid calling it in the main thread of the activity. That is, the IPC call will suspend the application and cause the interface to lose response. In this case, you should consider opening a thread separately for processing.
3. The thrown exception cannot be returned to the caller (it is not advisable to throw an exception across processes ).
 
3. Client Acquisition InterfaceHow does the client obtain the aidl interface? Use imyservice. stub. asinterface (service) to obtain the imyservice object:
Private imyservice mremoteservice; private serviceconnection mremoteconnection = new serviceconnection () {public void onserviceconnected (componentname classname, ibinder Service) {mremoteservice = imyservice. stub. asinterface (service);} public void onservicedisconnected (componentname classname) {mremoteservice = NULL ;}}; in the generated imyservice. in Java, the following code is found:/*** cast an ibinder object into an COM. d Emo. imyservice interface, * generating a proxy if needed. */public static COM. demo. imyservice asinterface (Android. OS. ibinder OBJ ){...} but the binding of service is no different: If (misremotebound) {unbindservice (mremoteconnection);} else {bindservice (new intent ("com. demo. imyservice "), mremoteconnection, context. bind_auto_create);} misremotebound =! Misremotebound;

Call/transmit data through IPCAfter the client binds the service, it can call/transmit data through IPC and directly call the interface method of the service object:
addPersonButton.setOnClickListener(                 new View.OnClickListener(){                         private int index = 0;                         @Override                         public void onClick(View view) {                                 Person person = new Person();                                 index = index + 1;                                 person.setName("Person" + index);                                 person.setAge(20);                                 person.setTelNumber("123456" );                                 try {                                         mRemoteService.savePersonInfo(person);                                 } catch (RemoteException e) {                                         e.printStackTrace();                                 }                         }                 }); listPersonButton.setOnClickListener(                 new View.OnClickListener(){                         @Override                         public void onClick(View view) {                                 List<Person> list = null ;                                 try {                                         list = mRemoteService.getAllPerson();                                 } catch (RemoteException e) {                                         e.printStackTrace();                                 }                                 if (list != null ){                                         StringBuilder text = new StringBuilder();                                         for (Person person : list){                                                 text.append("\nPerson name:" );                                                 text.append(person.getName());                                                 text.append("\n             age :" );                                                 text.append(person.getAge());                                                 text.append("\n tel number:" );                                                 text.append(person.getTelNumber());                                         }                                         inputPersonEdit.setText(text);                                 }else {                                         Toast.makeText(ServiceActivity.this , "get data error" ,                                                         Toast.LENGTH_SHORT).show();                                 }                         }                 });

  Permission permission
If the service declares the global mandatory access permission in androidmanifest. XML, other references must declare the permission to start, stop or bind the service.
In addition, the Service can protect her IPC method calling through permissions, and ensure that this operation can be performed by calling the checkcallingpermission (string) method. Service Element of androidmanifest. xml
< service android:name =".RemoteService" android:process =":remote" >         < intent-filter >                 < action android:name ="com.demo.IMyService" />         </ intent-filter > </ service >

Android: Process = ": Remote". I didn't add it at the beginning. I used IPC in the same program, that is, the same program as the client/server, result: mremoteservice = imyservice. stub. asinterface (service); a null pointer exception is prompted. I have observed the IPC code in different programs.
Android: Process = ": Remote. Later in the official document http://androidappdocs.appspot.com/guide/topics/manifest/service-element.html to learn (pay attention to the second paragraph of text ):

Android: Process
The name of the process where the service is to run. normally, all components of an application run in the default process created for the application. it has the same name as the application package. the <Application> element's process attribute can
Set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application processing SS multiple processes. If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process
Name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. this allows components in different applications to share a process, cing resource usage.

Android: Process = ": Remote" indicates that a new process is automatically created when the service is required in an application. If Android: Process = "remote" does not have a semicolon (:), a global process is created and different applications share the process.

Related Article

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.