編輯:關於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.Creator CREATOR = 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 {
Map map = 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學習教程之圓形Menu菜單制作方法(1)
本文實例為大家分享了Android圓形菜單的使用方法,供大家參考,具體內容如下MainActivity.java代碼:package siso.handlerdemo;i
android點擊事件的分發過程
本文將講述android點擊事件的分發過程我的上一篇文章講述了android點擊事件的來源,本文接著講述當點擊事件傳輸到Activity之後 分發的過程是什麼樣的。通過上
如何獲取和安裝Android L開發者預覽版
周三谷歌推出下一個流行的移動操作系統Android L。但是只提供了簡單地預覽版本,稍後將提供一個開發者預覽版,完整版計劃在今年秋天發布。 下面我們一起來看看如何
AsyncTask 流程解析
為什麼要使用異步任務?Android 單線程模型,多線程的操作系統耗時操作放在非主線程中運行AsyncTask 為何而生?子線程中更新UI封裝簡化異步操作構建AsyncT