Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 淺談binder機制

淺談binder機制

編輯:關於Android編程

前段時間一直在看有關Binder的知識,最近剛好有時間,總結一些一些知識,希望和大家交流學習。

說起Binder我相信大家學android開發的多多少少都對binder有些了解,binder機制作為android進程間通信的一種機制,在Android底層中應用的非常多。我們都知道Android系統是基於LInux內核開發的,Linux內核提供了豐富的進程間通信的機制,如:管道、信號、消息隊列、共享內存和套接字等,但是Android系統並沒有采用傳統的進程間通信機制,而是開發了一套新的進程間通信的機制BInder,當然采用Binder肯定有一些優勢,與傳統的進程間通信相比,BInder進程通信機制在進程間傳輸數據的時候,只需要執行一次拷貝操作,因此,在效率和內存節省方面有一定的優勢。

接下來我們就開始談談Binder了,Binder說白了就是Android中的一個類,它實現了Ibinder接口,從Android-Framework角度來說,Binder是ServiceManager連接各種Manager(ActivityManager、WindowManager等)和相應的Manager_Service的橋梁;下面有一張他們之間的圖

 

Binder在進行進程間通信的時候,每一個Server進程和Client進程都維護一個Binder線程池來處理進程間的通信要求,Service組件在啟動時,會將自己注冊到一個Service Manager組件中,以便Client組件可以通過Service Manager組件找到它。上圖中Binder驅動程序和Service Manager由系統提供,Client和Service由應用程序實現,接下來我已我們Android中最常用的AIDL為例討論一下

編寫一個AIDL程序需要以下幾步:

 

首先我們看看服務端程序需要的步驟:

(1)首先編寫你的類(book.java)文件,這個類必須實現Parcelable接口進行序列化。

(2)編寫與該類相同的名的aidl文件(book.aidl)

(3)編寫接口文件(IBookManager.aidl),此接口即客戶端請求時的接口

(4)實現服務端的service(BookManagerService),該service為客戶端實際進行服務(主要實現Stub類)

 

接下來我們看看客戶端要實現的步驟:

客戶端其實與服務端很多地方相似:

(1)我們這一塊需要將服務端的所有AIDL文件拷貝帶客戶端,這裡的報名必須與服務端一致,因為存在序列化與反序列化問題

(2)編寫客戶端Activity,綁定服務端service

(3)實現ServiceConnection,在onServiceConnected方法中,將講IBinder轉化為AIDL接口類型,然後調用遠程服務

(4)如果遠程服務比較耗時,可以將調用方法從主線程中分離出來,開一個子線程,這樣程序就不會崩潰

 

好吧,大家現在估計也是很懵逼的吧,我再給大家理一遍然後就上代碼了:

首先大家可以看到,當我們新建一個AIDL文件之後,在gen文件夾下會生成一個對應的AIDL文件,他是系統為我們自動生成的一個接口類,繼承自android.os.IInterface接口,其中有幾個比較重要的類和方法這裡我給大家一一說明:

首先是stub類,這個Stub類繼承BInder實現了我們定義的AIDL接口,這個類也是我們客戶端在實際要用到的類,在這個類中有一個asInterface方法,他的參數是一個IBinder接口,他返回了另一個Stub的內部類proxy,這個proxy類真正實現了AIDL接口,每當客戶端通過Stub的asInterface方法獲取到該類時,調用具體的接口方法時,proxy類裡面會調用transact,當客戶端和服務端都位於一個進程時,方法調用就不會走跨進程的transact過程,如果不在同一個進程的話將會交給Proxy的處理,這裡transact有幾個參數第一個參數為請求的方法類型,接下來_data與_reply他們兩個是一個parcel類型,其中分別封裝客戶端的請求信息和服務端反饋的信息,然後底層通過Bindler傳送到onTransact方法中,他會從客戶端傳過來的參數中判斷客戶端請求的是那個方法,裡面的請求信息是什麼,接下來會將數據寫入,返回到客戶端。

上面就是BInder跨進程的的整個流程,下面就是上代碼了:

AIDL文件

 

Book.java
package com.binderpro.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable{
	private String name;
	private int price;
	private int bookId;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public Book(String name, int price) {
		super();
		this.name = name;
		this.price = price;
	}
	@Override
	public String toString() {
		return "Book [name=" + name + ", price=" + price + "]";
	}
	@Override
	public int describeContents() {
		// TODO Auto-generated method stub
		return 0;
	}
	@Override
	public void writeToParcel(Parcel arg0, int arg1) {
		// TODO Auto-generated method stub
		arg0.writeInt(bookId);
		arg0.writeString(name);
		arg0.writeInt(price);
	}
	public static final Parcelable.Creator CREATOR = new Parcelable.Creator(){

		@Override
		public Book createFromParcel(Parcel arg0) {
			// TODO Auto-generated method stub
			return new Book(arg0);
		}

		@Override
		public Book[] newArray(int arg0) {
			// TODO Auto-generated method stub
			return new Book[arg0];
		}
	
	};
	private Book(Parcel in){
		bookId = in.readInt();
		name = in.readString();
		price = in.readInt();
	}
}
Book.aidl
package com.binderpro.aidl;

parcelable Book;

 

IBookManager

 

package com.binderpro.aidl;

import java.util.List;
import com.binderpro.aidl.Book;
interface IBookManager {
	List getBookList();
	void addBook(in Book book);

}

 

