Example to explain the AIDL internal process communication interface using _android in Android

Source: Internet
Author: User
Tags int size modifiers stub

First describe what we want to achieve, and we want to use the Click button in one application to manipulate the music playback function applied in another process.

In the figure, when we click "Play", the system will go to the remote call we provide a service (not the same as the current service application OH), and then operate the music play in the service, click "Stop" will stop playback. If you want to replay, you must first "destroy the service", and then click the Play button Oh. (As for why the first point to destroy the button to play, is entirely to show you, Remote Call service, how to solve the binding service).

In this example, we use a very important concept, aidl.

Aidl (Android Interface Definition language) The Android interface describes the language, and its main function is to allow us to communicate between different processes.

We all know that each application runs in its own process, and that the Android platform does not allow direct object data to be passed between different processes. If we have to communicate between processes, we must break down our data objects into tiny, data units that can be understood by the operating system, and then sequentially check through the process boundaries.

If we let ourselves achieve, then this process is worried about the death of a batch of program people. Fortunately, Android solves this problem for us, and that's why Aidl is there.

Aidl (Android Interface Definition Language) is an IDL language that generates code that can process interprocess communication (IPC) between two processes on an Android device. If you are in a process, such as an activity, to invoke an operation on another process (such as a service) object, you can use Aidl to generate serializable parameters.
The AIDL IPC mechanism is interface-oriented, like COM or CORBA, but more lightweight. It is the use of proxy classes to pass data on both the client and the implementation side.

Note: Aidl only supports methods, cannot define static members, and methods cannot have modifiers such as public, aidl run methods have any type of parameters and return values, in Java types, the following types are used without importing packages (import), basic data types, String, Map, List. Of course, to avoid errors, it is recommended that you import the package as long as you use it.

Steps to use Aidl:

Service side (service provided):

Step one: Define a *.aidl file that conforms to the interface definition of the AIDL language specification, which defines the methods that external applications can access. When we save the file, eclipse will automatically generate a corresponding Java interface file for us under the Gen folder. such as Remoteserviceinterface.java

Step two: Define a service of your own and register it in the Androidmanifest.xml file, for example:

<service android:name= "Myremoteservice" >
 <intent-filter>
 <action android:name= " Cn.com.chenzheng_java.remote "/>
 </intent-filter>
 </service>

Note here must provide a intent-filter, our client process is through this action access to the server process OH.

We all know that in implementing our own service, for other applications to interact with our service through Bindservice, we have to implement the Onbind () method in the service and return an inner class that inherits binder; Eclipse automatically has an inner class, remoteserviceinterface.stub, that implements the binder for the Remoteserviceinterface.java we generate. Aidl asked us, here can no longer directly to implement the Binder class, but to implement, Aidl provided to our stub class. While implementing the stub class, Aidl also requires that we implement the various services that we define in the interface at the same time. So far, our service side has been bound to our aidl files together Oh.

Client:

The first step: the client wants to use this service, must first know our service in the Aidl file in the end to provide what service, right? So, the first step, we have to do is to copy the Aidl file to the client's program (here must be noted that the package path and the service side of the consistency oh, such as the service end of Cn.com.chenzheng_java.remote.a.aidl, This should also be the path on the client side.

Step Two: We all know that in order to interact with the service, we have to pass the Bindservice method, which has a serviceconnection type of argument. And our main code is in the implementation of the interface.

Step three: In the Serviceconnection implementation class onserviceconnected (componentname name, IBinder Service) method through a similar remoteserviceinterface = RemoteServiceInterface.Stub.asInterface (service), you can get an instance of the service provided by the remote server, and then we can go through the Remoteserviceinterface object to invoke the method provided in the interface to interact with it. (The key here is through *.) Stub.asinterface (service); method gets an instance of a Aidl interface OH)

We said earlier in the service side that we must provide a intent-filter to match the request is legitimate, so when we access the service on the client, we must also pass intent that contains the matching action.

The bottom whole is code:
Remote Service side:

