您的位置:首页 > 移动开发 > Android开发

android 跨进程访问service方法(AIDL)

2012-11-10 09:49 393 查看
Acitivity 访问自己进程的service用startService就可以了,访问其中的方法,可以new Service().Method(不推荐)或者通过继承Binder方式来实现。

但是如果要访问系统service (继承binder,ServiceManager.addService)或者 其他 进程(APK)的servcie(四大组件之一,实现onBind)的方法

就要使用bindService +ASDL的方式。如果你只是简单的启动service而

不使用service中的方法,则不需要使用 ASDL。当然你也可以简单通过广播来实现通信。

还有一种比较新鲜的方法“Messenger”!但是Messenger是线程安全的,如果要多线程访问servcie就要使用ASDL 了。

这里只介绍ASDL的方式,另外两种可以参考http://blog.csdn.net/lizhenmingdirk/article/details/7864737





(1)首先定义Service端,比如一个播放音乐的MediaPlaybackService.



定义一个ASDL 文件。注意Open方法得参数,in 的含义,AIDL 和普通的java 接口语法还是有差别的。

如果希望 这个ASDL被编译为Java接口文件。需要在Android.mk文件中替换LOCAL_SRC_FILES如下编译选项。

这样就会在out/target/common/obj/APPS/Music_intermediates/src/src/com/android/music生成 IMediaPlaybackService.java(负责通信,有兴趣可以看一下源码)接口文件 和IMediaPlaybackService.P文件,不需要将该接口文件拷贝到工程目录,就可通过import com.android.music.IMediaPlaybackService;引用它了。





Java代码

LOCAL_SRC_FILES := $(call all-java-files-under, src) \

src/com/android/music/IMediaPlaybackService.aidl







Java代码

package com.android.music;



import android.graphics.Bitmap;



interface IMediaPlaybackService

{

void openFile(String path);

void open(in long [] list, int position);

int getQueuePosition();

boolean isPlaying();

void stop();

void pause();

void play();

void prev();

void next();

long duration();

long position();

long seek(long pos);

String getTrackName();

String getAlbumName();

long getAlbumId();

String getArtistName();

long getArtistId();

void enqueue(in long [] list, int action);

long [] getQueue();

void moveQueueItem(int from, int to);

void setQueuePosition(int index);

String getPath();

long getAudioId();

void setShuffleMode(int shufflemode);

int getShuffleMode();

int removeTracks(int first, int last);

int removeTrack(long id);

void setRepeatMode(int repeatmode);

int getRepeatMode();

int getMediaMountedCount();

int getAudioSessionId();

void playAll(in long[] list, int position, boolean force);

}



(2)编写音乐servcie代码,注意是继承了IMediaPlaybackService.Stub:

Java代码

public class MediaPlaybackService extends Service {



private IBinder binder = new MyBinder(this);

@Override

public IBinder onBind(Intent intent) {

return binder;

}

public String play(){

//......

}

public class MyBinder extends IMediaPlaybackService.Stub{



WeakReference<MediaPlaybackService> mService;



MyBinder(MediaPlaybackService service) {

mService = new WeakReference<MediaPlaybackService>(service);

}



@Override

public String play() {

return mService.play();

}

@Override

protected boolean onTransact(int code, Parcel data, Parcel reply,

int flags) throws RemoteException {

return super.onTransact(code, data, reply, flags);

}

}

}





修改Music Manifest.xml文件



Java代码

<service android:name="com.android.music.MediaPlaybackService"

android:exported="true" >

<intent-filter>

<action android:name="com.android.music.IMediaPlaybackService" />

</intent-filter>

</service>



至此 ,服务器端工作完毕。











客户端调用流程:

将Music的IMediaPlaybackService.asdl文件拷贝到 客户端工程,注意需要在客户端工程中建立和服务端相同的包结构。

这和webservice很像。 同样修改Android.mk文件使其生成IMediaPlaybackService.java文件。(其实完全可以copy服务器端的)

myService = IMediaPlaybackService.Stub.asInterface(service);






Java代码

import com.android.music.IMediaPlaybackService;

Java代码

public class HelloActivity extends Activity {



@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);



View view = getLayoutInflater().inflate(R.layout.hello_activity, null);

setContentView(view);

//注意:这个bindService不能在onclick方法中调用。service中进行耗时操作也要起线程。

boolean issuccess = bindService(new Intent("com.android.music.IMediaPlaybackService"),

serviceConnection, Context.BIND_AUTO_CREATE);

Button btn = (Button)this.findViewById(R.id.text);

btn.setOnClickListener(new View.OnClickListener(){



@Override

public void onClick(View v) {



try {

myService.pause();

} catch (RemoteException e) {



e.printStackTrace();

}

}



});

}

IMediaPlaybackService myService = null;



ServiceConnection serviceConnection = new ServiceConnection()

{



@Override

public void onServiceConnected(ComponentName name, IBinder service) {



myService = IMediaPlaybackService.Stub.asInterface(service);

//myService = (IMediaPlaybackService)service;//Wrong !!!跨进程不可行

}

@Override

public void onServiceDisconnected(ComponentName name) {

serviceConnection = null;

}

};



}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: