android aidl 使用實例

最近在看Binder的實現機制,但是感覺總不是很清晰,所以想理解他的實現原理,先暫時學會怎麼使用。Binder是android中的一種進程間通信機制,

android的底層是Linux系統,Linux系統中進程間通信方式主要有以下幾種:

1、socket,即客戶端服務器模式。所以我們客戶端程序通過socket和服務器端程序進行通信,其實就是進程間通信的一個實例。

2、傳統的消息隊列機制

3、共享內存機制

4、信號量機制

在android系統中,由於安全性等一些其他因素影響,所以android的開發者們實現了另外一種進程間通信方式Binder,android中所有的進程間通信方式

都是通過Binder以及以上4種方式來實現的,ContentProvider實現的進程間數據共享方式就是通過共享內存以及Binder方式來實現進程間通信的,具體

的詳細解釋可以參考老羅的這篇博客:http://blog.csdn.net/luoshengyang/article/details/6946067。android的RPC機制(遠程過程調用)也是通過Binder

機制來實現的,RPC其實就是IPC機制的一種實現方式,IPC即Interprocess communication 進程間通信,實現IPC有很多方式,但是有時候我們並不滿

足於僅僅實現數據通信,有時候我們還需要去調用其它進程間的方法或對象,這時就需要RPC機制了,而android中就是通過AIDL來實現這樣一種RPC

機制。具體關於RPC的定義可以google去看wiki的介紹。下面我們就來看看android的RPC機制是怎樣通過AIDL(接口定義語言)來實現進程間的方法或對

象調用的。

一 、新建遠程調用app(即新建一個進程),實現遠程方法調用

1、新建一個AIDL文件RemoteServiceAidl.aidl,定義幾個方法,分別以基本類型數據和對象作爲參數。定義好之後會在工程的gen目錄下生成相同的包

名以及相同文件名的java文件RemoteServiceAidl.java,他的代碼我就不貼出來了。

package com.lonuery.aidl;

import com.lonuery.remote.GroupInfo;

interface RemoteServiceAidl {

	int calculate(int num1,int num2);
	void checkInfo(String str,double data);
	
	String save(in GroupInfo groupInfo);
	
}

2、由於AIDL中傳遞基本數據類型和對象的方式不同,傳遞對象就必須實現Parcelable接口,接下來定義GroupInfo類

public class GroupInfo implements Parcelable{
	
	String name,groupId,memCount;
	
	public GroupInfo(String name,String groupId,String memCount){
		this.name = name;
		this.groupId = groupId;
		this.memCount = memCount;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getGroupId() {
		return groupId;
	}
	
	public void setGroupId(String groupId) {
		this.groupId = groupId;
	}
	
	public String getMemCount() {
		return memCount;
	}
	
	public void setMemCount(String memCount) {
		this.memCount = memCount;
	}
	
	@Override
	public int describeContents() {
		return 0;
	}
	
	@Override
	public void writeToParcel(Parcel parcel, int arg1) {
		//參數的寫入是什麼順序,那麼下面參數的讀取就應該是什麼順序。參數的寫入順序不對,會導致讀取的參數順序不對
		parcel.writeString(this.name);
		parcel.writeString(this.groupId);
		parcel.writeString(this.memCount);
	}
	//如果要傳遞對象那麼這個類中就必須創建一個名字爲CREATOR的Creator對象。
	public static final Parcelable.Creator<GroupInfo> CREATOR = 
				new Parcelable.Creator<GroupInfo>() {

		@Override
		public GroupInfo createFromParcel(Parcel parcel) {
			return new GroupInfo(parcel.readString(), parcel.readString(), parcel.readString());
		}

		@Override
		public GroupInfo[] newArray(int size) {
			return new GroupInfo[size];
		}
	};
}

3、在GroupInfo.java相同包下定義GroupInfo.aidl文件。

package com.lonuery.remote;

parcelable GroupInfo;

3、實現RemoteServiceAidl.Stub類,並且定義一個Service以供其他程序來遠程綁定,返回Stub的對象。

public class RemoteService extends Service{

	String TAG = "RemoteService";
	AidlImpl aidlService = new AidlImpl();
	@Override
	public IBinder onBind(Intent arg0) {
		Log.v(TAG, "onBind");
		return aidlService;
	}
	
	class AidlImpl extends RemoteServiceAidl.Stub{

		@Override
		public int calculate(int num1, int num2) throws RemoteException {
			int result = num1*num2;
			
			return result;
		}

		@Override
		public void checkInfo(String str, double data) throws RemoteException {
			if(str!=null){		
				Log.v("checkInfo", "輸出");
			}
		}

		@Override
		public String save(GroupInfo groupInfo) throws RemoteException {
			String str = null;
			if(groupInfo!=null){
				if(groupInfo.getGroupId().equals("電話")){
					str = "地方金額1";
				}else if(groupInfo.getMemCount().equals("電話")){
					str = "地方金額2";
				}else if(groupInfo.getName().equals("電話")){
					str = "地方金額3";
				}
			}
			return str;	
		}
	}
}

二、新建調用app即新建調用進程

1、在新建的調用app中新建和RemoteServiceAidl.aidl相同的包名,並將RemoteServiceAidl.aidl複製到這個包中。同樣,在gen目錄下也會自動生成

RemoteServiceAidl.java的文件。

2、新建和GroupInfo.java相同的包名並將GroupInfo.java和GroupInfo.aidl文件複製到此包中。

3、綁定遠程服務,利用遠程服務對象,調用遠程方法。

public class MainActivity extends Activity implements OnClickListener{

	Button btn1;
	RemoteServiceAidl remoteService;
	TextView tv;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		btn1 = (Button)findViewById(R.id.button1);		
		btn1.setOnClickListener(this);
		
		tv = (TextView)findViewById(R.id.textView1);
		
		bindService(new Intent(RemoteServiceAidl.class.getName()), connection, 
				Context.BIND_AUTO_CREATE);
		
	}
	
	@Override
	public void onClick(View view) {
		if(view.getId()==R.id.button1){
			try {
				int result=0;
				GroupInfo info = new GroupInfo("", "電話", "");
				String str=null;
				try {
					result = remoteService.calculate(6, 8);
					str = remoteService.save(info);
				} catch (DeadObjectException e) {
					e.printStackTrace();
				}
				tv.setText("result:"+result);				
				String text = tv.getText().toString() + "Id:"+str;
				tv.setText(text);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}	
	}

	@Override
	protected void onDestroy() {
		unbindService(connection);
		super.onDestroy();
	}
	
	private ServiceConnection connection = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName arg0) {
			remoteService = null;
		}
		
		@Override
		public void onServiceConnected(ComponentName arg0, IBinder binder) {
			remoteService = RemoteServiceAidl.Stub.asInterface(binder);
		}
	};
}

4、在AndroidManifest.xml中對所創建的服務進行註冊。

接下來我們分別安裝遠程app,和調用app,來看一下效果。

好了android中aidl的使用實例就完成了,接下來我們總結一下:

1、RemoteService只是一個代理的角色,他的作用就是讓其他的進程來綁定他,然後通過他進行遠程方法調用,真正的調用其實是在

RemoteServiceAidl.Stub的實現類AidlImpl中實現的。

2、將AidlImpl類的對象返回給RemoteService的綁定接口onBind,遠程調用就是通過這個接口來獲取AidlImpl對象,繼而實現方法的調用。

3、遠程進程通過bindService方法綁定遠程服務RemoteService。

實例已經上傳到csdn上http://download.csdn.net/detail/zkw12358/7362967

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章