Aidl实现对象传递
2014-04-21 21:38
274 查看
一 场景需求
这里假设我要写一个音乐服务,如果我仅仅提供简单的播放和停止功能,不是用java对象的话是没有问题的,我们很容易就将一个接口转化为aidl文件了。但是如果方法的参数或返回值包含自定义对象的话在你将一个接口类改为aidl文件时就会报错。就像在我写的demo中,我的系统服务提供了获得播放列表的功能,由于每首歌会有许多信息,因此我把它包装成了对象,这时该怎么处理呢。
注:我定义aidl的方法都是先写一个java接口类,然后将.java的后缀该为.aidl,让后再将.aidl文件中的public修饰符去掉。
二 服务端编写
编写服务端暴漏的方法的接口类
这时打开gen目录,就会看到自动生成的MusicServiceAidl 类了,这个类中有个内部类stub,他继承了Binder对象,实现了你上面定于的接口
在服务端的service对象中我们会复写onBind方法,在这个方法中要返回一个IBinder对象,这个IBinder对象不再是继承Binder类了,而是实现上面生成的MusicServiceAidl的内部类Stub。
在上面的接口中,getMusicList()返回的是一个Song对象的集合,但是,我们虽然定义了Song对象,上面生成的接口类仍然报错,这个就是aidl传输对象需要解决的问题。
我们让我们写的Song对象实现Percelable接口
实现未实现的方法
在文件中只写一句代码
但是在gen目录下生成的MusicServiceAidl.java却还是报错,仔细查看发现是缺少CREATOR对象,这时就在Song对象中添加CREATOR对象
至此服务端的代码就写完了。
三客户端代码
将服务端编写的aidl和要传递的对象带着包名一起复制到客户端的代码中。报名一定不要改。
注意:客户端是通过服务端的service的action绑定的。
在绑定服务时,要传递一个ServiceConnection对象,对象定于如下。
得到了接口对象了,就可以调用接口里的方法了。
这里假设我要写一个音乐服务,如果我仅仅提供简单的播放和停止功能,不是用java对象的话是没有问题的,我们很容易就将一个接口转化为aidl文件了。但是如果方法的参数或返回值包含自定义对象的话在你将一个接口类改为aidl文件时就会报错。就像在我写的demo中,我的系统服务提供了获得播放列表的功能,由于每首歌会有许多信息,因此我把它包装成了对象,这时该怎么处理呢。
注:我定义aidl的方法都是先写一个java接口类,然后将.java的后缀该为.aidl,让后再将.aidl文件中的public修饰符去掉。
二 服务端编写
编写服务端暴漏的方法的接口类
public interface MusicServiceAidl{ public List<Song> getMusicList(); publicvoid playSong(int index); public void changeSong(int flag); public void pauseSong(); }改写为.aidl文件
interface MusicServiceAidl{ List<Song> getMusicList(); void playSong(int index); /** * 传入一个整型的参数,为0则切换为当前的歌曲,小于0则切换到上一首,大于0则切换到下一首 * @param flag */ void changeSong(int flag); void pauseSong(); }
这时打开gen目录,就会看到自动生成的MusicServiceAidl 类了,这个类中有个内部类stub,他继承了Binder对象,实现了你上面定于的接口
public static abstract class Stub extends android.os.Binder implements com.MusicPlayer.aidl.MusicServiceAidl
在服务端的service对象中我们会复写onBind方法,在这个方法中要返回一个IBinder对象,这个IBinder对象不再是继承Binder类了,而是实现上面生成的MusicServiceAidl的内部类Stub。
@Override public IBinder onBind(Intent intent) { binder = new MusicIBinder(this); return binder; }
在上面的接口中,getMusicList()返回的是一个Song对象的集合,但是,我们虽然定义了Song对象,上面生成的接口类仍然报错,这个就是aidl传输对象需要解决的问题。
我们让我们写的Song对象实现Percelable接口
实现未实现的方法
@Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(_id); dest.writeString(title); dest.writeString(artist); dest.writeString(path); dest.writeLong(duration); dest.writeLong(size); }编写与Song同名的aidl文件(一定要与传递的对象同名)
在文件中只写一句代码
parcelable Song;这时MusicServiceAidl.aidl文件就不再报错了,
但是在gen目录下生成的MusicServiceAidl.java却还是报错,仔细查看发现是缺少CREATOR对象,这时就在Song对象中添加CREATOR对象
public static Creator<Song> CREATOR = new Creator<Song>() { @Override public Song[] newArray(int size) { return new Song[size]; } @Override public Song createFromParcel(Parcel source) { long _id = source.readLong(); String title = source.readString(); String artist = source.readString(); String path = source.readString(); long duration = source.readLong(); long size = source.readLong(); Song song = new Song(); song.set_id(_id); song.setTitle(title); song.setArtist(artist); song.setPath(path); song.setDuration(duration); song.setSize(size); return song; } };上面红色标注的地方的writeToParcel和createFromParcel方法读写顺序必须要一致。
至此服务端的代码就写完了。
三客户端代码
将服务端编写的aidl和要传递的对象带着包名一起复制到客户端的代码中。报名一定不要改。
注意:客户端是通过服务端的service的action绑定的。
Intent service = new Intent(); service.setAction("com.archermind.ACTION_MUSIC_PLAYER"); bindService(service, conn, Context.BIND_AUTO_CREATE);
在绑定服务时,要传递一个ServiceConnection对象,对象定于如下。
private MusicServiceAidl musicService;
private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { musicService = (MusicServiceAidl)MusicServiceAidl.Stub.asInterface(service); try { playList = musicService.getMusicList(); } catch (RemoteException e) { e.printStackTrace(); } lv.setAdapter(myAdapter); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { try { musicService.playSong(position); } catch (RemoteException e) { e.printStackTrace(); } play.setText("暂停"); isPlaying = true; } }); } };注意:不要直接爆service强转成MusicService,而是调用MusicServiceAidl.Stub.asInterface(service)方法获得。
得到了接口对象了,就可以调用接口里的方法了。
playList = musicService.getMusicList();
相关文章推荐
- AIDL详解(AIDL、Messenger两种方式实现跨进程通信,传递自定义对象)
- Aidl 基础其一 Aidl 单方向实现以及传递自定义类的对象
- 【原】android 中通过 aidl 传递map对象
- Android中的Parcel机制 实现Bundle传递对象
- 借助Intent实现Android工程中Activity之间Java对象的传递——实现Serializable接口
- Android实用开发技巧之二:用Serializable方式及Parcelable方式实现Intent传递对象功能
- 使用HttpURLConnection实现在android客户端和服务器之间传递对象
- Android中的Parcel机制 实现Bundle传递对象
- 线程之间传递数据对象(利用线程槽实现)
- 使用AIDL实现进程间的通信之复杂类型传递 (转载liuhe688)
- AIDL实现不同应用之间跨进程通讯及传递与返回各种数据类型和远程接口回调
- 基础总结篇之四:Service完全解析--使用AIDL实现进程间的通信之复杂类型传递
- Android判断网络状态是否断开+Android完全关闭应用程序+ 本文讲述了Android中不同Activity之间的数据传递 — Bundle对象的实现(-)+Android中Bundle的使用示例
- Android Activity之间实现数据(对象,对象集合)传递
- 使用AIDL实现进程间的通信之复杂类型传递
- Android中的Parcel机制 实现Bundle传递对象
- js jquery 实现html页面之间参数传递(单一参数、对象参数传递)
- Android--Service之AIDL传递复杂对象
- 实体实现parcelable接口传递整个对象(购物车逻辑之前)
- <a>标签中href和onclick传递this对象的实现方法