Explanation of Android Service (3) AIDL and androidaidl

Source: Internet
Author: User

Explanation of Android Service (3) AIDL and androidaidl

This article is translated from the official android documentation and tested by yourself.

Android Interface Definition Language (AIDL) allows us to define our own programming Interface, which enables cross-process communication (IPC) between the client and the service ). Generally, cross-process communication is not allowed in android. Therefore, you need to break down the passed objects into raw states (data) that can be recognized by the system and serialize them across processes. Android uses AIDL to process callback alling because it is cumbersome.

Note: AIDL is required only when clients of different applications are allowed to obtain the service for IPC and multi-thread processing is required in the service. Most applications should not use AIDL to create the Bound Service, because it may require multi-threaded processing capabilities and make the code more complex. Therefore, AIDL is not applicable to most applications. If it is used only within an application without cross-process, we can directly interact by inheriting the Binder class. This is the most common method. If the cross-process IPC does not need to handle multithreading, you can use the Messenger method, because Messenger puts all requests in one thread, so there is no need to worry about thread security.

(There are still some problems in the following understanding) before designing the AIDL interface, you must note that calling the AIDL interface is a direct call method. We should not assume that the call method occurs in the subthread. The thread calls in the local process and remote process are different:

  • It is called in a local process. If it is called in the main thread, the AIDL interface is executed in the main thread. If it is another sub-thread, the thread executes the code in the service. Therefore, if only the local thread obtains the service, we can completely control it. In this case, we should not use AIDL, but inherit the Binder implementation.
  • If a remote process is called, The AIDL implementation must ensure full thread security. This is because remote calls may need to be processed simultaneously (concurrently ).
  • One-way change of Remote Call behavior. When this method is used, remote calls are not blocked; it simply sends data and returns immediately. In the end, the interface is used to receive remote calls, just like conventional calls through the Binder thread pool. If one-way call is used locally, the call will not be affected and the call is still asynchronous.

The above content understands some problems and must be reviewed and verified againIn addition, please kindly advise.

Define the AIDL Interface

The AIDL interface must be defined in.aidlFile (the name meets the java syntax), and is stored in the application where the service is located and other applications bound to the service (the service must be IPC through AIDL, saved in source codesrc/Directory.

When we create a new.aidlThe android SDK automatically generates an IBinder Interface Based on the file and storesgen/Directory. The service must implement the IBinder interface before the client can bind the service and call the method to obtain the object for IPC.

The above directory is in eclipse, and in android studio, it is in:

To create a service using AIDL, follow these steps:

Note: Changes to the AIDL interface after the first release must ensure compatibility with the original version, prevent other applications from accessing our service (other clients may copy the original interface version ).

The preceding steps are described in detail below:

1. Create .aidlFile

AIDL needs to satisfy some simple Syntax: it enables us to declare an interface that can contain one or more methods and can contain parameters and return values. Parameters and return values can be any type or even interfaces generated by other AIDL.

Each.aidlThe file must define an interface, and only the interface declaration and method declaration are required.

By default, AIDL supports the following data types:

  • Eight basic data types in java
  • String
  • CharSequence
  • List
    Of course, the type in the List also needs to be supported by AIDL. A List is usually used to declare variables, and the specific type (such as ArrayList) is determined during definition.
  • Map
    The usage is the same as that of List.

If you use a type other than the above (such as a custom class), you must import the relevant declaration, even if it is defined in the same package.

When defining the AIDL interface, pay attention to the following points:

  • The method can contain 0 or more parameters, and you can choose whether to return values.
  • All non-basic data types need to specify a direction to mark the data flow (inbound, outbound, and inbound and outbound ). The basic data type is input by default and cannot be changed. It is necessary to restrict the data direction (the actually needed direction) because the cost of the wide alling parameter is high.
  • All code comments in the file are included in the generated IBinder interface, unless they are annotated before import and package.
  • Only methods are supported, but static member variables are not supported. The method cannot have modifiers.
  • Manually enter the package name (manual is not required for android studio)

The following is an example:

Package com. sywyg. servicetest; import com. sywyg. servicetest. man; // Declare any non-default types here with import statements // the location where the custom type needs to be imported. interface IRemoteService {/** Request the process ID of this service, to do edevil things with it. */int getPid ();/** Demonstrates some basic types that you can use as parameters * and return values in AIDL. */void basicTypes (int anInt, long aLong, boolean sort lean, float aFloat, double aDouble, String aString); // Man getMan ();}

Then the system automatically generates an IRemoteService. java (corresponding to IRemoteService. aidl) file.
Some compilers generate immediately, while others generate when compiling the application.

2. Implementation Interface

The automatically generated file contains an internal abstract class Stub that inherits the Binder and is an abstract Implementation of the parent class interface..aidlAll methods in the file. Stub also defines some other useful methods, especiallyasInterface()Method. This method receives an IBinder object and returns the implementation of the Stub interface. Stub indicates the meaning of a Stub in English. This class is a process on the server. We must inherit this class and implement the methods in the aidl interface.

The following uses an anonymous class to implement a simple interface instance:

/*** Defines an anonymous internal class to implement the aidl interface and must inherit the IRemoteService. stub class * in. the Methods declared in the aidl file need to be implemented here */private final IRemoteService. stub mBinder = new IRemoteService. stub () {public int getPid () {Log. d (TAG, "getPid is executed... "); return android. OS. process. myPid ();} public void basicTypes (int anInt, long aLong, boolean sort lean, float aFloat, double aDouble, String aString) {Log. d (TAG, "basicTypes is executed... ");}};

Stub implements the Binder class (defines the Remote Procedure Call Protocol RPC), so mBinder can be transmitted to the client.

When implementing AIDL, pay attention to the following points:

  • Calls cannot be executed in the main thread. We should consider multithreading and ensure that the service is thread-safe.
  • By default, RPC calls are asynchronous. If the service requires a long period of operation, make sure that the call cannot occur in the main thread, because this may cause the Application to fail to respond to the problem Application Not Responding ANR. Therefore, we should ensure that the call occurs in another child thread.
  • No exception is thrown to the caller.
3. Expose the interface to the client

The AIDL interface is implemented for the service. We should expose the interface to the client so that they can bind it. The complete code is provided below to illustrate how to implement it:

/*** Use AIDL to implement IPC * @ author sywyg * @ since 2015.7.16 */public class AIDLService extends Service {private final String TAG = "result"; public AIDLService () {}/*** defines an anonymous internal class to implement the aidl interface. The IRemoteService must be inherited. stub class * in. the Methods declared in the aidl file need to be implemented here */private final IRemoteService. stub mBinder = new IRemoteService. stub () {public int getPid () {Log. d (TAG, "getPid is executed... "); return android. OS. process. myPid ();} public void basicTypes (int anInt, long aLong, boolean sort lean, float aFloat, double aDouble, String aString) {Log. d (TAG, "basicTypes is executed... ") ;};@ Override public IBinder onBind (Intent intent) {return mBinder ;}}

Then, when the client callsbindService()When the service is connected, the client calls backonServiceConnected()Method to receiveonBinder()).

The client must also be able to obtain this interface class. Therefore, when the client and service are in different applications, the client application must copy one copy..aidlFile to obtain the methods in AIDL.

When the customeronServiceConnected()When receiving an IBinder object in the method, you must callYourServiceInterface.Stub.asInterface(service)Convert to YourServiceInterface type. As follows:

IRemoteService mIRemoteService; private ServiceConnection mConnection = new ServiceConnection () {@ Override public void onServiceConnected (ComponentName, IBinder service) {Log. d (TAG, "bound successfully"); // Following the example above for an AIDL interface, // this gets an instance of the IRemoteService, which we can use to call on the service // or the above example, get an IRemoteService instance in this way, // so that we can process it on the client. MIRemoteService = IRemoteService. Stub. asInterface (service); mBound = true ;}@ Override public void onServiceDisconnected (ComponentName name) {mBound = false ;}};
Passing objects through IPC

We can pass an object from one process to another through IPC. However, we must ensure that this object can be obtained in another process (that is, the code of this class is required), and this class must support the Parcelable interface. Parcelable must be supported so that the system can break down objects into basic data types (cross-process externalled ).

Note: Parcelable is an interface. The class instances that implement this interface can be saved in Parcel and restored from it. This class must have a static member variable named CREATOR, which is an implementation instance of Parcelable. Creator.

To create a class that supports the Parcelable protocol, you must complete the following:

AIDL generates the marshall and unmarshall objects through the above method.

The following is a Rect class that implements the Parcelable interface. The Rect. aidl file must first be available:

Package android. graphics; // Declare Rect so AIDL can find it and knows that it implements // the parcelable protocol. // declare the Rect. AIDL finds and confirms that it implements the parcelable protocol parcelable Rect;

The following is the Rect class:

import android.os.Parcel;import android.os.Parcelable;public final class Rect implements Parcelable {    public int left;    public int top;    public int right;    public int bottom;    public static final Parcelable.Creator<Rect> CREATOR = newParcelable.Creator<Rect>() {        public Rect createFromParcel(Parcel in) {            return new Rect(in);        }        public Rect[] newArray(int size) {            return new Rect[size];        }    };    public Rect() {    }    private Rect(Parcel in) {        readFromParcel(in);    }    public void writeToParcel(Parcel out) {        out.writeInt(left);        out.writeInt(top);        out.writeInt(right);        out.writeInt(bottom);    }    public void readFromParcel(Parcel in) {        left = in.readInt();        top = in.readInt();        right = in.readInt();        bottom = in.readInt();    }}

Parcel can also write data of other types.

Warning do not forget the security issue when retrieving data from another process. In the above example, Rect gets four numbers, but this depends on how much data you get (the read/write order must be consistent ).

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.