1、定义aidl接口。
为服务定义aidl接口,所有拥有服务的客户端都可使用该接口中的函数。
package com.service;
interface IMusicPlayerService {
boolean start();
void stop();
}
该接口elipse会自动生成IMusicPlayerService.java文件。该文件不需要修改。
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: /home/zhangfang/workspace_eclipse/RemoteService/src/com/service/IMusicPlayerService.aidl
*/
package com.service;
public interface IMusicPlayerService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.service.IMusicPlayerService
{
private static final java.lang.String DESCRIPTOR = "com.service.IMusicPlayerService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.service.IMusicPlayerService interface,
* generating a proxy if needed.
*/
public static com.service.IMusicPlayerService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.service.IMusicPlayerService))) {
return ((com.service.IMusicPlayerService)iin);
}
return new com.service.IMusicPlayerService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_start:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.start();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_stop:
{
data.enforceInterface(DESCRIPTOR);
this.stop();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.service.IMusicPlayerService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public boolean start() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_start, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public void stop() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_start = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public boolean start() throws android.os.RemoteException;
public void stop() throws android.os.RemoteException;
}
注意该生成的接口文件:
IMusicPlayerService继承了android.os.IInterface,并实现了抽象的Stub类,该Stub继承android.os.Binder。该Stub是一个庄,它继承Binder,那么它的对象就可以被远程的进程使用了。本例中,在MusicPlayerServer中的类MyMusicPlayer继承了IMusicPlayerService.Stub,则该Stub中的函数可以在其他进程中使用。本例在另外Activity中调用。
public class MyMusicPlayer extends IMusicPlayerService.Stub
2、定义一个服务,实现IMusicPlayerService中定义的函数。该MusicPlayerServer相当与服务端,可以和client在同一个进程中,也可在不同进程中。
package com.service;
import com.remoteservice.R;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MusicPlayerServer extends Service {
private static final String Tag = "com.remote.service.MusicPlayerServer";
MediaPlayer player=null;
public class MyMusicPlayer extends IMusicPlayerService.Stub
{
public void stop() throws RemoteException {
// TODO Auto-generated method stub
Log.v(Tag,"stop is called.");
player.stop();
}
public boolean start() throws RemoteException {
// TODO Auto-generated method stub
Log.v(Tag,"start is called.");
player=MediaPlayer.create(MusicPlayerServer.this,R.raw.dream);
player.setLooping(true);
player.start();
return true;
}
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.v(Tag,"in oncreate");
super.onCreate();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.v(Tag,"in onDestroy");
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
Log.v(Tag,"in onBind");
return new MyMusicPlayer();
}
}
该MusicPlayerServer相当与服务端,可以和client在同一个进程中,也可在不同进程中。如果希望客户端和服务端在不同进程中,则在AndroidManifest.xml中指定服务在不同的进程。
<service android:name="com.service.MusicPlayerServer"
android:process=":zhang"></service>
3、Client端代码
package com.remoteservice;
import com.service.IMusicPlayerService;
import com.service.MusicPlayerServer;
import android.app.Activity;
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.util.Log;
import android.view.Menu;
import android.view.MenuItem;
public class RemoteServiceActivity extends Activity {
/** Called when the activity is first created. */
private static final String Tag="com.android.remote.service.RemoteServiceActivity";
IMusicPlayerService iPlayer=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initService();
}
/**
* 开启服务
* 绑定服务
*/
private void initService()
{
Intent intent=new Intent();
intent.setClass(RemoteServiceActivity.this, MusicPlayerServer.class);
bindService(intent,conn,Context.BIND_AUTO_CREATE);
}
private ServiceConnection conn=new ServiceConnection(){
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
iPlayer=IMusicPlayerService.Stub.asInterface(service);
Log.v(Tag,"in onServiceConnected");
}
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
Log.v(Tag,"in onServiceDisConnected");
}
};
/**
* 设置菜单按钮
*/
public boolean onCreateOptionsMenu(Menu menu)
{
menu.add(0, 0, 0, "start");
menu.add(0, 1, 1, "stop");
return true;
}
public boolean onOptionsItemSelected(MenuItem item)
{
int item_id=item.getItemId();
switch(item_id){
case 0:{
try {
iPlayer.start();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
case 1:{
try {
iPlayer.stop();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
return true;
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
RemoteServiceActivity.this.unbindService(conn);
}
}
使用bindservice函数。onServiceConnected函数第二个参数是MusicPlayerServer服务中onBinder返回的值。
该Activity用下面函数获得service中的Stub对象,这样就可以在activity中使用Stub对象中定义的方法了,即使该Stub对象在另一个进程中。底层的进程间通信android已经帮我们做好了。
iPlayer=IMusicPlayerService.Stub.asInterface(service);
4、AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.remoteservice"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".RemoteServiceActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.service.MusicPlayerServer"
android:process=":zhang"></service>
</application>
</manifest>
5、下载运行,可以看到Client和Server在不同的进程中。
3170 10037 0:00 {m.remoteservice} com.remoteservice
3178 10037 0:00 {teservice:zhang} com.remoteservice:zhang