Package cn.com. remoteServiceClient; import com.cn. aidl. IRemoteQuery; import android. app. activity; import android. content. componentName; import android. content. intent; import android. content. serviceConnection; import android. OS. bundle; import android. OS. IBinder; import android. view. view; import android. view. view. onClickListener; import android. widget. button; import android. widget. textView; // client step: // 1 custom Servic The eConnection class implements the ServiceConnection interface // RemoteQueryServiceConnection implements ServiceConnection // rewrite its method public void onServiceConnected (ComponentName, IBinder service) // The main purpose is to accept the Binder object passed by the server, that is, the IBinder service parameter of the method. // However, because AIDL protocol conversion exists, IBinder service is a proxy object. We must convert it to an interface type object. the Code is as follows: // public void onServiceConnected (ComponentName, IBinder service) {// remoteQueryBinder = IRemoteQuery. stub. asInterfac E (service); // strong conversion !! ///} // 2 use the implicit intent to activate the remote service // 3 Use remoteQueryBinder to call the methods in the service ////// AIDL client summary: // (1) use an implicit intent to activate the service, because the service and the client are not in the same application! // You cannot see each other, so it is "hidden". Therefore, you must use the implicit intent to activate the service. Therefore, you must configure the intent filter when declaring the service component in the file list! // (2) when receiving the Binder object returned by the server in the onServiceConnected () method, be sure to pay attention to it !!! // This is different from the local service !!! Because AIDL protocol conversion exists, IBinder service is a proxy object. // We must convert it to an interface type object remoteQueryBinder // that is, remoteQueryBinder = IRemoteQuery. stub. asInterface (service); Implement conversion // (3) Core Summary: // now we have finished writing both examples, and then let's look back, then we can find that both the local service and remote service are centered around a core: Get a Binder object ---> this Binder object has a significant feature: you can bind the service and complete some services. /// the implementation in the local service is as follows: the class of the Binder object inherits from the Binder and implements the business interface // you can use this interface to receive the Binder object when receiving the object (the parent class references the object pointing to the subclass object) //// the implementation in the remote service is: we need to write an aidl file. // then AIDL automatically generates a large Interface The core of this interface is the Stub class! It inherits from the Binder and // implements the business interface we have defined! So the returned Binder proxy object (note that it is a proxy object !) // The ability to "bind" services, also has the ability to complete the business method // so we can use the business interface to accept the returned Binder object or the Binder proxy object public class MainActivity extends Activity {TextView in the local and remote processes numberTextView; textView resultTextView; Button button; RemoteQueryServiceConnection conn = new RemoteQueryServiceConnection (); IRemoteQuery remoteQueryBinder; public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); numberTextView = (TextView) findViewById (R. id. number); resultTextView = (TextView) findViewById (R. id. result); button = (Button) findViewById (R. id. button); button. setOnClickListener (new ButtonOnClickListener (); Intent service = new Intent (); service. setAction ("com.cn. remoteService. remoteQueryService "); bindService (service, conn, this. BIND_AUTO_CREATE); // bind Service} private class ButtonOnClickListener implements OnClickListener {public void onClick (View v) {String number = numberTextView. getText (). toString (); String result; try {result = remoteQueryBinder. queryByNum (Integer. valueOf (number); resultTextView. setText (result);} catch (Exception e) {e. printStackTrace () ;}}// receives the bound service and disconnects the private final class RemoteQueryServiceConnection implements ServiceConnection {public void onServiceConnected (ComponentName, IBinder service) {remoteQueryBinder = IRemoteQuery. stub. asInterface (service);} public void onServiceDisconnected (ComponentName name) {remoteQueryBinder = null ;}} protected void onDestroy () {unbindService (conn); super. onDestroy ();}}
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/number" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/number" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button" android:id="@+id/button" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/result" /></LinearLayout>
Package com.cn. remoteService; import com.cn. aidl. IRemoteQuery; import android. app. service; import android. content. intent; import android. OS. IBinder; import android. OS. remoteException; // server step: // 1 generate the aidl file // create an interface, which can contain various methods. // make a slight modification to this interface so that "Interface Name" and "method name" are not modified (such as public )!! The Code is as follows: // interface IRemoteQuery {// String queryByNum (int number); //} // then locate the file path of the modified interface, follow this path to change its suffix. aidl // This generates the aidl file. note: The Interface Name and aidl file name must be the same. // 2 refresh the project. The system automatically generates an IRemoteQuery for remote communication. java // analyze this IRemoteQuery. java // (1) IRemoteQuery. java is actually an interface named IRemoteQuery // (2) The most important internal interface of IRemoteQuery is a Stub class (IRemoteQuery. stub), this class inherits from the Binder class and implements the IRemoteQuery business interface // the object of this class has the ability to remotely access /// 3 create a package on the client, the package name is the same as that of the aidl file! Copy the aidl file on the server to this package, and then refresh // It is found that IRemoteQuery is generated under the client gen. java /// 4 RemoteQueryService, which inherits from service /// 5 Write an internal class RemoteQueryBinder in RemoteQueryService to inherit from IRemoteQuery. stub // RemoteQueryBinder extends IRemoteQuery. stub // 6 override the public IBinder onBind (Intent intent) method of the service, and return a Binder object, that is, the RemoteQueryBinder class object, to the client. // summary of the aidl Server: // (1) the automatically generated Stub is the core point. The generated code shows that: it inherits from the Binder and implements our defined business interfaces // so it can be bound and called. Service capabilities (this is similar to the example of calling a local service just now) // (2) the definition of AIDL is similar to that of an interface, however, neither "Interface Name" nor "method name" is modified !!!! For example, public // (3) this package is required on both the client and server !! This is equivalent to a communication protocol !!! Both parties must comply with the rules. Therefore, make two copies !!! Public class RemoteQueryService extends Service {@ Overridepublic IBinder onBind (Intent intent) {return remoteQueryBinder;} RemoteQueryBinder remoteQueryBinder = new RemoteQueryBinder (); private String [] names = new String [] {"Xiao Ming", "Xiao Wang", "Xiao Yang", "Xiao Li"}; private final class RemoteQueryBinder extends IRemoteQuery. stub {@ Overridepublic String queryByNum (int number) throws RemoteException {return query (number) ;}} public String query (int I) {if (I> 0 & I <5) {return names [I-1];} return "query error, please input again ";}}
/** This file is auto-generated. do not modify. * Original file: D :\\ workspace \ queryByRemoteService \ src \ com \ cn \ aidl \ IRemoteQuery. aidl */package com.cn. aidl;/*** Note: * The definition of AIDL is similar to that of an interface, but neither "Interface Name" nor "method name" is modified !!!! For example, public */public interface IRemoteQuery extends android. OS. IInterface {/** Local-side IPC implementation stub class. */public static abstract class Stub extends android. OS. binder implements com.cn. aidl. IRemoteQuery {private static final java. lang. string DESCRIPTOR = "com.cn. aidl. IRemoteQuery ";/** Construct the stub at attach it to the interface. */public Stub () {this. attachInterface (this, DESCRIPTOR) ;}/*** Cast an IBinder object into an com.cn. aidl. IRemoteQuery interface, * generating a proxy if needed. */public static com.cn. aidl. IRemoteQuery asInterface (android. OS. IBinder obj) {if (obj = null) {return null;} android. OS. IInterface iin = obj. queryLocalInterface (DESCRIPTOR); if (iin! = Null) & (iin instanceof com.cn. aidl. IRemoteQuery) {return (com.cn. aidl. IRemoteQuery) iin);} return new com.cn. aidl. IRemoteQuery. stub. proxy (obj) ;}@ Override public android. OS. IBinder asBinder () {return this ;}@ Override public boolean onTransact (int code, android. OS. parcel data, android. OS. parcel reply, int flags) throws android. OS. remoteException {switch (code) {case INTERFACE_TRANSACTION: {reply. writeString (DESCRIPTOR); return true;} case TRANSACTION_queryByNum: {data. enforceInterface (DESCRIPTOR); int _ arg0; _ arg0 = data. readInt (); java. lang. string _ result = this. queryByNum (_ arg0); reply. writeNoException (); reply. writeString (_ result); return true ;}} return super. onTransact (code, data, reply, flags);} private static class Proxy implements com.cn. aidl. IRemoteQuery {private android. OS. IBinder mRemote; Proxy (android. OS. IBinder remote) {mRemote = remote;} @ Override public android. OS. IBinder asBinder () {return mRemote;} public java. lang. string getInterfaceDescriptor () {return DESCRIPTOR;} @ Override public java. lang. string queryByNum (int number) throws android. OS. remoteException {android. OS. parcel _ data = android. OS. parcel. obtain (); android. OS. parcel _ reply = android. OS. parcel. obtain (); java. lang. string _ result; try {_ data. writeInterfaceToken (DESCRIPTOR); _ data. writeInt (number); mRemote. transact (Stub. TRANSACTION_queryByNum, _ data, _ reply, 0); _ reply. readException (); _ result = _ reply. readString ();} finally {_ reply. recycle (); _ data. recycle ();} return _ result;} static final int TRANSACTION_queryByNum = (android. OS. IBinder. FIRST_CALL_TRANSACTION + 0);} public java. lang. string queryByNum (int number) throws android. OS. remoteException ;}