Remoteserviceinterface.aidl

Package cn.com.chenzheng_java.remote; 
/**aidl's syntax is slightly different from the interface syntax, 
* There are only methods in it, and those modifiers in Java, such as public, are not supported here. 
* When we add a aidl file to the end of the. Aidl in eclipse, if you are in the correct format, then 
* in the Gen directory, you will see the corresponding Java class that the system automatically generates for you according to the Aidl file you provide 
* @author Chenzheng_java 
* * 
 
 
 interface Remoteserviceinterface { 
 
   void Startmusic (); 
   void Stopmusic (); 
} 

Myremoteservice.java

Package cn.com.chenzheng_java.remote; 
 
Import java.io.IOException; 
Import Android.app.Service; 
Import android.content.Intent; 
Import Android.media.MediaPlayer; 
Import Android.os.IBinder; 
Import android.os.RemoteException; /** * @description Remote Service * @author Chenzheng_java * * */public class Myremoteservice extends service {Medi 
  Aplayer MediaPlayer; 
  @Override public IBinder onbind (Intent Intent) {return new Mybinder (); 
     @Override public void OnCreate () {/* * * * Mediaplayer.create method The first argument is actually a context object, where we pass the service directly to it, 
     * Because the service itself has inherited the context. 
    * * MediaPlayer = mediaplayer.create (Myremoteservice.this, r.raw.aiweier); 
  Super.oncreate (); /** * @description Here it is important to note that the inheritance is no longer a binder, but an inner class of the binder that the system automatically generates for us, called a stub. 
   By inheriting the stub class and then implementing the method defined in Aidl *, we have implemented the interface method concretely. * @author Chenzheng_java * * */Private class Mybinder extends remoteserviceinterface.stub{public void Startmusic () throws RemoteException {Mediaplayer.start (); 
      public void Stopmusic () throws RemoteException {mediaplayer.stop (); 
      try {mediaplayer.prepare (); 
      catch (IllegalStateException e) {e.printstacktrace (); 
      catch (IOException e) {e.printstacktrace (); 

 } 
    } 
     
  } 
 
}

Remoteserviceactivity.java

Package cn.com.chenzheng_java.remote; 
 
Import android.app.Activity; 
Import Android.os.Bundle; 
/** 
 * Many people do not understand that there is basically nothing to achieve, why also to provide it? 
 * In fact, the reason is this, the service code we have written, but also registered in the configuration file, 
 * so that the mobile phone system will recognize it? No, you have to at least 
 run the application once for the service. How else does the phone know you've added a service, right? 
 * @author Chenzheng_java 
 * * */public 
class Remoteserviceactivity extends activity { 
  @Override Public 
  void OnCreate (Bundle savedinstancestate) { 
    super.oncreate (savedinstancestate); 
    Setcontentview (R.layout.main); 
  } 
 

Androidmanifest.xml

 <?xml version= "1.0" encoding= "Utf-8"?> <manifest "xmlns:android=" Schemas.android.com/apk/res/android "package=" Cn.com.chenzheng_java.remote "android:versioncode=" 1 "android:ve Rsionname= "1.0" > <uses-sdk android:minsdkversion= "8"/> <application android:icon= "@drawable/icon" and Roid:label= "@string/app_name" > <activity android:name= ". Remoteserviceactivity "android:label=" @string/app_name "> <intent-filter> <action and 
      Roid:name= "Android.intent.action.MAIN"/> <category android:name= "Android.intent.category.LAUNCHER"/> </intent-filter> </activity> <service android:name= "Myremoteservice" > <inten t-filter> <action android:name= "Cn.com.chenzheng_java.remote"/> </intent-filter> </service& 
 
  Gt </application> </manifest> 

Client:

Activity code:

Package Cn.com.chenzheng_java; 
Import android.app.Activity; 
Import Android.content.ComponentName; 
Import Android.content.Context; 
Import android.content.Intent; 
Import android.content.ServiceConnection; 
Import Android.os.Bundle; 
Import Android.os.IBinder; 
Import android.os.RemoteException; 
Import Android.util.Log; 
Import Android.view.View; 
Import Android.view.View.OnClickListener; 
Import Android.widget.Button; 
Import Cn.com.chenzheng_java.remote.RemoteServiceInterface; /*** * @author Chenzheng_java * @description invoke the remote service in different processes through the current activity/public class Localserviceactivity ex 
  Tends activity implements Onclicklistener {String action_name = "Cn.com.chenzheng_java.remote"; 
  Boolean flag = false; 
  Button Button_start; 
  Button Button_stop; 
   
  Button Button_destroy; 
    @Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
     
    Setcontentview (R.layout.music); Button_start = (Button) finDviewbyid (R.id.button1); 
    Button_stop = (Button) Findviewbyid (R.id.button2); 
     
    Button_destroy = (Button) Findviewbyid (R.id.button3); 
    Button_start.setonclicklistener (this); 
    Button_stop.setonclicklistener (this); 
  Button_destroy.setonclicklistener (this); 
   
  } remoteserviceinterface Remoteserviceinterface; Private class Myserviceconnection implements serviceconnection{public void onserviceconnected (componentname name, IB 
      Inder Service) {remoteserviceinterface = RemoteServiceInterface.Stub.asInterface (service); 
        try {log.i ("flag", flag+ ""); 
          if (flag) {LOG.I ("notice", "already started singing"); 
        Remoteserviceinterface.startmusic (); 
          }else{log.i ("notice", "has ceased singing"); 
        Remoteserviceinterface.stopmusic (); 
      } catch (RemoteException e) {e.printstacktrace (); 
     } public void onservicedisconnected (componentname name) {  
    } private Myserviceconnection serviceconnection = new Myserviceconnection (); 
      public void OnClick (View v) {if (v = = Button_start) {flag = true; 
      Intent Intent = new Intent (action_name); /** * context.bind_auto_create When binding service, if found not yet create, then create a first, then bind/bindservice (intent, SE 
    Rviceconnection, context.bind_auto_create); 
      } if (v = = button_stop) {log.i ("notification", "has clicked the Stop button"); 
      Flag = false; 
      Intent Intent = new Intent (action_name); 
      Bindservice (Intent, serviceconnection, context.bind_auto_create); 
      try {remoteserviceinterface.stopmusic (); 
      catch (RemoteException e) {e.printstacktrace (); 
      } if (v = = Button_destroy) {flag = false; 
      Intent Intent = new Intent (action_name); 
      Bindservice (Intent, serviceconnection, context.bind_auto_create); 
    Unbindservice (serviceconnection); } 
     
  } 
} 

 

Music.xml

<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android= 
"http://schemas.android.com/apk/" Res/android " 
  android:layout_width=" match_parent "android:layout_height=" match_parent "> 
  <Button android:text= "Play" android:id= "@+id/button1" android:layout_width= "wrap_content" android:layout_height= "WRAP_" 
    Content "></Button> 
  <button android:text=" Stop "android:id=" @+id/button2 " 
    android:layout_width= "Wrap_content" android:layout_height= "wrap_content" ></Button> 
  <button android:text= "Destroy service" Android:id= "@+id/button3" 
    android:layout_width= "wrap_content" android:layout_height= "Wrap_content" ></ Button> 
</LinearLayout> 


Other code that is not pasted is generated by the system default.

Aidl and Passing objects

In addition to the above we mentioned that through the service to provide music playback and other similar services, we can also pass the object back through the service Oh, you know how to use, first look at the example:

When we click "Get", we get an object from another thread's service and read the contents.

For AIDL implementations interact in an object's way. The main steps are as follows:

Service side:
First: Define an entity class, this is beauty, Defines a service interface Aidl file Remotebeauty.aidl, one thing to note here is that when we reference a custom entity class to the aidl, we need to import the package through the import, but you will find that even if you import the package, or the hint is not found, at this time, you have to do is to build an entity class name named the AI DL files, such as beauty.aidl, add a sentence of pracelable Beauty inside.

Second: Start writing beauty, here must note that it must implement the Pracelable interface, which is a serialized interface, the function and serializable similar, but the function is more rapid. In addition, be sure to declare a public static final Pracelable.creator<t>creator object inside the beauty!! Except that T in the inside represents the entity class, the rest is not allowed to change oh.

Third: Register the service in the Androidmanifest.xml. and define the action string to access the service.

Client:
The client side of the corresponding to a lot simpler, but to note that the entity class and Aidl files are copied over Oh, but also to ensure that the path is exactly the same!!

Beauty.java

Package cn.com.chenzheng_java.service; 
Import Android.os.Parcel; 
Import android.os.Parcelable; /** * * @author Chenzheng_java * @description parcelable is a higher-efficiency serial number interface provided by Android than Serializable * Here must inherit parcel Able Oh, no serial number how can pass ... 
 Right?! * In the entity class we have to do two important things: * First: Implement Parcelable interface * Second: Define a Parcelable.creator type of creator Object * Third: To provide a beauty.aidl file, where the content is Parcelab 
 Le Beauty, once defined, does not prompt for an error when referencing Beauty in other aidl files. 
  * @since 2011/03/18 * * */public class Beauty implements parcelable {String name; 
  int age; 
   
  String sex; 
  Public String GetName () {return name; 
  public void SetName (String name) {this.name = name; 
  public int getage () {return age; 
  public void Setage (int age) {this.age = age; 
  Public String Getsex () {return sex; 
  } public void Setsex (String sex) {this.sex = sex; 
  @Override public int describecontents () {return 0; /** * The object serial number * Dest is the object is about to be writtenThe purpose of the object * flags the identification of the way of the object serial number * Note that the write order is identical to the order read in the Createfromparcel method. For example, write first for name, * then read name/@Override public void Writetoparcel (Parcel dest, int flags) in Createfromparcel 
      {dest.writestring (name); 
      Dest.writeint (age); 
  dest.writestring (Sex); /** * Be sure to declare the constant inside the entity class that you want to pass the serial number to. The constant name can only be Creator, and the type must also be * parcelable.creator<t>/public static final parcelable.creator<beauty> CREA TOR = new Creator<beauty> () {/** * creates an array of entity classes to be serial numbers, all of which are set to NULL */@Override Pub 
    Lic beauty[] NewArray (int size) {return new beauty[size]; /*** * According to the serial number of the parcel object, the reverse sequence number is the original entity object * read out order and Writetoparcel write order is the same * * * @Override Publ 
      IC Beauty createfromparcel (Parcel source) {String name = Source.readstring (); 
      int age = Source.readint (); 
      String sex = source.readstring (); 
      Beauty Beauty = new Beauty (); Beauty.setnamE (name); 
      Beauty.setage (age); 
       
      Beauty.setsex (Sex); 
    return beauty;    
   
} 
  }; 

 }

Remoteservice.java

Package cn.com.chenzheng_java.service; 
 
Import Android.app.Service; 
Import android.content.Intent; 
Import Android.os.IBinder; 
Import android.os.RemoteException; 
Import Android.util.Log; 
/** 
 * * 
 @author chenzheng_java 
 * @description Service 
 * * 
 /Public 
class Remoteservice extends Service { 
 
  @Override public 
  ibinder onbind (Intent Intent) { 
    log.i ("Notifications", "executed Onbind "); 
    return new Mybinder (); 
  } 
 
   
  Private class Mybinder extends remotebeauty.stub{ 
 
    @Override public 
    Beauty getbeauty () throws RemoteException { 
       
      Beauty Beauty = new Beauty (); 
      Beauty.setname ("Feifei"); 
      Beauty.setage (); 
      Beauty.setsex ("female"); 
       
      return beauty; 
    }} 
   
   
   
 

Serviceactivity.java

Package cn.com.chenzheng_java.service; 
 
Import android.app.Activity; 
Import Android.os.Bundle; 
/** 
 * @description Transfer of object data between processes 
 * @author Chenzheng_java 
 * * */public 
class Serviceactivity extends Activity { 
  @Override the public 
  void OnCreate (Bundle savedinstancestate) { 
    super.oncreate ( Savedinstancestate); 
    Setcontentview (R.layout.main); 
  } 
 

Beauty.aidl

Parcelable Beauty; 

Remotebeauty.aidl

package cn.com.chenzheng_java.service; 
Import cn.com.chenzheng_java.service.Beauty; 
 Interface Remotebeauty { 
 
  Beauty getbeauty (); 
   
} 

Manifest.xml

<?xml version= "1.0" encoding= "Utf-8"?> <manifest xmlns:android= "http://schemas.android.com/apk/res/" Android "package=" Cn.com.chenzheng_java.service "android:versioncode=" 1 "android:versionname=" 1.0 "> < USES-SDK android:minsdkversion= "8"/> <application android:icon= "@drawable/icon" android:label= "@string/app_ Name "> <activity android:name=". Serviceactivity "android:label=" @string/app_name "> <intent-filter> <action android:n 
      Ame= "Android.intent.action.MAIN"/> <category android:name= "Android.intent.category.LAUNCHER"/> 
    </intent-filter> </activity> <!--service starts--> <service android:name= "Remoteservice" >  
  <intent-filter> <action android:name= "Cn.com.chenzheng_java.remote2"/> </intent-filter> 

 </service> <!--service end--> </application> </manifest>

Client:

Clientactivity.java

Package cn.com.chenzheng_java.client; 
Import android.app.Activity; 
Import Android.content.ComponentName; 
Import Android.content.Context; 
Import android.content.Intent; 
Import android.content.ServiceConnection; 
Import Android.os.Bundle; 
Import Android.os.IBinder; 
Import android.os.RemoteException; 
Import Android.util.Log; 
Import Android.view.View; 
Import Android.view.View.OnClickListener; 
Import Android.widget.Button; 
Import Android.widget.TextView; 
Import Cn.com.chenzheng_java.service.Beauty; 
 
Import Cn.com.chenzheng_java.service.RemoteBeauty; 
  public class Clientactivity extends activity implements Onclicklistener {TextView TextView; 
  Button button; 
  String actionname = "Cn.com.chenzheng_java.remote2"; 
   
  Remotebeauty remotebeauty; 
    @Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
    Setcontentview (R.layout.main); 
    TextView = (TextView) Findviewbyid (R.ID.TEXTVIEW1); Button = (button) FIndviewbyid (R.id.button1); 
  Button.setonclicklistener (this); Private class Myserviceconnection implements serviceconnection{@Override public void onserviceconnecte D (componentname name, IBinder service) {LOG.I ("notification", "link success!") 
      "); 
      Remotebeauty = RemoteBeauty.Stub.asInterface (service); 
        try {Beauty Beauty = Remotebeauty.getbeauty (); 
         
         
      Textview.settext ("Beauty Name:" +beauty.getname () + "Age:" +beauty.getage () + "Gender:" +beauty.getsex ()); 
      catch (RemoteException e) {e.printstacktrace (); @Override public void onservicedisconnected (componentname name) {}} MyServ 
  Iceconnection connection = new Myserviceconnection (); 
    @Override public void OnClick (View v) {Intent Intent = new Intent (actionname); 
  Bindservice (Intent, connection, context.bind_auto_create); 

 } 
}

In addition, Beauty.java and Remotebeauty.aidl are all copied from the server system.

If you want your service to start when the system is powered on. You can add such a configuration to the androidmanifest.xml of the service.

<receiver android:name= ". Startbroadcastreceiver "> 

      <intent-filter>

  <action android:name=" android.intent.action.BOOT_ COMPLETED "/>

      </intent-filter>    

</receiver>

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.