2011年12月26日 星期一

Android - Pass Data (4) - Activity 和 Service 之間用AIDL工具

先前在Activity和Service之間是傳遞簡單的資料,如果今天要傳遞的是物件(不是IBinder)的話,正統的做法可麻煩了。參考官網:http://developer.android.com/guide/developing/tools/aidl.html
AIDL工具則是為了簡化程式碼撰寫而提供的工具,它放在android-sdk-linux_86/platforms/android-8/tools/aidl

aidl的方式要傳遞物件的步驟如下:
(1)撰寫xxxxx.aidl : 這個aidl是一個interface介面,裡面有一個callback function,用來回傳欲傳遞的物件,本範例為:ICallback.aidl

(2) 欲傳遞的物件implements Parcelable : 詳細作法參考前文Pass Data(2),本範例為:Data.java

(3) 利用aidl 工具產生相關java檔: 先把項目(2)的類別名稱,寫在/android-sdk-linux_86/platforms/android-8/framework.aidl 裡面(依你的android版本而定)。否則到時候aidl工具會找不到要import的class而出現couldn't find import for class的錯誤。之後如果是command的方式,就下aidl -I/path/project/src -p/path/framework.aidl xxxxxx.aidl,-I 後面加的是xxx.aidl所在的src路徑, -p是framework.aidl的完整路徑,然後就會在xxxxxx.aidl的目錄下產生xxxxxx.java。如果是使用eclipse的話, 只要先設好framework.aidl,則在Project -> Clean後,會在gen目錄底下產生xxxxxx.java檔。

(4)其餘作法參考前文Pass Data(2)

下面為測試程式碼:

ICallback.aidl:
package com.test.testaidl;
import com.test.testaidl.Data;

interface ICallback { 
    //這個getData()就是一種callback function,在未來會被實作要丟回什麼物件
    Data getData();
}

Data.java:
public class Data implements Parcelable {
    private String mTempString;

    //以下是因為implements Parcelable情況下,一定要有的function   
    public Data(Parcel in) {
        readFromParcel(in);
    }
   
    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        //先把資料寫進去dest這個Parcel裡面
        dest.writeString(mTempString);
    }

    private void readFromParcel(Parcel in) {
        //要用的時候,就按當初寫入的順序讀出in這個Parcel裡面的資料
        mTempString = in.readString();
    }

    public static final Parcelable.Creator<Data> CREATOR = new Parcelable.Creator<Data>() {
        public Data createFromParcel(Parcel in) {
            return new Data(in);
        }
        public Data[] newArray(int size) {
            return new Data[size];
        }
    };
   
    //以下是通常在沒有implements Parcelable情況下,自己寫的function
    public Data() {
    }

    public void setTempString(String TempString) {
        mTempString = TempString;
    }

    public String getTempString() {
        return mTempString;
    }

}

BackgroundService.java:
public class BackgroundService extends Service {
    public String mTempString = "This is BackgroundService";

    public myBinderClass mBinder = new myBinderClass();
    @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }
   
    public class myBinderClass extends ICallback.Stub{
        //在這裡進行Activity和Service之間的通訊
        //直接對Object物件的傳遞就是寫在這裡
        public Data getData() throws RemoteException {
            Data data = new Data();
            data.setTempString("This is setted by BackgroundService.");
            return data;       
        }
    }
}

Main.java:
public class Main extends Activity {
    private ServiceConnection serviceCon;
    private ICallback myCallback;
    private Data myDataObject;
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
              
        serviceCon = new ServiceConnection() {       
            public void onServiceConnected(ComponentName name, IBinder service) {
                //取得名為Data的物件Object
                myCallback = ICallback.Stub.asInterface(service);               
                try {
                    myDataObject = myCallback.getData();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }       
               
                Toast.makeText(Main.this, myDataObject.getTempString(), Toast.LENGTH_LONG).show();
            }       
            public void onServiceDisconnected(ComponentName name) {
               
            }
        };
        bindService(new Intent("com.test.action.myservice"), serviceCon, this.BIND_AUTO_CREATE);      
    }
}

請注意,在BackgroundService.java中的extends ICallback.Stub和Main.java和的ICallback.Stub.asInterface(service);程式碼到底寫在那裡,其實就是在aidl產生的ICallback.java裡面

結果畫面如下:

沒有留言:

張貼留言