編輯:關於Android編程
package com.aidl; import android.os.Parcel; import android.os.Parcelable; public class Person implements Parcelable { // 自定義的類型具體包含的數據,本例為age和name。 private intage = 0; private String name = null; // 這個構造函數,是方便我們在client中創新相關對象,並將之作為接口連接中調用方法的的參數 public Person() { } /*提供構造函數,用於從Parcel中創建對象,也即是讀的過程。這裡設置為private,禁止外部調用 */ private Person(Parcel in) { readFromParcel(in); } @Override publicint describeContents() { return 0; } /* * 【2】要實現Parcelable接口,需要實現writeToParcel()和readFromParcel(),實現將對象(數據)寫入Parcel, * 和從Parcel中讀出對象 * 。需要注意,寫的順序和讀的順序必須一致,因為Parcel類是快速serialization和deserialization機制 * ,和bundle不同,沒有索引機制,是線性的數據存貯和讀取。 * 注意其中readFromParcel()並不是overrider,而是我們自己提供的方法,如果我們不提供,就要在 private * Person(Parcel in){ age = in.readInt(); name = in.readString(); } * 鑒於實際的數據類型會比小例子復雜,以及便於代碼閱讀,我們仿照writeToParcel()的命名,給出readFromParcel() */ @Override public void writeToParcel(Parcel out, int flag) { out.writeInt(age); // 先寫入age out.writeString(name); // 其次寫如name } public void readFromParcel(Parcel in) { age = in.readInt(); // 先讀出age,保持與寫同順序 name = in.readString(); // 其次讀出name,保持與寫同順序 } /* * 實現Parcelable接口的類必須要有一個static * field稱為CREATOR,用於實現Parcelable.Creator接口的對象 * 。在AIDL文件自動生成的Java接口中,IBinder將調用Parcelable.Creator來獲得傳遞對象:_arg1 = * cn.wei.flowingflying * .proandroidservice.Person.CREATOR.createFromParcel(data); */ public static final Parcelable.CreatorCREATOR = new Parcelable.Creator () { @Override public Person createFromParcel(Parcel source) { return new Person(source); } @Override public Person[] newArray(int size) { return new Person[size]; } }; /* 一系列getter,setter方法 */ publicint getAge() { returnage; } public String getName() { returnname; } publicvoid setAge(intage) { this.age = age; } publicvoid setName(String name) { this.name = name; } }
要在進程間傳遞非本地對象,要注意必須實現Parcelable接口。通過重寫public void writeToParcel(Parcel out, int flag)來將對象的屬性保存到傳遞出去的Parcel對象。此外還必須實現一個公共靜態的Creator域:Parcelable.Creator
package com.aidl; parcelable Person;
package com.aidl; import com.aidl.Person; interface IMyService { Map getPersonAll(in String tag, in Person person); Person getPerson(); }
類似於定義interface,可以再次提供相應的屬性和方法。方法也可以接受零到多個參數。參數需要使用(in,out,inout)來修飾。
/* * This file is auto-generated. DO NOT MODIFY. * Original file: F:\\Android Workspace\\AIDLServer\\src\\com\\aidl\\IMyService.aidl */ package com.aidl; public interface IMyService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.aidl.IMyService { private static final java.lang.String DESCRIPTOR = "com.aidl.IMyService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.aidl.IMyService interface, * generating a proxy if needed. */ public static com.aidl.IMyService asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.aidl.IMyService))) { return ((com.aidl.IMyService) iin); } return new com.aidl.IMyService.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_getPersonAll: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); com.aidl.Person _arg1; if ((0 != data.readInt())) { _arg1 = com.aidl.Person.CREATOR.createFromParcel(data); } else { _arg1 = null; } java.util.Map _result = this.getPersonAll(_arg0, _arg1); reply.writeNoException(); reply.writeMap(_result); return true; } case TRANSACTION_getPerson: { data.enforceInterface(DESCRIPTOR); com.aidl.Person _result = this.getPerson(); reply.writeNoException(); if ((_result != null)) { reply.writeInt(1); _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { reply.writeInt(0); } return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.aidl.IMyService { 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.util.Map getPersonAll(java.lang.String tag, com.aidl.Person person) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.util.Map _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(tag); if ((person != null)) { _data.writeInt(1); person.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_getPersonAll, _data, _reply, 0); _reply.readException(); java.lang.ClassLoader cl = (java.lang.ClassLoader) this .getClass().getClassLoader(); _result = _reply.readHashMap(cl); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public com.aidl.Person getPerson() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); com.aidl.Person _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getPerson, _data, _reply, 0); _reply.readException(); if ((0 != _reply.readInt())) { _result = com.aidl.Person.CREATOR .createFromParcel(_reply); } else { _result = null; } } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final intTRANSACTION_getPersonAll = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final intTRANSACTION_getPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public java.util.Map getPersonAll(java.lang.String tag, com.aidl.Person person) throws android.os.RemoteException; public com.aidl.Person getPerson() throws android.os.RemoteException; }
注意源碼中實現了stub類:抽象類,繼承了Binder
public static abstract class Stub extends android.os.Binder implements com.aidl.IMyService
4、接下來實現服務器端的service:
package com.aidl; public class MyService extends Service{ /*Service擴展Stub並實現要求的功能,相當於implements生成的IMyService.java*/ public class MyServiceImpl extends IMyService.Stub { @Override public Map getPersonAll(String tag, Person person) throws RemoteException { Mapmap = new HashMap (); map.put("tag", tag); map.put("name", person.getName()); map.put("age", String.valueOf(person.getAge())); map.put("person", person.toString()); return map; } @Override public Person getPerson() throws RemoteException { return new Person(); } } @Override public IBinder onBind(Intent intent) { return new MyServiceImpl(); } }
在mainfest文件中注冊service:
5、在客戶端的Activity中綁定使用Service
package com.example.aidlclient; import com.aidl.IMyService; import com.aidl.Person; public class MainActivity extends Activity { private Button mybu; private final static String ACTION_TAG = "com.aidl.action.IMyService"; //MyService可以當做普通的Service形式進行調用 private IMyService iMyService; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //獲得service的實例 iMyService = IMyService.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { iMyService = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mybu = (Button) findViewById(R.id.mybu); //綁定Service bindService(new Intent(ACTION_TAG), serviceConnection, Context.BIND_AUTO_CREATE); mybu.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { doWithService(); } catch (RemoteException e) { } } }); } /*******操作Service提供的服務 * @throws RemoteException ************/ private void doWithService() throws RemoteException { Person person = iMyService.getPerson(); person.setAge(10); person.setName("Mary"); Log.i("doWithService", "getName :" + person.getName()); Log.i("doWithService", "getAge :" + String.valueOf(person.getAge())); Log.i("doWithService", "getPersonAll :" + iMyService.getPersonAll("Map", person)); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { intid = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
使用bindService(new Intent(ACTION_TAG), serviceConnection, Context.BIND_AUTO_CREATE);來對Service進行綁定。
在onServiceConnected中通過iMyService = IMyService.Stub.asInterface(service);來獲取實例;進而通過Service調用相關服務。客戶端在執行bindService的時候,成功綁定服務之後,會回調mConnection的onServiceConnected(),並且傳回了服務端的通信接口IBinder,此IBinder即服務onBind()時返回的IBinder,詳見mAIDLService.java。
在onServiceConnected(),客戶端成功獲取了服務端通信接口,實際上是本地代理對象,該對象存在於客戶端進程空間,客戶端只和代理對象交互,真正的IPC通信是本地代理對象和服務端的通信。
整個交互流程如下:
1.客戶端通過綁定服務,獲取了服務的句柄(本地代理對象);
2.客戶端執行onClick(),調用本地代理對象的get()等函數,本地代理對象調用mRemote.transact()發出遠程調用請求;
3.服務端響應onTransact()執行this.get(),並將執行結果返回;
由於客戶端只和本地代理對象即服務句柄通信,由代理對象進行真正的IPC操作,所以對客戶端來說,IPC過程是透明的,調用遠程操作如同調用本地操作一樣。在客戶端調用transact()時,會將服務描述DSCRIPTION寫入到data裡,在客戶端onTransact時會驗證,如果兩個不一樣,則不能通信。而DSCRIPTION是根據mInterface包名和接口名自動生成的,這就是為什麼兩個工程裡的aidl文件要在同一個包的原因。
在這個過程中,aidl起到了橋梁的作用,規定統一了客戶端和服務端的通信接口,使得客戶端和服務端得以成功的通信。
具體的通信transact和onTransact的過程也就是利用Binder驅動通信的過程。
本文實例為大家分享了Android圓形菜單的使用方法,供大家參考,具體內容如下MainActivity.java代碼:package siso.handlerdemo;i
本文將講述android點擊事件的分發過程我的上一篇文章講述了android點擊事件的來源,本文接著講述當點擊事件傳輸到Activity之後 分發的過程是什麼樣的。通過上
周三谷歌推出下一個流行的移動操作系統Android L。但是只提供了簡單地預覽版本,稍後將提供一個開發者預覽版,完整版計劃在今年秋天發布。 下面我們一起來看看如何
為什麼要使用異步任務?Android 單線程模型,多線程的操作系統耗時操作放在非主線程中運行AsyncTask 為何而生?子線程中更新UI封裝簡化異步操作構建AsyncT