關於Android中的四大組件(AIDL Service的使用)

來源:互聯網
上載者:User

標籤:parcelable   aidl service   service   android   四大組件   

跨進程調用Service(AIDL Service)


Android系統中的進程之間不能共用記憶體,因此,需要提供一些機制在不同進程之間進行資料通訊。


在前一篇文章(關於Android中的四大組件(Service的開啟與關閉))中介紹了開發人員如何定製自己的服務,但這些


服務並不能被其它的應用程式訪問,為了使其它的應用程式也可以訪問本應用程式提供的服務,Android系統採用了


遠端程序呼叫(Remote Procedure Call,RPC)方式來實現。與很多其它的基於RPC的解決方案一樣,Android使用一種


介面定義語言(Interface Definition Language,IDL)來公開服務的介面,因此,可以將這種跨進程訪問的服務稱為


(Android Interface Definition Language)AIDL服務。



AIDL服務的建立步驟


建立AIDL服務比普通的服務要複雜一些,具體步驟如下。


(1)在Eclipse Android工程的Java源檔案目錄中建立一個副檔名為aidl的檔案,該檔案的文法類似於Java代


碼,但會稍不同。


(2)如果aidl檔案的內容是正確的,ADT會自動產生一個Java介面檔案(*.java)。


(3)建立一個服務類(Service的子類)。


(4)實現由aidl檔案產生的Java介面。


(5)在AndroidManifest.xml檔案中配置AIDL服務,注意的是<action>標籤中android:name的屬性值就是用戶端


要引用該服務的ID,也就是Intent類構造方法的參數值。


建立AIDL服務


以下程式是服務端建立了一個簡單的AIDL服務,這個服務有兩個get方法,分別擷取姓名和年齡,建立此AIDL服務的步驟


如下。


(1)建立一個aidl檔案,如中的IPerson.aidl檔案。



IPerson.aidl檔案的內容如下:

<pre name="code" class="html">package com.aidl;interface IPerson{String getName();int getAge();}



IPerson.aidl檔案的內容與Java代碼非常相似,但要注意,不能加修飾符,比如:public、private,同時AIDL服


務不支援的資料類型例如:InputStream、OutputStream等內容。


(2)如果IPerson.adil檔案中內容正確,ADT會自動產生一個IPerson.java檔案。


(3)編寫一個MyService類,該類繼承自Service,在MyService類中定義了一個內聯類PersonImpl,該類繼承自


IPerson.Stub,MyService類的代碼如下:


public class MyService extends Service{public class PersonImpl extends IPerson.Stub{@Overridepublic String getName() throws RemoteException {return "bill";}@Overridepublic int getAge() throws RemoteException {return 25;}}@Overridepublic IBinder onBind(Intent intent) {return new PersonImpl();}}

注意:以上的onBind()方法必須返回PersonImpl對象,否則用戶端無法獲得服務物件。


(4)在AndroidManifest.xml檔案中配置MyService類,代碼如下:


<service android:name="com.example.aidlserviceproject.service.MyService">            <intent-filter >                <action android:name="com.aidl.IPerson"/>            </intent-filter></service>

注意:其中的“com.aidl.IPerson”是用戶端用於訪問AIDL服務的ID。


至此服務端的AIDL服務編寫完成,接下來進行用戶端代碼的編寫,建立工程,將服務端的自動產生的


IPerson.java檔案連同包目錄一起複製到用戶端工程中,如:






以下程式實現了綁定AIDL服務,以及擷取服務端資料:


public class MainActivity extends Activity implements OnClickListener{private Button btn_aidl;private Button btn_get;private TextView tv_show;private Intent mIpItent;private IPerson mIpIPerson=null;private ServiceConnection conn=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mIpIPerson=IPerson.Stub.asInterface(service);btn_get.setEnabled(true);}};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();        initView();        initEvent();    }        private void initData(){    mIpItent=new Intent("com.aidl.IPerson");    }    private void initView(){    btn_aidl=(Button) this.findViewById(R.id.btn_aidl);    btn_get=(Button) this.findViewById(R.id.btn_get);    tv_show=(TextView) this.findViewById(R.id.tv_show);    btn_get.setEnabled(false);    }           private void initEvent(){    btn_aidl.setOnClickListener(this);    btn_get.setOnClickListener(this);    }    @Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_aidl://綁定AIDL服務bindService(mIpItent, conn, Context.BIND_AUTO_CREATE);break;case R.id.btn_get://擷取服務端資料try {tv_show.setText("姓名:"+mIpIPerson.getName()+"\n年齡:"+mIpIPerson.getAge());} catch (RemoteException e) {e.printStackTrace();}default:break;}}}



