先前在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裡面
結果畫面如下:
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裡面
結果畫面如下:
沒有留言:
張貼留言