BookManagerService

 

package com.example.binderpro;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;

import com.binderpro.aidl.Book;
import com.binderpro.aidl.IBookManager;

public class BookManagerService extends Service {
	private static final String TAG = "BMS";
	private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();
	public BookManagerService() {
		// TODO Auto-generated constructor stub
	}
	private  Binder mBinder = new IBookManager.Stub() {
		
		@Override
		public List getBookList() throws RemoteException {
			// TODO Auto-generated method stub
			return mBookList;
		}
		
		@Override
		public void addBook(Book book) throws RemoteException {
			// TODO Auto-generated method stub
			mBookList.add(book);
		}
	};

	
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		mBookList.add(new Book("android", 1));
		mBookList.add(new Book("ios", 2));
	}
	public IBinder onBind(Intent intent){
		return mBinder;
	}
}

接下來是客戶端代碼,aidl文件同上

 

MainActivity.java

 

package com.example.binderpro;

import java.util.List;

import com.binderpro.aidl.Book;
import com.binderpro.aidl.IBookManager;


import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {

	private ServiceConnection mConnection = new ServiceConnection() {

		@Override
		public void onServiceDisconnected(ComponentName arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onServiceConnected(ComponentName arg0, IBinder arg1) {
			// TODO Auto-generated method stub
			IBookManager bookManager = IBookManager.Stub.asInterface(arg1);
			List list;
			try {
				list = bookManager.getBookList();
				Log.i("Tag", list.toString());
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	};

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Intent intent = new Intent("com.example.binderpro.BookManagerService");

		bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		unbindService(mConnection);

	}

}

最後是系統根據AIDL文件生成的java代碼;

 

IBookManager代碼比較長,我刪除了一部分

 

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: G:\\android_code\\Binderpro\\src\\com\\binderpro\\aidl\\IBookManager.aidl
 */
package com.binderpro.aidl;

public interface IBookManager extends android.os.IInterface {
	/** Local-side IPC implementation stub class. */
	public static abstract class Stub extends android.os.Binder implements
			com.binderpro.aidl.IBookManager {
		private static final java.lang.String DESCRIPTOR = "com.binderpro.aidl.IBookManager";

		/** Construct the stub at attach it to the interface. */
		public Stub() {
			this.attachInterface(this, DESCRIPTOR);
		}

		/**
		 * Cast an IBinder object into an com.binderpro.aidl.IBookManager
		 * interface, generating a proxy if needed.
		 */
		public static com.binderpro.aidl.IBookManager asInterface(
				android.os.IBinder obj) {
			if ((obj == null)) {
				return null;
			}
			android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
			if (((iin != null) && (iin instanceof com.binderpro.aidl.IBookManager))) {
				return ((com.binderpro.aidl.IBookManager) iin);
			}
			return new com.binderpro.aidl.IBookManager.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_getBookList: {
				data.enforceInterface(DESCRIPTOR);
				java.util.List _result = this
						.getBookList();
				reply.writeNoException();
				reply.writeTypedList(_result);
				return true;
			}
			case TRANSACTION_addBook: {
				data.enforceInterface(DESCRIPTOR);
				com.binderpro.aidl.Book _arg0;
				if ((0 != data.readInt())) {
					_arg0 = com.binderpro.aidl.Book.CREATOR
							.createFromParcel(data);
				} else {
					_arg0 = null;
				}
				this.addBook(_arg0);
				reply.writeNoException();
				return true;
			}
			}
			return super.onTransact(code, data, reply, flags);
		}

		private static class Proxy implements com.binderpro.aidl.IBookManager {
			private android.os.IBinder mRemote;

	

			@Override
			public java.util.List getBookList()
					throws android.os.RemoteException {
				android.os.Parcel _data = android.os.Parcel.obtain();
				android.os.Parcel _reply = android.os.Parcel.obtain();
				java.util.List _result;
				try {
					_data.writeInterfaceToken(DESCRIPTOR);
					mRemote.transact(Stub.TRANSACTION_getBookList, _data,
							_reply, 0);
					_reply.readException();
					_result = _reply
							.createTypedArrayList(com.binderpro.aidl.Book.CREATOR);
				} finally {
					_reply.recycle();
					_data.recycle();
				}
				return _result;
			}

			@Override
			public void addBook(com.binderpro.aidl.Book book)
					throws android.os.RemoteException {
				android.os.Parcel _data = android.os.Parcel.obtain();
				android.os.Parcel _reply = android.os.Parcel.obtain();
				try {
					_data.writeInterfaceToken(DESCRIPTOR);
					if ((book != null)) {
						_data.writeInt(1);
						book.writeToParcel(_data, 0);
					} else {
						_data.writeInt(0);
					}
					mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
					_reply.readException();
				} finally {
					_reply.recycle();
					_data.recycle();
				}
			}
		}

		static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
		static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
	}
}

今天大概就講這麼多,最近我也正在研究一些關於Binder底層的東西,可能後續感覺自己能力到了會寫一些關於Binder底層的東西,因為Binder實在太復雜了,在linux驅動層好多都是C代碼,在底層都是以好多結構體和一些紅黑樹,hash表,引用鏈組織起來,其中一些Binder線程池、同步、緩沖區、死亡通知之間的關聯十分復雜,有興趣的可以看看羅升陽的《Android系統源碼情景分析》這本書對於Binder底層機制講的非常好。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved