android 遠程服務傳遞自訂資料類型

來源:互聯網
上載者:User

標籤:

在Android系統中,進程間傳遞的資料包括Java語言支援的基礎資料型別 (Elementary Data Type)和使用者自訂的資料類型,為了使資料能夠穿越進程邊界,所有資料都必須是“可打包”。對於Java語言的基礎資料型別 (Elementary Data Type),打包過程是自動完成的。但對於自訂的資料類型,使用者需要實現Parcelable介面,使自訂的資料類型能夠轉換為系統級原語儲存在Parcel對象中,穿越進程邊界後可再轉換為初始格式。

AIDL支援的資料類型如下表:

類型 說明 需要引入
基礎資料型別 (Elementary Data Type) boolean、byte、short、int、
long、char、float、double
String java.lang.String
CharSequence java.lang.CharSequence
List 其中元素都必須是AIDL支援的資料類型
Map 其中ket和value都必須是AIDL支援的資料類型
其他AIDL介面 任何其他使用AIDL語言產生的介面類型
Parcelable對象 實現Parcelable介面的對象


下面以ParcelMathServiceDemo樣本為參考,說明如何在遠程服務中使用自訂類型。這個樣本是RemoteMathServiceDemo樣本的延續,查看我的RemoteMathServiceDemo樣本文章 ,也定義了MathService服務,同樣可以為遠程調用者提供加法服務,而且同樣也是沒有啟動介面。

不同之處在於MathService服務涉及到了自訂資料類型,在接受到輸入參數後,將不再只向調用者返回long類型的資料,而是返回一個包含“加、減、乘、除”全部運算結果的對象。這個對象是一個自訂的類,為了能夠使其他AIDL檔案可以使用這個自訂的類,需要使用AIDL語言聲明這個類。

首先建立AllResult.aidl檔案

然後在AllResult.aidl檔案中聲明AllResult類,AllResult.aidl檔案中的代碼如下:

// AllResult.aidlpackage com.example.remotemathservicedemo;//在這裡聲明任何非預設類型parcelable AllResult;

(這個簡陋的aidl檔案可不會自動產生對應的java介面檔案哦)

然後在IMathService.aidl中為全運算增加新函數,傳回型別就是在AllResult.aidl中定義的AllResult,代碼如下:

// IMathService.aidlpackage com.example.remotemathservicedemo;// Declare any non-default types here with import statementsinterface IMathService {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */     long Add(long a,long b);     AllResult ComputeAll(long a,long b);}

然後Build->Make Project 重建介面檔案,使增加的新函數生效。這時候在新產生的IMathService.java中會提示錯誤,因為其中需要關於AllResult的資訊都找不到。

接下來手動構造AllResult類,可以放在和自動產生的IMathService.java同目錄下。下面先把AllResult.java的完整代碼貼出來:

