您好,登錄后才能下訂單哦!
在Andorid平臺中,各個組件運行在自己的進程中,他們之間是不能相互訪問的,但是在程序之間是不可避免的要傳遞一些對象,在進程之間相互通信。為了實現(xiàn)進程之間的相互通信,Andorid采用了一種輕量級的實現(xiàn)方式RPC(Remote Procedure Call 遠程進程調(diào)用)來完成進程之間的通信,并且Android通過接口定義語言(Andorid Interface Definition Language ,AIDL)來生成兩個進程之間相互訪問的代碼,例如,你在Activity里的代碼需要訪問Service中的一個方法,那么就可以通過這種方式來實現(xiàn)了。
AIDL是Android的一種接口描述語言; 編譯器可以通過aidl文件生成一段代碼,通過預(yù)先定義的接口達到兩個進程內(nèi)部通信進程的目的. 如果需要在一個Activity中, 訪問另一個Service中的某個對象, 需要先將對象轉(zhuǎn)化成 AIDL可識別的參數(shù)(可能是多個參數(shù)), 然后使用AIDL來傳遞這些參數(shù), 在消息的接收端, 使用這些參數(shù)組裝成自己需要的對象。
AIDL RPC機制是通過接口來實現(xiàn)的,類似Windows中的COM或者Corba,但他是輕量級的,客戶端和被調(diào)用實現(xiàn)之間是通過代理模式實現(xiàn)的,代理類和被代理類實現(xiàn)同一個接口Ibinder接口。
下面是實現(xiàn)Activity訪問Service例子的步驟:
一.創(chuàng)建.aidl文件
AIDL使用簡單的語法來聲明接口,描述其方法以及方法的參數(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)建一個BookInfo.aidl文件,該文件有4個方法:
setName(String name)設(shè)置圖書的書名,setPrice(int price)設(shè)置圖書的價格,setPublish(String pname)設(shè)置圖書的出版社和String display()顯示圖書的信息.
BookInfo.aidl文件
package com.android.aidl; //BookInfo接口 interface BookInfo{ void setName(String name); void setPrice(int price); void ssetPublish(String pname); //顯示圖書的信息 String display(); }
創(chuàng)建好BookInfo.aidl文件,系統(tǒng)會自動在gen目錄下生成Java接口文件BookInfo.java
二.實現(xiàn)AIDL文件生成的JAVA接口
AIDL會生成一個和.aidl文件同名的JAVA接口文件,該接口中有一個靜態(tài)抽象內(nèi)部類Stub,該類中聲明了AIDL文件中定義的所有方法,其中有一個重要的方法是asInterface(),該方法通過代理模式返回JAVA接口的實現(xiàn)我們可以定義一個實現(xiàn)類,BookImpl,該類繼承Stub類,實現(xiàn)我們定義的4個方法
package com.android.aidl; import android.os.RemoteException; public class BookInfoImpl extends BookInfo.Stub { //聲明三個個變量 private int price; private String name,pname; //顯示書名,價格,出版社 public String display() throws RemoteException{ return "書名:"+name+";價格:"+price+";出版社:"+price; } @Override //設(shè)置書名 public void setName(String name) throws RemoteException { // TODO Auto this.name= name; } @Override //設(shè)置價格 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)實現(xiàn)了BookInfo接口,接下來要將該接口暴露給客戶端調(diào)用。一般通過定義一個Service來實現(xiàn),在Service的onBind()方法中返回該接口,當(dāng)我們綁定該接口時調(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)用
定義一個Activity來綁定遠程Service,獲得BookInfo接口,通過RPC機制調(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; // 實例化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開發(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); // 實例化Button btn = (Button) findViewById(R.id.Button1); //為Button添加單擊事件監(jiān)聽器 btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 實例化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
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:text="遠程調(diào)用Service" android:id="@+id/Button1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
在AndroidManifest.xml文件16~20聲明Service
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.aidl" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="RemoteService"> <intent-filter> <action android:name="com.android.aidl.action.MY_REMOTE_SERVICE"/> </intent-filter> </service> </application> </manifest>
效果圖:
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。