在過去的技術中,Corba可以實現跨進程的調用;在Java技術中,RMI也可以實現跨進程的調用;在Android中類似可以使用AIDL服務跨進程調用Service。
Android的遠程Service調用與Java的RMI基本相似,一樣都是先定義一個遠程調用介面,然後為該介面提供一個實作類別即可。與RMI不同的是,用戶端訪問Service時,Android並不是直接返回Service對象給用戶端。
在Android中綁定本地Service時,返回的是一個IBinder對象;而訪問遠程Service時,是將IBinder的代理返回給用戶端,當用戶端獲得IBinder對象的代理後,就可以通過IBinder對象去回調遠程Service的屬性和方法了。
樣本如下:
建立AIDL檔案:
AIDL:指Android Interface Definition Language
注意:AIDL定義介面的原始碼必須以.aidl結尾;
AIDL介面中用到的資料類型,除了基本類型、String、List 、Map、CharSequence之外,其他類型都需要導包,即使在同一包中也需導包。
在Service端和用戶端都需要為該介面提供實現。使用ADT工具進行開發,會自動為AIDL介面產生實現。
這是AIDL原始碼的一個簡單例子:
[java]
package com.lovo.service;
interface IMessage{
int getFlag();
String getMessage(String msg);
}
package com.lovo.service;
interface IMessage{
int getFlag();
String getMessage(String msg);
}自動產生的AIDL實現,在此不給出。
遠端Service:
[java]
package com.lovo.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class RemoteService extends Service {
@Override
public IBinder onBind(Intent intent) {
MyMessage message = new MyMessage();
return message;
}
}
package com.lovo.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class RemoteService extends Service {
@Override
public IBinder onBind(Intent intent) {
MyMessage message = new MyMessage();
return message;
}
}
MyMessage類(IMessage的實作類別):
[java]
package com.lovo.service;
public class MyMessage extends IMessage.Stub {
@Override
public int getFlag() {
return 100;
}
@Override
public String getMessage(String msg) {
return msg + "Android!";
}
}
package com.lovo.service;
public class MyMessage extends IMessage.Stub {
@Override
public int getFlag() {
return 100;
}
@Override
public String getMessage(String msg) {
return msg + "Android!";
}
}
用戶端的Activity:
[java]
package com.lovo.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.lovo.conn.RemoteServiceConnection;
import com.lovo.lesson10.R;
public class StartRemoteActivity extends Activity {
private Button startServiceBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.remote_main);
startServiceBtn = (Button) findViewById(R.id.remote_main_btn_startserver);
startServiceBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.lovo.service.REMOTE_SERVICE");
bindService(intent, new RemoteServiceConnection(),
BIND_AUTO_CREATE);
}
});
}
}
package com.lovo.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.lovo.conn.RemoteServiceConnection;
import com.lovo.lesson10.R;
public class StartRemoteActivity extends Activity {
private Button startServiceBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.remote_main);
startServiceBtn = (Button) findViewById(R.id.remote_main_btn_startserver);
startServiceBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.lovo.service.REMOTE_SERVICE");
bindService(intent, new RemoteServiceConnection(),
BIND_AUTO_CREATE);
}
});
}
}
用戶端的ServiceConnection的實作類別(RemoteServiceConnection):
[java]
package com.lovo.conn;
import com.lovo.service.IMessage;
import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class RemoteServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 將遠端代理對象轉換成真實對象
IMessage message = IMessage.Stub.asInterface(service);
try {
Log.i("訪問遠程方法:",
message.getFlag() + " " + message.getMessage("I like "));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
package com.lovo.conn;
import com.lovo.service.IMessage;
import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class RemoteServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 將遠端代理對象轉換成真實對象
IMessage message = IMessage.Stub.asInterface(service);
try {
Log.i("訪問遠程方法:",
message.getFlag() + " " + message.getMessage("I like "));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
布局檔案只有一個按鈕在此省略不寫。本文只是簡單地調用了遠端方法,在實際中可以使用AIDL傳遞複雜資料。