在过去的技术中,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源代码的一个简单例子:
package com.lovo.service; interface IMessage{ int getFlag(); String getMessage(String msg); }
自动生成的AIDL实现,在此不给出。
远程的Service:
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的实现类):
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:
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):
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传递复杂数据。