以上代碼使用bindService方法來綁定AIDL服務,其中需要指定AIDL服務的ID,也就是<action>標籤中的


android:name屬性值。在綁定時需要一個ServiceConnection對象,當綁定成功,系統調用


ServiceConnection.onServiceConnected方法,通過此方法的service參數擷取AIDL服務物件。最後先運行服務端程


序,再運行用戶端程式。


效果如下:




傳遞複雜資料的AIDL服務

AIDL服務只支援有限的資料類型,因此,如果用AIDL服務傳遞一些複雜的資料需要做更一步處理,AIDL服務支


持的資料類型如下。


(1)java的簡單類型(int、char、boolean等),不需要匯入。


(2)String和CharSequence,不需要匯入。


(3)List和Map,List和Map對象的元素類型必須是AIDL服務支援的資料類型,不需要匯入。


(4)AIDL自動產生的介面,需要匯入。


(5)實現android.os.Parcelable介面的類,需要匯入。


以下程式傳遞的資料類型是Person類,服務端代碼如下:


(1)建立Person實現Parcelable介面


public class Person implements Parcelable{private String name;private int age;public static final Parcelable.Creator<Person> CREATOR=new Creator<Person>() {@Overridepublic Person[] newArray(int size) {return new Person[size];}@Overridepublic Person createFromParcel(Parcel source) {return new  Person(source.readInt(),source.readString());}};public Person(){}public Person(int age,String name){this.name=name;this.age=age;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(age);dest.writeString(name);}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}


Person實現android.os.Parcelable這個介面,該介面用於序列化對象,在Person類中必須有一個靜態常量,常量


名必須是CREATOR,而且CREATOR常量的資料類型必須是Parcelable.Creator。在writeToParcel方法中需要將序列


化的值寫入Parcel對象,注意,讀取的順序必須和寫入的順序保持一致。


(2)接著建立一個IPerson.aidl檔案,代碼如下:


package com.aidl;import com.aidl.Person;interface IPerson{Person getPerson();}


(3)建立一個Person.aidl檔案,代碼如下:

package com.aidl; parcelable Person;


(4)建立一個MyService類,代碼如下:


public class MyService extends Service {public class PersonImpl extends IPerson.Stub {@Overridepublic Person getPerson() throws RemoteException {Person person = new Person();person.setName("bill");person.setAge(25);return person;}}@Overridepublic IBinder onBind(Intent intent) {return new PersonImpl();}}


最後服務端的工程目錄結構如:





OK,服務端的AIDL服務編寫完畢,接著編寫用戶端程式,將服務端的Person.java與IPerson.aidl連同包一起複


制到用戶端工程中,如:





以下代碼實現了擷取服務端的Person對象中的資料:


public class MainActivity extends Activity implements OnClickListener{private Button btn_aidl;private Button btn_get;private TextView tv_show;private Intent mIpItent;private IPerson mIpIPerson=null;private ServiceConnection conn=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mIpIPerson=IPerson.Stub.asInterface(service);btn_get.setEnabled(true);}};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();        initView();        initEvent();    }        private void initData(){    mIpItent=new Intent("com.bill.aidl.IPerson");    }    private void initView(){    btn_aidl=(Button) this.findViewById(R.id.btn_aidl);    btn_get=(Button) this.findViewById(R.id.btn_get);    tv_show=(TextView) this.findViewById(R.id.tv_show);    btn_get.setEnabled(false);    }           private void initEvent(){    btn_aidl.setOnClickListener(this);    btn_get.setOnClickListener(this);    }    @Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_aidl://綁定AIDL服務bindService(mIpItent, conn, Context.BIND_AUTO_CREATE);break;case R.id.btn_get://擷取服務端資料try {Person person=mIpIPerson.getPerson();tv_show.setText("姓名:"+person.getName()+"\n年齡:"+person.getAge());} catch (RemoteException e) {e.printStackTrace();}default:break;}}}


先運行服務端程式,在運行用戶端程式,運行效果如下:









-------------------------------------------------------------------------------------------------------------------------------------------------------

轉載請註明出處:http://blog.csdn.net/hai_qing_xu_kong/article/details/47748779情緒控




著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

關於Android中的四大組件(AIDL Service的使用)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.