Android服務(Service)全解析(四)–AIDL

來源:互聯網
上載者:User

以下為用戶端:

MainActivity如下:

package cn.com.remoteServiceClient;import com.cn.aidl.IRemoteQuery;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;//用戶端步驟://1 自訂ServiceConnection類實現ServiceConnection介面//即RemoteQueryServiceConnection implements ServiceConnection//重寫其方法public void onServiceConnected(ComponentName name, IBinder service)//主要目的就是接受服務端傳過來的Binder對象,即方法的參數IBinder service.//但是因為存在AIDL協議的轉換,所以IBinder service是一個代理對象,我們要強轉,將其轉換為介面類型對象.代碼如下://public void onServiceConnected(ComponentName name, IBinder service) {//remoteQueryBinder=IRemoteQuery.Stub.asInterface(service);//強轉!!//}////2 利用隱式意圖啟用遠程服務////3 利用remoteQueryBinder調用服務裡面的方法////////AIDL的用戶端的總結:// (1) 採用的是隱式意圖去啟用服務service,因為服務和用戶端不在同一個應用!//    彼此看不見,所以是"隱"的,那麼就要採用隱式意圖去啟用,所以在檔案清單裡//    聲明服務元件的時候,還要給其配置意圖過濾器!// (2) 在onServiceConnected()方法裡接收服務端返回來的Binder對象時一定要注意!!!//     這裡和本地服務的情況不一樣!!!因為存在AIDL協議的轉換,所以IBinder service是一個代理對象//     我們要強轉將其轉換為介面類型對象remoteQueryBinder//     即remoteQueryBinder=IRemoteQuery.Stub.asInterface(service);實現轉換// (3) 核心總結://     現在把兩個例子都寫完了,再往回看,那麼可以發現其實本地服務和遠程服務//     都在圍繞一個核心:得到一個Binder對象--->這個Binder對象有一個顯著的//     特點:可以實現與服務的綁定,且可以完成一些業務//     //     在本地服務裡面的實現是:Binder對象的類繼承自Binder且實現了業務的介面//     那麼在接收此Binder對象的時候,當然可以用此介面來接收(父類引用指向子類對象嘛)//     //     在遠程服務裡面實現是:我們要寫一個aidl檔案.//     然後由AIDL自動產生了一個很大的介面,在此介面中最核心是Stub類!它繼承自Binder而且//     實現了我們定義的業務介面!所以返回來的Binder代理對象(注意是代理對象!)//     既有"綁定"到服務的能力,也有完成業務方法的能力//     //     所以在本地和遠程中我們都可以用業務介面來接受返回來的Binder對象或Binder代理對象    public class MainActivity extends Activity {    TextView numberTextView;    TextView resultTextView;    Button button;    RemoteQueryServiceConnection conn=new RemoteQueryServiceConnection();    IRemoteQuery remoteQueryBinder;    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);           numberTextView=(TextView) findViewById(R.id.number);        resultTextView=(TextView) findViewById(R.id.result);        button=(Button) findViewById(R.id.button);        button.setOnClickListener(new ButtonOnClickListener());        Intent service=new Intent();        service.setAction("com.cn.remoteService.RemoteQueryService");        bindService(service, conn, this.BIND_AUTO_CREATE);//綁定服務    }        private class ButtonOnClickListener implements OnClickListener{public void onClick(View v) {String number=numberTextView.getText().toString();String result;try {result = remoteQueryBinder.queryByNum(Integer.valueOf(number));resultTextView.setText(result);} catch (Exception e) {e.printStackTrace();}}       }    //接收綁定的服務和解除服務    private final class RemoteQueryServiceConnection implements ServiceConnection{public void onServiceConnected(ComponentName name, IBinder service) {remoteQueryBinder=IRemoteQuery.Stub.asInterface(service);}public void onServiceDisconnected(ComponentName name) {remoteQueryBinder=null;}       }protected void onDestroy() {unbindService(conn);super.onDestroy();}        }

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"    >   <TextView      android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:text="@string/number"    />    <EditText    android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:id="@+id/number"    />    <Button    android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="@string/button"    android:id="@+id/button"    />    <TextView      android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:id="@+id/result"    /></LinearLayout>

以下為服務端:

RemoteQueryService如下:

package com.cn.remoteService;import com.cn.aidl.IRemoteQuery;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;//服務端步驟://1 產生aidl檔案//建立一個介面,裡面可以有各種方法.//將此介面稍作修改,讓"介面名"和"方法名"都沒有修飾(如public)!!代碼如下://interface IRemoteQuery {//   String queryByNum(int number);//}// 然後找到這個被修改後介面的檔案路徑,按照此路徑在硬碟上將其尾碼改為.aidl//這樣就產生了aidl檔案.在此過程中注意:介面名和aidl檔案名稱必須相同.//2 重新整理工程,系統會自動產生用於用於遠程通訊的IRemoteQuery.java// 分析此IRemoteQuery.java//(1)IRemoteQuery.java內部實際是一個名叫IRemoteQuery的介面//(2)該IRemoteQuery介面內部最重要的是一個Stub類(即IRemoteQuery.Stub),此類繼承自Binder類且實現了IRemoteQuery業務介面// 所以該類的對象具有遠端存取的能力//    //3在用戶端建立一個包,包的名稱與aidl檔案所在的包名一致!然後將服務端的aidl檔案拷貝到此包下,然後重新整理//發現在用戶端的gen下產生了IRemoteQuery.java//    //4 自訂遠程服務類(RemoteQueryService),其繼承自service////5 在RemoteQueryService裡面寫一個內部類RemoteQueryBinder繼承自IRemoteQuery.Stub//即RemoteQueryBinder extends IRemoteQuery.Stub//6 重寫服務的public IBinder onBind(Intent intent)方法,返回一個Binder對象即RemoteQueryBinder類對象給用戶端//////關於AIDL的服務端的總結://(1) 自動產生的Stub是核心重點,從產生的程式碼可以看出:它繼承自Binder而且實現了我們定義的業務介面// 所以它既可以有綁定的能力也有調用業務的能力(這點和剛才寫的調用本地服務的例子有異曲同工之妙)//(2) AIDL的定義和介面很類似,但是"介面名"和"方法名"都沒有修飾!!!!比如public//(3) 在用戶端和服務端都要此包!!因為這相當於一個通訊協定!!!雙方都必須遵守,所以一式兩份!!!public class RemoteQueryService extends Service {@Overridepublic IBinder onBind(Intent intent) {return remoteQueryBinder;}RemoteQueryBinder remoteQueryBinder=new RemoteQueryBinder();private String [] names=new String [] {"小明","小王","小楊","小李"};private final class RemoteQueryBinder extends IRemoteQuery.Stub{@Overridepublic String queryByNum(int number) throws RemoteException {return query(number);}}public String query(int i){if(i>0&&i<5){return names[i-1];}return "查詢錯誤,請再次輸入";}}

以下為AIDL檔案:

IRemoteQuery如下:

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: D:\\workspace\\queryByRemoteService\\src\\com\\cn\\aidl\\IRemoteQuery.aidl */package com.cn.aidl;/** *注意: *此AIDL的定義和介面很類似,但是"介面名"和"方法名"都沒有修飾!!!!比如public */public interface IRemoteQuery extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.cn.aidl.IRemoteQuery{private static final java.lang.String DESCRIPTOR = "com.cn.aidl.IRemoteQuery";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.cn.aidl.IRemoteQuery interface, * generating a proxy if needed. */public static com.cn.aidl.IRemoteQuery asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.cn.aidl.IRemoteQuery))) {return ((com.cn.aidl.IRemoteQuery)iin);}return new com.cn.aidl.IRemoteQuery.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_queryByNum:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();java.lang.String _result = this.queryByNum(_arg0);reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.cn.aidl.IRemoteQuery{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}@Override public java.lang.String queryByNum(int number) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(number);mRemote.transact(Stub.TRANSACTION_queryByNum, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_queryByNum = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public java.lang.String queryByNum(int number) throws android.os.RemoteException;}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.