【Android】IPC机制(二)
2016-04-12 11:59
429 查看
Android中的IPC方式
1.使用Bundle
四大组件中的三大组件都支持在Intent中传递Bundle数据,由于Bundle接口实现了Parcelable接口,可以方便地在不同进程之间传输,传输的数据必须可以序列化,如基本数据类型、实现了Parcelable接口的对象,实现了Serialiable接口的对象等。2.使用文件共享
适合用在对数据同步要求不高的进程之间进行通信,并且要妥善处理并发读/写问题。SharedPreferences也属于文件的一种,但是在内存中会有一份SharedPreferences文件的缓存,在多线程模式下就变得非常不可靠,因此不建议在进程间通信使用SharedPreferences。3.使用Message
Message底层封装了AIDL。使用步骤:
1)服务端进程。
在服务端创建一个Service来处理客户端的连接请求。
首先,创建一个Handle来处理客户端发送过来的消息,然后,通过这个Handle对象来创建Messenger对象,最后,在Service的onBind()方法中返回Messenger对象底层的Binder。
如果需要回应客户端,则通过msg的replyTo属性获得客户端的Messenger对象来发送Message。
private static class MessagerHandle extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); System.out.println("receive msg from Client:" + msg.getData().getString("msg")); Messenger client = msg.replyTo; Message replyMessage = Message.obtain(); Bundle bundle = new Bundle(); bundle.putString("reply","嗯,你的消息我已收到,稍后会回复你"); replyMessage.setData(bundle); try { client.send(replyMessage); } catch (RemoteException e) { e.printStackTrace(); } } } private final Messenger messenger = new Messenger(new MessagerHandle()); @Override public IBinder onBind(Intent intent) { return messenger.getBinder(); }
2)客户端
绑定Service,根据服务端返回的binder对象,创建Messenger对象,并使用Messenger对象向服务端发送消息,如果客户端需要接收服务端发送的消息,也需要创建一个Handler来处理消息,并通过这个Handler对象创建一个Messenger,最后需要把接收服务端回复的Messager对象作为Message.replyTo参数传递给服务端。
private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { messenger = new Messenger(service); Message msg = Message.obtain(); Bundle bundle = new Bundle(); bundle.putString("msg", "这是从客户端发送来的消息"); msg.setData(bundle); msg.replyTo = clientMessenger; try { messenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); Intent intent = new Intent(this, MessagerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mConnection); } private Messenger clientMessenger = new Messenger(new ClientHandler()); private static class ClientHandler extends android.os.Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); System.out.println("这是服务端的回复:" + msg.getData().getString("reply")); } }
4.使用AIDL
AIDL文件所支持的数据类型:a.基本数据类型(int,long,char,boolean,double等);
b.String和CharSequence;
c.List:只支持ArrayList,里面每一个元素都必须能被AIDL文件支持;
d.Map:只支持HashMap,里面每一个元素都必须都能被AIDL文件支持,包括key,value
e.Parcelable:所有实现了Parcelable接口的对象;
f.AIDL:所有的AIDL接口本身也可以在AIDL文件中使用;
在AIDL文件中用到的自定义Parcelable对象必须新建一个和它同名的aidl文件
其内容如下:
package com.example.administrator.aidltest; parcelable Book;
自定义Parcelable对象需要显式导入到AIDL接口中
AIDL中除了基本类型的参数,其它数据类型的参数必须标上方向in,out,inout
AIDL无法使用普通接口,所以AIDL使用接口也必须创建成AIDL文件。
1)服务端实现:
创建Service供客户端连接,在Service中实现AIDL接口并在onBind方法中返回binder对象
public class AIDLService extends Service { public AIDLService() { } private CopyOnWriteArrayList<Book> mList = new CopyOnWriteArrayList<>(); @Override public void onCreate() { super.onCreate(); mList.add(new Book(1, "Android开发艺术探索")); mList.add(new Book(2,"Android群英传")); } @Override public IBinder onBind(Intent intent) { return binder; } private Binder binder = new IBookManager.Stub(){ @Override public void addBook(Book book) throws RemoteException { mList.add(book); } @Override public List<Book> getBookList() throws RemoteException { return mList; } }; }
2)客户端实现:
绑定Service,获取接口对象
Intent intent = new Intent(this, AIDLService.class); bindService(intent, conn, Context.BIND_AUTO_CREATE); private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IBookManager bookManager = IBookManager.Stub.asInterface(service); try { List<Book> list = bookManager.getBookList(); for (Book book : list) { System.out.println("bookid:" + book.bookId + ",bookname:" + book.bookName); } Book book = new Book(3,"Android源码设计模式解析与实战"); bookManager.addBook(book); List<Book> newList = bookManager.getBookList(); for (Book allbook : newList) { System.out.println("bookid:" + allbook.bookId + ",bookname:" + allbook.bookName); } } catch (RemoteException e) { e.printStackTrace(); } }
5.使用ContentProvider
6.使用Socket
不能在主线程中访问网络,在Android4.0以上的设备中会抛出android.os.NetworkOnMainThreadException,而且网络操作很可能是耗时的,放在主线程也会影响程序的响应效率。相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories