在Andorid平臺(tái)中,各個(gè)組件運(yùn)行在自己的進(jìn)程中,他們之間是不能相互訪問(wèn)的,但是在程序之間是不可避免的要傳遞一些對(duì)象,在進(jìn)程之間相互通信。為了實(shí)現(xiàn)進(jìn)程之間的相互通信,Andorid采用了一種輕量級(jí)的實(shí)現(xiàn)方式RPC(Remote Procedure Call 遠(yuǎn)程進(jìn)程調(diào)用)來(lái)完成進(jìn)程之間的通信,并且Android通過(guò)接口定義語(yǔ)言(Andorid Interface Definition Language ,AIDL)來(lái)生成兩個(gè)進(jìn)程之間相互訪問(wèn)的代碼,例如,你在Activity里的代碼需要訪問(wèn)Service中的一個(gè)方法,那么就可以通過(guò)這種方式來(lái)實(shí)現(xiàn)了。
成都創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站制作、做網(wǎng)站與策劃設(shè)計(jì),汪清網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:汪清等地區(qū)。汪清做網(wǎng)站價(jià)格咨詢:13518219792
AIDL是Android的一種接口描述語(yǔ)言; 編譯器可以通過(guò)aidl文件生成一段代碼,通過(guò)預(yù)先定義的接口達(dá)到兩個(gè)進(jìn)程內(nèi)部通信進(jìn)程的目的. 如果需要在一個(gè)Activity中, 訪問(wèn)另一個(gè)Service中的某個(gè)對(duì)象, 需要先將對(duì)象轉(zhuǎn)化成 AIDL可識(shí)別的參數(shù)(可能是多個(gè)參數(shù)), 然后使用AIDL來(lái)傳遞這些參數(shù), 在消息的接收端, 使用這些參數(shù)組裝成自己需要的對(duì)象。
AIDL RPC機(jī)制是通過(guò)接口來(lái)實(shí)現(xiàn)的,類似Windows中的COM或者Corba,但他是輕量級(jí)的,客戶端和被調(diào)用實(shí)現(xiàn)之間是通過(guò)代理模式實(shí)現(xiàn)的,代理類和被代理類實(shí)現(xiàn)同一個(gè)接口Ibinder接口。
下面是實(shí)現(xiàn)Activity訪問(wèn)Service例子的步驟:
一.創(chuàng)建.aidl文件
AIDL使用簡(jiǎn)單的語(yǔ)法來(lái)聲明接口,描述其方法以及方法的參數(shù)和返回值。這些參數(shù)和返回值可以是任何類型,甚至是其他AIDL生成的接口。重要的是必須導(dǎo)入導(dǎo)入除了內(nèi)建類型(例如:int,boolean等)外的任何其他類型,哪怕是這些類型是在與接口相同的包中。具體的要求如下:
JAVA基本數(shù)據(jù)類型不需要導(dǎo)入
String,List,Map和CharSequence不需要導(dǎo)入
使用Eclipse的ADT插件創(chuàng)建一個(gè)BookInfo.aidl文件,該文件有4個(gè)方法:
setName(String name)設(shè)置圖書(shū)的書(shū)名,setPrice(int price)設(shè)置圖書(shū)的價(jià)格,setPublish(String pname)設(shè)置圖書(shū)的出版社和String display()顯示圖書(shū)的信息.
BookInfo.aidl文件
package com.android.aidl; //BookInfo接口 interface BookInfo{ void setName(String name); void setPrice(int price); void ssetPublish(String pname); //顯示圖書(shū)的信息 String display(); }
創(chuàng)建好BookInfo.aidl文件,系統(tǒng)會(huì)自動(dòng)在gen目錄下生成Java接口文件BookInfo.java
二.實(shí)現(xiàn)AIDL文件生成的JAVA接口
AIDL會(huì)生成一個(gè)和.aidl文件同名的JAVA接口文件,該接口中有一個(gè)靜態(tài)抽象內(nèi)部類Stub,該類中聲明了AIDL文件中定義的所有方法,其中有一個(gè)重要的方法是asInterface(),該方法通過(guò)代理模式返回JAVA接口的實(shí)現(xiàn)我們可以定義一個(gè)實(shí)現(xiàn)類,BookImpl,該類繼承Stub類,實(shí)現(xiàn)我們定義的4個(gè)方法
package com.android.aidl; import android.os.RemoteException; public class BookInfoImpl extends BookInfo.Stub { //聲明三個(gè)個(gè)變量 private int price; private String name,pname; //顯示書(shū)名,價(jià)格,出版社 public String display() throws RemoteException{ return "書(shū)名:"+name+";價(jià)格:"+price+";出版社:"+price; } @Override //設(shè)置書(shū)名 public void setName(String name) throws RemoteException { // TODO Auto this.name= name; } @Override //設(shè)置價(jià)格 public void setPrice(int price) throws RemoteException { // TODO Auto-generated method stub this.price = price; } @Override //設(shè)置出版社 public void setPublish(String pname) throws RemoteException { // TODO Auto this.pname= pname; } }
三.向客戶端暴露接口
現(xiàn)在已經(jīng)實(shí)現(xiàn)了BookInfo接口,接下來(lái)要將該接口暴露給客戶端調(diào)用。一般通過(guò)定義一個(gè)Service來(lái)實(shí)現(xiàn),在Service的onBind()方法中返回該接口,當(dāng)我們綁定該接口時(shí)調(diào)用該方法。
package com.android.aidl; import com.android.aidl.BookInfo.Stub; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class RemoteService extends Service { //聲明BookInfo接口 private Stub bookifo = new BookInfoImpl(); public IBinder onBind(Intent intent){ return bookifo; } }
四.在客戶端調(diào)用
定義一個(gè)Activity來(lái)綁定遠(yuǎn)程Service,獲得BookInfo接口,通過(guò)RPC機(jī)制調(diào)用接口中的方法。
package com.android.aidl; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { // 聲明IPerson接口 private BookInfo bookInfo; // 聲明 Button private Button btn; // 實(shí)例化ServiceConnection private ServiceConnection conn = new ServiceConnection() { @Override synchronized public void onServiceConnected(ComponentName name, IBinder service) { // 獲得IPerson接口 bookInfo = BookInfo.Stub.asInterface(service); if (bookInfo != null) try { // RPC 方法調(diào)用 bookInfo.setName("Google Android SDK開(kāi)發(fā)范例大全"); bookInfo.setPrice(55); bookInfo.setPublish("人民郵電出版社"); String msg = bookInfo.display(); // 顯示方法調(diào)用返回值 Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG) .show(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 設(shè)置當(dāng)前視圖布局 setContentView(R.layout.main); // 實(shí)例化Button btn = (Button) findViewById(R.id.Button1); //為Button添加單擊事件監(jiān)聽(tīng)器 btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 實(shí)例化Intent Intent intent = new Intent(); // 設(shè)置Intent Action 屬性 intent.setAction("com.android.aidl.action.MY_REMOTE_SERVICE"); // 綁定服務(wù) bindService(intent, conn, Service.BIND_AUTO_CREATE); } }); } }
五.main.xml和AndroidManifest.xml文件
main.xml
在AndroidManifest.xml文件16~20聲明Service
效果圖: