Android中IPC机制(三)
来源:互联网 发布:龙神契约龙魂升级数据 编辑:程序博客网 时间:2024/04/19 16:09
Android中IPC机制(一)
Android中IPC机制(二)
1.Android中的IPC方式
(1)使用Bunder
四大组件中的三大组件(Activity、Service、Receiver)都支持在Intent中传递Bundle数据的,由于Bundle实现了Parcelable接口,所以它可以在不同进程间传输。
(2)使用文件共享
文件共享也是一种不错的进程间通信方式,两个进程通过读/写一个文件来交换数据,A进程把数据写入文件,B进程读取文件获取数据。
MainActivity和SecondActivity属于不同的进程
在MainActivity写入数据,在SecondActivity读取数据
首先,在清单文件中加入sd卡读写的权限
<!-- 在SDCard中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 往SDCard写入数据权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
实现Serializable接口的java类
package com.zhoujian.ipc.bean;import java.io.Serializable;/** * Created by zhoujian on 2017/2/24. */public class User implements Serializable{ private static final long serialVersionUID = 1L; private int userId; private String userName; private boolean isMale; public User(boolean isMale, int userId, String userName) { this.isMale = isMale; this.userId = userId; this.userName = userName; } public boolean isMale() { return isMale; } public void setMale(boolean male) { isMale = male; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Override public String toString() { return "User{" + "isMale=" + isMale + ", userId=" + userId + ", userName='" + userName + '\'' + '}'; }}
在MainActivity中写入数据
private void saveData() { new Thread(new Runnable() { @Override public void run() { if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ File file = Environment.getExternalStorageDirectory(); File saveFile = new File(file,"zhoujian.txt"); ObjectOutputStream outputStream = null; try { User use = new User(true,1,"周建"); outputStream = new ObjectOutputStream(new FileOutputStream(saveFile)); outputStream.writeObject(use); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); }
在SecondActivity中读取数据
private void readData() { new Thread() { @Override public void run() { if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ File file = Environment.getExternalStorageDirectory(); File files = new File(file,"zhoujian.txt"); ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream(files)); User usr = (User)in.readObject(); Log.d(TAG, "获取数据成功:"+ usr.toString()); } catch (Exception e) { e.printStackTrace(); } } } }.start(); }
注意:SharedPreferences是Android中提供的轻量级存储方案,它通过键值对来存储数据,在底层是采用XML来存储键值对,每个应用的SharedPreferences文件都可以在当前包所在的data目录下查看到。一般位于/data/data/package name/shared_prefs目录下,由于系统对SharedPreferences的读写有一定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存,因此在多进程模式下,系统对它的读写就变得不可靠
(3)使用Messenger
Messenger:信使,通过它可以在不同进程中传递Message对象,Messenger是一种轻量级的IPC,底层实现是AIDL
我们从Messenger的构造方法可以看出
public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); } public Messenger(Handler target) { mTarget = target.getIMessenger(); }
Messenger对AIDL进行了封装,Messenger一次处理一个请求,因此服务端不用考虑线程同步的问题,这是因为服务端中不存在并发执行的情形。
下面以一个具体的实例,来说明Messenger如何实现进程间通信
服务端:MessengerService,服务端与客户端位于不同的进程
MessengerService.java
package com.zhoujian.ipc.service;import android.app.Service;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.Messenger;import android.os.RemoteException;import android.util.Log;/** * Created by zhoujian on 2017/2/28. */public class MessengerService extends Service{ public static final String TAG = "MessengerService"; public static final int MSG_FROM_CLIENT = 1; public static final int MSG_FROM_SERVICE = 2; class mHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_FROM_CLIENT: String message = msg.getData().getString("msg"); Log.d(TAG, "消息来自客户端:"+message); //接受到客户端的消息后,给客户端回复消息 Messenger mMessenger = msg.replyTo; //创建消息 Message mMessage = Message.obtain(null,MSG_FROM_SERVICE); Bundle mBundle = new Bundle(); mBundle.putString("message","您好客户端!你的消息我已经收到"); mMessage.setData(mBundle); try { //使用信使Messenger发送消息 mMessenger.send(mMessage); } catch (RemoteException e) { e.printStackTrace(); } break; default: super.handleMessage(msg); } } } //创建信使Messenger,传入Handler Messenger mMessenger = new Messenger(new mHandler()); @Override public IBinder onBind(Intent intent) { //返回Messenger的getBinder对象 return mMessenger.getBinder(); }}
客户端:MessengerActivity.java
package com.zhoujian.ipc.activity;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.Handler;import android.os.IBinder;import android.os.Message;import android.os.Messenger;import android.os.RemoteException;import android.util.Log;import com.zhoujian.ipc.R;import com.zhoujian.ipc.service.MessengerService;/** * Created by zhoujian on 2017/2/28. */public class MessengerActivity extends Activity{ public static final String TAG = "MessengerActivity"; public static final int MSG_FROM_CLIENT = 1; public static final int MSG_FROM_SERVICE = 2; //接受服务端发送过来的消息 Messenger mMsg = new Messenger(new Handler(){ private String mMessage; @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_FROM_SERVICE: mMessage = msg.getData().getString("message"); Log.d(TAG, "消息来自服务端:"+mMessage); break; default: super.handleMessage(msg); } } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_messenger); Intent intent = new Intent(MessengerActivity.this, MessengerService.class); //绑定服务 bindService(intent, comm, Context.BIND_AUTO_CREATE); } ServiceConnection comm = new ServiceConnection() { private Messenger mMessenger; @Override public void onServiceConnected(ComponentName name, IBinder service) { //创建信使 mMessenger = new Messenger(service); //创建消息 Message message = Message.obtain(null,MSG_FROM_CLIENT); //创建Bundle,存入消息 Bundle bundle = new Bundle(); bundle.putString("msg","你好!我是客户端"); message.setData(bundle); //重要 message.replyTo= mMsg; try { //使用信使发送消息 mMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } };}
(4)使用AIDL
Messenger是以串行的方式处理客户端发来的消息,如果大量的消息同时发送到服务端,服务端也只能一个一个处理,如果有大量的并发请求,Messenger就不合适了。
AIDL进行进程间通信
服务端
服务端首先要创建一个Service来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口
客户端
客户端要绑定服务端的Service,绑定成功后,将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了。
AIDL接口的创建
IBookManager.aidl
import com.zhoujian.ipc.aidl.Book;// Declare any non-default types here with import statementsinterface IBookManager { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ List<Book> getBookList(); void addBook(in Book book);}
AIDL文件中,并不是所有的数据类型都是可以使用的,AIDL支持的数据类型
- 基本数据类型
- String和CharSequence
- List,只支持ArrayList,里面的每一个元素都必须能够被AIDL支持
- Map,只支持HashMap,里面的每一个元素都必须能够被AIDL支持,包括key和value
- Parcelable:所有实现Parcelable接口的对象
- AIDL:所有的AIDL接口本身也可以在AIDL文件中使用
以上6种数据类型就是AIDL所支持的所有类型,其中自定义Parcelable对象和AIDL对象必须显示import进来。
注意:如果AIDL文件中使用到了自定义的Parcelable对象,那么必须新建一个和它同名的AIDL文件,并在其中声明Parcelable类型。在上面的IBookManager.aidl中,我们用到了Book这个类,所以我们必须创建Book.aidl
Book.aidl
// Book.aidlpackage com.zhoujian.ipc.aidl;// Declare any non-default types here with import statementsparcelable Book;
注意:AIDL中每个实现了Parcelable接口的类都需要按照上面方式去创建相应的AIDL文件并声明那个类为parcelable。除此之外,AIDL中除了基本数据类型,其他类型的参数必须标上方向:in、out或者inout。in表示输入型参数,out表示输出型参数,inout表示输入输出型参数。AIDL接口只支持方法,不支持声明静态常量。
远程服务端的实现,服务端和客户端位于不同进程
<service android:name=".service.BookManagerService"android:process=":romote"/>
BookManagerService.java
package com.zhoujian.ipc.service;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.os.RemoteCallbackList;import android.os.RemoteException;import com.zhoujian.ipc.aidl.Book;import com.zhoujian.ipc.aidl.IBookManager;import com.zhoujian.ipc.aidl.INewBookArrivedListener;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.atomic.AtomicBoolean;/** * Created by zhoujian on 2017/2/28. */public class BookManagerService extends Service { private AtomicBoolean mBoolean = new AtomicBoolean(false); public static final String TAG = "BookManagerService"; //CopyOnWriteArrayList支持并发的读写 CopyOnWriteArrayList<Book> bookList= new CopyOnWriteArrayList<Book>(); RemoteCallbackList<INewBookArrivedListener> listeners = new RemoteCallbackList<>(); private int mInt; @Override public void onCreate() { super.onCreate(); // AtomicBoolean //添加两本书 bookList.add(new Book(1,"安卓书籍一")); bookList.add(new Book(2,"安卓书籍二")); //开启一个线程,每隔5秒向书库中增加一本书,并通知感兴趣的用户 new Thread(new ServiceWork()).start(); } class ServiceWork implements Runnable { @Override public void run() { while (! mBoolean.get()) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } int bookId = bookList.size()+1; Book newBook = new Book(bookId,"安卓书籍"+bookId); //有新的书籍到了 onNewBookArrived(newBook); } } } private void onNewBookArrived(Book book) { bookList.add(book); mInt = listeners.beginBroadcast(); for (int i = 0; i <mInt; i++) { INewBookArrivedListener listener = listeners.getBroadcastItem(i); if (listener != null) { try { listener.onNewBookArrived(book); } catch (RemoteException e) { e.printStackTrace(); } } } listeners.finishBroadcast(); } @Override public IBinder onBind(Intent intent) { return mBinder; } //IBookManager类是AIDL文件对应的生成的java类 Binder mBinder = new IBookManager.Stub() { @Override public List<Book> getBookList() throws RemoteException { return bookList; } @Override public void addBook(Book book) throws RemoteException { bookList.add(book); } @Override public void registListenner(INewBookArrivedListener listener) throws RemoteException { listeners.register(listener); } @Override public void unregistListenner(INewBookArrivedListener listener) throws RemoteException { listeners.unregister(listener); } };}
BookManagerActivity.java
package com.zhoujian.ipc.activity;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.Handler;import android.os.IBinder;import android.os.Message;import android.os.RemoteException;import android.util.Log;import com.zhoujian.ipc.R;import com.zhoujian.ipc.aidl.Book;import com.zhoujian.ipc.aidl.IBookManager;import com.zhoujian.ipc.aidl.INewBookArrivedListener;import com.zhoujian.ipc.service.BookManagerService;import java.util.List;/** * * Created by zhoujian on 2017/2/28. */public class BookManagerActivity extends Activity{ public static final String TAG = "BookManagerActivity"; public static final int NEW_BOOK_ARRIVED= 0; private IBookManager mIBookManager; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case NEW_BOOK_ARRIVED: Log.e(TAG, "receive new book:"+(Book)msg.obj); } } }; private INewBookArrivedListener listenner = new INewBookArrivedListener.Stub() { @Override public void onNewBookArrived(Book newBook) throws RemoteException { mHandler.obtainMessage(NEW_BOOK_ARRIVED,newBook).sendToTarget(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_book_manager); Intent intent = new Intent(BookManagerActivity.this, BookManagerService.class); bindService(intent,comm, Context.BIND_AUTO_CREATE); } ServiceConnection comm = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //获取IBookManager.aidl 文件 IBookManager bookManager = IBookManager.Stub.asInterface(service); try { mIBookManager =bookManager; //在客户端调用方法获取书籍 List<Book> bookList = bookManager.getBookList(); // Log.e(TAG, "查询的书籍为"+bookList.toString()); //在客户端再添加一本书 Book book = new Book(3,"安卓开发三"); bookManager.addBook(book); Log.e(TAG, "新添加的书籍为:"+book.toString()); //再次获取所有书籍 List<Book> bookLists = bookManager.getBookList(); Log.e(TAG, "查询的书籍为"+bookLists.toString()); bookManager.registListenner(listenner); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onDestroy() { super.onDestroy(); if(mIBookManager!=null && mIBookManager.asBinder().isBinderAlive()){ try { mIBookManager.unregistListenner(listenner); } catch (RemoteException e) { e.printStackTrace(); } } unbindService(comm); }}
(5)使用ContentPrivider
请阅读我的另一篇博客:
ContentPrivider实现IPC:http://blog.csdn.net/u014005316/article/details/53407674
(6)使用Socket
请阅读我的另一篇博客:
Socket实现进程间通信:http://blog.csdn.net/u014005316/article/details/53419839
- Android中IPC机制(三)
- android IPC机制讲解(三)
- android IPC机制(三)
- android中IPC机制学习
- Android中IPC机制(一)
- Android中IPC机制(二)
- Android IPC机制学习笔记(三) Binder
- IPC机制系列之三 Android中的IPC方式
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
- Android IPC 通讯机制源码分析【中】
- Android IPC 通讯机制源码分析【中】
- Android中IPC机制之service(一)
- Android中IPC机制之(二)
- 读书笔记--IPC机制(三)
- IPC 机制(三)
- Android进阶(三)Android 中的IPC机制(1)
- mongodb 自增长
- DM8168]DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送
- oracle11g卸载(win7)
- linux --- mkdir
- 1452, 'Cannot add or update a child row: a foreign key constraint fails
- Android中IPC机制(三)
- 枚举类型理解
- c# 占位符的使用
- 第一行代码学习2(7)
- android 对话框(Dialog)使用
- 程序装入的具体过程
- Python Vs Java(从Java到Python)
- 织梦标签{dede:global.cfg_templets_skin/}不解析
- 多线程编程2