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

0 0
原创粉丝点击