首页 > 系统 > Android > 正文

Android中IPC机制(三)

2019-11-06 09:53:47
字体:
来源:转载
供稿:网友

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和CharSequenceList,只支持ArrayList,里面的每一个元素都必须能够被AIDL支持Map,只支持HashMap,里面的每一个元素都必须能够被AIDL支持,包括key和valueParcelable:所有实现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.RemoteException;import com.zhoujian.ipc.aidl.Book;import com.zhoujian.ipc.aidl.IBookManager;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;/** * Created by zhoujian on 2017/2/28. */public class BookManagerService extends Service { //CopyOnWriteArrayList支持并发的读写 CopyOnWriteArrayList<Book> bookList= new CopyOnWriteArrayList<Book>(); @Override public void onCreate() { super.onCreate(); //添加两本书 bookList.add(new Book(1,"安卓书籍一")); bookList.add(new Book(2,"安卓书籍二")); } @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); } };}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表