package com.example.remotemathservicedemo;import android.os.Parcel;import android.os.Parcelable;/** * Created by yinghao on 2016/5/7. */public class AllResult implements Parcelable {    public long addResult;    public long subResult;    public long mulResult;    public double divResult;    public AllResult(long addResult, long subResult, long mulResult, double divResult) {        this.addResult = addResult;        this.subResult = subResult;        this.mulResult = mulResult;        this.divResult = divResult;    }    //從Parcel對象得到資料,拆包函數    public AllResult(Parcel parcel) {        addResult = parcel.readLong();        subResult = parcel.readLong();        mulResult = parcel.readLong();        divResult = parcel.readDouble();    }    @Override    public int describeContents() {        return 0;    }    //顧名思義 wiiteToParcel  打包函數    //將AllResult類內部的資料按照特定順序寫入Parcel對象    //寫入順序必須與建構函式讀取順序一致    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeLong(addResult);        dest.writeLong(subResult);        dest.writeLong(mulResult);        dest.writeDouble(divResult);    }    //實現靜態公用欄位Creator,用來使用Parcel物件建構AllResult對象    public static final Parcelable.Creator<AllResult> CREATOR = new Creator<AllResult>() {        @Override        public AllResult createFromParcel(Parcel parcel) {            return new AllResult(parcel);        }        @Override        public AllResult[] newArray(int size) {            return new AllResult[size];        }    };}

AllResult繼承於Parcelable,其中的資料就是全運算的運算結果。
AllResult類除了基本的建構函式以外,還需要以Parcel對象為輸入的建構函式,並且要重載打包函數writeToParcel()。 把這個類寫完後,你就會發現IMathService.java中的錯誤提示消失了。

到這裡,關於自訂資料類型的工作就完成了,然後在MathService.java檔案中,增加用來進行全運算的ComputAll()函數,並將運算結果儲存在AllResult對象中。MathService.java中的完整代碼如下:

package com.example.remotemathservicedemo;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.support.annotation.Nullable;import android.widget.Toast;/** * Created by yinghao on 2016/5/7. */public class MathService extends Service {    /*           1. 建立 IMathService.Stub的執行個體mBinder並實現AIDL檔案定義的遠程服務介面           2. 在onBind()方法中將mBinder返回給遠程調用者     */    private final IMathService.Stub mBinder = new IMathService.Stub(){        @Override        public long Add(long a, long b) throws RemoteException {            return a + b;        }        @Override        public AllResult ComputeAll(long a, long b) throws RemoteException {            long addResult = a + b;            long subResult = a - b;            long mulResult = a * b;            double divResult = a / b;            AllResult allResult = new AllResult(addResult, subResult, mulResult, divResult);            return allResult;        }    };    @Nullable    @Override    public IBinder onBind(Intent intent) {        Toast.makeText(MathService.this, "遠程綁定:MathService", Toast.LENGTH_SHORT).show();        return mBinder;    }    //Return true if you would like to have the service‘s onRebind method later called when new clients bind to it.    @Override    public boolean onUnbind(Intent intent) {        Toast.makeText(MathService.this, "取消遠程綁定", Toast.LENGTH_SHORT).show();        return false;    }}

到這裡,服務端的工作就全部完成了,當然如果你沒看過我的上篇關於遠程服務傳遞基礎資料型別 (Elementary Data Type)的話,那還缺少一步,註冊Service。

然後就是調用者如何去綁定和調用服務,首先需要將服務端的Module中的兩個aidl檔案以及對應的java介面檔案和自己構造的AllResult.java類全部拷貝到調用端Module中。(關於原因可在上篇文章中查看)

然後將原來的“加法運算”功能改為“全運算”功能,關於remoteMathCallerDemo中MainActivity.java中的完整代碼如下:

package com.example.remotemathcallerdemo;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.TextView;import com.example.remotemathservicedemo.AllResult;import com.example.remotemathservicedemo.IMathService;public class MainActivity extends AppCompatActivity {    private TextView textView;    private Button bind;    private Button unbind;    private Button add;    private boolean isBound = false;    private IMathService mathService;    private ServiceConnection mConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mathService = IMathService.Stub.asInterface(service);        }        @Override        public void onServiceDisconnected(ComponentName name) {            mathService = null;        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView = (TextView) findViewById(R.id.textView);        bind = (Button) findViewById(R.id.bind);        unbind = (Button) findViewById(R.id.unbind);        add = (Button) findViewById(R.id.add);        bind.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (!isBound) {                    final Intent serviceIntent = new Intent();                    serviceIntent.setAction("com.example.remote.MathService");                    bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);                    isBound = true;                }            }        });        unbind.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (isBound) {                    unbindService(mConnection);                    isBound = false;                    mathService = null;                }            }        });        add.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (mathService == null) {                    textView.setText("未綁定遠程服務");                    return;                }                long a = Math.round(Math.random() * 100);                long b = Math.round(Math.random() * 100);                AllResult result = null;                try {                    result = mathService.ComputeAll(a, b);                } catch (RemoteException e) {                    e.printStackTrace();                }                String msg = "";                if (result != null) {                    msg += String.valueOf(a) + "+" + String.valueOf(b) + "=" +                            String.valueOf(result.addResult) + "\n";                    msg += String.valueOf(a) + "-" + String.valueOf(b) + "=" +                            String.valueOf(result.subResult) + "\n";                    msg += String.valueOf(a) + "*" + String.valueOf(b) + "=" +                            String.valueOf(result.mulResult) + "\n";                    msg += String.valueOf(a) + "/" + String.valueOf(b) + "=" +                            String.valueOf(result.divResult) + "\n";                }                textView.setText(msg);            }        });    }}

運行效果如下:

對於遠程服務的一些基礎知識總結以及遠程服務傳遞基礎資料型別 (Elementary Data Type)的Demo在Android Service 遠程服務(點擊查看),歡迎大家指出差錯或交流。

android 遠程服務傳遞自訂資料類型

聯繫我們

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