Android跨进程通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/likuan0214/article/details/78781393

本文基于《Android开发艺术探索》,是一本不错的进阶书籍。

多进程

IPC(Inter-Process Communication):进程间通信或者跨进程通信,两个进程间进行数据交换的过程。
线程:CPU调度的最小单元。
进程:一个执行单元,比如一个程序活着应用。
一个进程可以包含多个线程。

在Android中使用多进程的方法:在AndroidManifest.xml中指定android:process属性。
比如:

        <service
            android:name=".socket.TCPService"
            android:enabled="true"
            android:exported="true"
            android:process=":socket" />

        <provider
            android:name=".contentprovider.BookProvider"
            android:authorities="com.study.ipcdemo.contentprovider.provider"
            android:permission="com.study.ipcdemo.PROVIDER"
            android:process=":provider" />

查看应用下的进程:

bogon:~ ygdx_lk$ adb shell ps | grep com.study.ipcdemo
u0_a194   10016 233   554152 28292 ffffffff 00000000 S com.study.ipcdemo
u0_a194   10030 233   534616 16640 ffffffff 00000000 S com.study.ipcdemo:binderpool

多进程会导致的问题:
1.静态成员和单例模式失去作用。
2.线程同步机制失效。
3.SharedPreferences的可靠性下降。
SharedPreferences底层是通过读写XML文件实现的,并发读写都可能出问题。
4.Application会多次创建。

序列化

静态成员变量和transient关键字标记的成员变量不参与序列化过程。

Serializable

Serializable是Java提供的一个序列化接口,为对象提供标准的序列化和反序列化操作。

package com.study.ipcdemo.serializableparcelable;

import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * Created by ygdx_lk on 17/12/9.
 */

public class SerializableUser implements Serializable {
    private static final String TAG = "SerializableUser";
    private static final long serialVersionUID = 4455919821130069028L;
    public int id;
    public String userName;
    public boolean isMale;

    public SerializableUser(int id, String userName, boolean isMale) {
        this.id = id;
        this.userName = userName;
        this.isMale = isMale;
    }

    @Override
    public String toString() {
        return "id:" + id + " name:" + userName + " isMale:" + isMale;
    }

    /**
     12-09 16:28:17.469 20334-20334/com.study.ipcdemo I/SerializableUser:     user: id:1 name:danny isMale:false
     12-09 16:28:17.469 20334-20334/com.study.ipcdemo I/SerializableUser: new user: id:1 name:danny isMale:false
     */
    public static void test(){
        SerializableUser user = new SerializableUser(1, "danny", false);
        try {

            //序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(user);
            out.close();


            //反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream in = new ObjectInputStream(bis);
            SerializableUser newUser = (SerializableUser) in.readObject();
            in.close();
            bis.close();
            bos.close();

            Log.i(TAG, "user: " + user.toString());
            Log.i(TAG, "new user: " + newUser.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Parcelable

package com.study.ipcdemo.serializableparcelable;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by ygdx_lk on 17/12/9.
 */

public class ParcelableUser implements Parcelable {
    private static final String TAG = "ParcelableUser";
    public int id;
    public String name;
    public boolean isMale;
    public Book book;

    //从序列化后的对象中创建原始对象
    protected ParcelableUser(Parcel in) {
        id = in.readInt();
        name = in.readString();
        isMale = in.readInt() == 1;
        book = in.readParcelable(Thread.currentThread().getContextClassLoader());
    }

    public ParcelableUser(int id, String name, boolean isMale, Book book) {
        this.id = id;
        this.name = name;
        this.isMale = isMale;
        this.book = book;
    }

    @Override
    public String toString() {
        return "id:" + id + " name:" + name + " isMale:" + isMale + " Book:" + book;
    }

    public static final Creator<ParcelableUser> CREATOR = new Creator<ParcelableUser>() {
        //从序列化后的对象中创建原始对象
        @Override
        public ParcelableUser createFromParcel(Parcel in) {
            return new ParcelableUser(in);
        }

        //创建指定长度的原始对象数组
        @Override
        public ParcelableUser[] newArray(int size) {
            return new ParcelableUser[size];
        }
    };

    //返回当前对象的内容描述。如果含有文件描述符,返回1,否则返回0,几乎所有情况都返回0
    @Override
    public int describeContents() {
        return 0;
    }

    //将当前对象写入序列化结构中,其中flags标识有两种值:0或者1。
    //为1时标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为0
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
        dest.writeInt(isMale ? 1 : 0);
        dest.writeParcelable(book, 0);
    }

}

Binder

Binder是android中的一个类,它实现了IBinder接口。
Binder是android中的一种跨进程通信方式。
Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager)和相应ManagerService的桥梁。
Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含服务端业务调用的Binder对象,通过这个Binder,客户端可以获取服务端提供的服务或者数据。

Binder主要用于Service,包括AIDL和Messenger。Messenger的底层是AIDL。

AIDL

AIDL:Android Interface Definition Language,即Android接口定义语言。

aidl实现:
1.新建项目包名:com.study.ipcdemo
2.新建aidl,路径和包名一致
这里写图片描述
最终结构如下:
这里写图片描述
3.分别在aidl和java的com.study.ipcdemo下新建binderaidl包
在java的ipcdemo下创建Book.java

package com.study.ipcdemo.binderaidl;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by ygdx_lk on 17/12/9.
 */

public class Book implements Parcelable {

    public int id;
    public String name;

    public Book(int id, String name) {
        this.id = id;
        this.name = name;
    }

    protected Book(Parcel in) {
        id = in.readInt();
        name = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
    }
}

在aidl的binderaidl包下创建:
Book.aidl

package com.study.ipcdemo.binderaidl;
parcelable Book;

IOnNewBookArrivedListener.aidl

// IOnNewBookArrivedListener.aidl
package com.study.ipcdemo.binderaidl;

import com.study.ipcdemo.binderaidl.Book;

interface IOnNewBookArrivedListener {
    void onNewBookArrived(in Book newBook);
}

IBookManager.aidl

// IBookManager.aidl
package com.study.ipcdemo.binderaidl;
import com.study.ipcdemo.binderaidl.Book;
import com.study.ipcdemo.binderaidl.IOnNewBookArrivedListener;

interface IBookManager {

            List<Book> getBookList();
            void addBook(in Book book);
            void registerListener(IOnNewBookArrivedListener listener);
            void unregisterListener(IOnNewBookArrivedListener listener);
}

在Java的binderaidl下新建service包并创建AidlService

package com.study.ipcdemo.binderaidl.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;

import com.study.ipcdemo.binderaidl.Book;
import com.study.ipcdemo.binderaidl.IBookManager;
import com.study.ipcdemo.binderaidl.IOnNewBookArrivedListener;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

public class AidlService extends Service {
    private static final String TAG = "AidlService";
    //书籍列表
    CopyOnWriteArrayList<Book> bookList = new CopyOnWriteArrayList<>();
    //service是否被销毁
    private AtomicBoolean mIsServiceDestroyed = new AtomicBoolean(false);
    //客户端的监听列表
    private RemoteCallbackList<IOnNewBookArrivedListener> listeners = new RemoteCallbackList<>();


    public AidlService() {}

    @Override
    public void onCreate() {
        super.onCreate();
        bookList.add(new Book(1, "android"));
        bookList.add(new Book(2, "java"));

        new Thread(new ServiceWorker()).start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mIsServiceDestroyed.set(true);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new IBookManager.Stub() {
            @Override
            public List<Book> getBookList() throws RemoteException {
                Log.i(TAG, "getBookList: service");
                SystemClock.sleep(5000);
                return bookList;
            }

            @Override
            public void addBook(Book book) throws RemoteException {
                if(!bookList.contains(book)){
                    Log.i(TAG, "addBook: service");
                    bookList.add(book);
                }
            }

            @Override
            public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
                listeners.register(listener);
                Log.i(TAG, "registerListener: add listener");
            }

            @Override
            public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
                listeners.unregister(listener);
                Log.i(TAG, "unregisterListener: unregister listener succeed.");
            }
        };
    }



    //每隔5分钟添加一本书,并且通知客户端
    private class ServiceWorker implements Runnable {
        @Override
        public void run() {
            while (!mIsServiceDestroyed.get()){
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int id = bookList.size() + 1;
                Book book = new Book(id, "new book#" + id);
                try {
                    onNewBookArrived(book);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void onNewBookArrived(Book book) throws RemoteException{
        bookList.add(book);
        Log.i(TAG, "onNewBookArrived: notify all linsteners");
        int N = listeners.beginBroadcast();
        for (int i = 0; i < N; i++) {
            IOnNewBookArrivedListener listener = listeners.getBroadcastItem(i);
            if(listener != null) {
                listener.onNewBookArrived(book);
            }
        }
        listeners.finishBroadcast();
    }
}

MainActivity.java

package com.study.ipcdemo;

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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.study.ipcdemo.binderaidl.Book;
import com.study.ipcdemo.binderaidl.IBookManager;
import com.study.ipcdemo.binderaidl.IOnNewBookArrivedListener;
import com.study.ipcdemo.binderaidl.service.AidlService;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    private static final int MESSAGE_NEW_BOOK_ARRIVED = 1;
    //远程服务器
    private IBookManager remoteService;
    //断开连接后,重新连接
    private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            if(remoteService == null)return;
            remoteService.asBinder().unlinkToDeath(deathRecipient, 0);
            remoteService = null;
            //重新绑定远程服务
            bindService();
        }
    };


    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, final IBinder service) {
            new Thread(){
                @Override
                public void run() {
                    super.run();
                    Log.i(TAG, "onServiceConnected: ");
                    //连接成功后,获取远程服务器接口对象
                    remoteService = IBookManager.Stub.asInterface(service);

                    try {
                        //获取远程的书籍列表
                        List<Book> list = remoteService.getBookList();
                        Log.i(TAG, "onServiceConnected: query book list, list  type:" + list.getClass().getCanonicalName());
                        Log.i(TAG, "onServiceConnected: query book list:" + list.toString());


                        //添加一本书到服务器
                        Book newBook = new Book(3, "php");
                        remoteService.addBook(newBook);
                        Log.i(TAG, "onServiceConnected: add ok new book");

                        //获取远程服务器更新后的书籍列表
                        List<Book> list1 = remoteService.getBookList();
                        Log.i(TAG, "onServiceConnected: query book list:" + list1.toString());

                        //注册服务器新书通知的监听
                        remoteService.registerListener(mOnNewBookArrivedListener);

                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }


                    try {
                        //连接断开的重连操作
                        service.linkToDeath(deathRecipient, 0);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }.start();

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "onServiceDisconnected: binder died");
            remoteService = null;
        }
    };


    private IOnNewBookArrivedListener mOnNewBookArrivedListener = new IOnNewBookArrivedListener.Stub() {
        @Override
        public void onNewBookArrived(Book newBook) throws RemoteException {
            //接收到新书消息
            mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRIVED, newBook).sendToTarget();
        }
    };

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MESSAGE_NEW_BOOK_ARRIVED:
                    Log.i(TAG, "handleMessage: recived new book:" + ((Book)msg.obj).toString());
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);

        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            remoteService.addBook(new Book(1, "test"));
                            List<Book> list = remoteService.getBookList();
                            Log.i(TAG, "onClick: size:" + list.size());
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });

        bindService();

    }

    //绑定服务器
    private void bindService() {
        Intent intent = new Intent(this, AidlService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(remoteService != null && remoteService.asBinder().isBinderAlive()){
            try {
                remoteService.unregisterListener(mOnNewBookArrivedListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        unbindService(mConnection);
    }

}

4.在AndroidManifest.xml中修改AidlService为bookservice进程

        <service
            android:name=".binderaidl.service.AidlService"
            android:enabled="true"
            android:exported="true"
            android:process=":bookservice" />

最终结构如下:
这里写图片描述

运行结果:

12-12 15:20:59.668 16056-16085/com.study.ipcdemo I/MainActivity: onServiceConnected: query book list, list  type:java.util.ArrayList
12-12 15:20:59.668 16056-16085/com.study.ipcdemo I/MainActivity: onServiceConnected: query book list:[id:1  name:android, id:2  name:java, id:3  name:new book#3]
12-12 15:20:59.668 16056-16085/com.study.ipcdemo I/MainActivity: onServiceConnected: add ok new book
12-12 15:21:04.668 16056-16085/com.study.ipcdemo I/MainActivity: onServiceConnected: query book list:[id:1  name:android, id:2  name:java, id:3  name:new book#3, id:3  name:php, id:5  name:new book#5]
12-12 15:21:09.628 16056-16056/com.study.ipcdemo I/MainActivity: handleMessage: recived new book:id:6  name:new book#6
12-12 15:21:14.628 16056-16056/com.study.ipcdemo I/MainActivity: handleMessage: recived new book:id:7  name:new book#7
12-12 15:21:19.628 16056-16056/com.study.ipcdemo I/MainActivity: handleMessage: recived new book:id:8  name:new book#8

AIDL的实现过程:
1.在aidl下创建A.aidl文件,并定义对应的抽象方法。
如果用到一些序列化对象,比如Book,就需要新建Book.aidl并且和客户端的Book路径一致。
如客户端的路径是:com.a.b.Book.java,则服务器也需要在com.a.b.Book.aidl创建
并且在A.aidl中要全路径引入Book:
import com.a.b.Book;
2.新建Service服务器,并且在
public abstract IBinder onBind(Intent intent)方法中
返回binder:

return new A.Stub(){
    //A中定义好的方法
    ....
}

3.接下来就是客户端绑定服务器了

        Intent intent = new Intent(this, AidlService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

mConnection是ServiceConnection:

public interface ServiceConnection {
     //连接成功
     void onServiceConnected(ComponentName name, IBinder service);
     //失去连接
    void onServiceDisconnected(ComponentName name);
}

可以在onServiceConnected中获取服务器返回的binder

remoteService = IBookManager.Stub.asInterface(service);

调用IBookManager对应的服务器方法。

绑定服务器,也要忘记关闭Activity时解绑:

unbindService(mConnection);

Messenger

Messenger信使,通过它可以在不同进程间传递Message对象,在Message放入需要传递的数据,即可实现数据的进程间的传递。
Messenger是一种轻量级的IPC方案,的底层是AIDL。

public final class Messenger implements Parcelable {
    private final IMessenger mTarget;

    /**
     * Create a new Messenger pointing to the given Handler.  Any Message
     * objects sent through this Messenger will appear in the Handler as if
     * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
     * been called directly.
     * 
     * @param target The Handler that will receive sent messages.
     */
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }

    /**
     * Send a Message to this Messenger's Handler.
     * 
     * @param message The Message to send.  Usually retrieved through
     * {@link Message#obtain() Message.obtain()}.
     * 
     * @throws RemoteException Throws DeadObjectException if the target
     * Handler no longer exists.
     */
    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }

    /**
     * Retrieve the IBinder that this Messenger is using to communicate with
     * its associated Handler.
     * 
     * @return Returns the IBinder backing this Messenger.
     */
    public IBinder getBinder() {
        return mTarget.asBinder();
    }

    /**
     * Comparison operator on two Messenger objects, such that true
     * is returned then they both point to the same Handler.
     */
    public boolean equals(Object otherObj) {
        if (otherObj == null) {
            return false;
        }
        try {
            return mTarget.asBinder().equals(((Messenger)otherObj)
                    .mTarget.asBinder());
        } catch (ClassCastException e) {
        }
        return false;
    }

    public int hashCode() {
        return mTarget.asBinder().hashCode();
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeStrongBinder(mTarget.asBinder());
    }

    public static final Parcelable.Creator<Messenger> CREATOR
            = new Parcelable.Creator<Messenger>() {
        public Messenger createFromParcel(Parcel in) {
            IBinder target = in.readStrongBinder();
            return target != null ? new Messenger(target) : null;
        }

        public Messenger[] newArray(int size) {
            return new Messenger[size];
        }
    };

    /**
     * Convenience function for writing either a Messenger or null pointer to
     * a Parcel.  You must use this with {@link #readMessengerOrNullFromParcel}
     * for later reading it.
     * 
     * @param messenger The Messenger to write, or null.
     * @param out Where to write the Messenger.
     */
    public static void writeMessengerOrNullToParcel(Messenger messenger,
            Parcel out) {
        out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
                : null);
    }

    /**
     * Convenience function for reading either a Messenger or null pointer from
     * a Parcel.  You must have previously written the Messenger with
     * {@link #writeMessengerOrNullToParcel}.
     * 
     * @param in The Parcel containing the written Messenger.
     * 
     * @return Returns the Messenger read from the Parcel, or null if null had
     * been written.
     */
    public static Messenger readMessengerOrNullFromParcel(Parcel in) {
        IBinder b = in.readStrongBinder();
        return b != null ? new Messenger(b) : null;
    }

    /**
     * Create a Messenger from a raw IBinder, which had previously been
     * retrieved with {@link #getBinder}.
     * 
     * @param target The IBinder this Messenger should communicate with.
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }
}

实现:
1.新建MessagerService

package com.study.ipcdemo.binderaidl.messenger;

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;

public class MessagerService extends Service {
    private static final String TAG = "MessagerService";
    private static class MessageHandler extends Handler{
        int replyCount = 0;
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MyConstants.MSG_FROM_CLIENT:
                //接收到客户端发来的消息
                    Log.i(TAG, "handleMessage: client:" + msg.getData().getString("msg"));
                    Messenger client = msg.replyTo;
                    Message replyMessage = Message.obtain(null, MyConstants.MSG_FROM_SERVICE);
                    Bundle bundle = new Bundle();
                    bundle.putString("msg", "ok, i recived, i will reply to you later " + ++replyCount);
                    replyMessage.setData(bundle);
                    try {
                        client.send(replyMessage);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    private final Messenger messenger = new Messenger(new MessageHandler());

    public MessagerService() {}

    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}

public class MyConstants {
    public static final int MSG_FROM_CLIENT = 1;
    public static final int MSG_FROM_SERVICE = 2;
}

2.Main2Acitivity.java

package com.study.ipcdemo;

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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import com.study.ipcdemo.binderaidl.messenger.MessagerService;
import com.study.ipcdemo.binderaidl.messenger.MyConstants;

public class Main2Activity extends AppCompatActivity {


    private static final String TAG = "Main2Activity";

    private Messenger mService;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i(TAG, "onServiceConnected: ");
            //绑定成功以后,保存service到Messenger进行消息发送
            mService = new Messenger(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "onServiceDisconnected: ");
        }
    };



    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MyConstants.MSG_FROM_SERVICE:
                    Log.i(TAG, "handleMessage: service:" + msg.getData().getString("msg"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }


    private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        //绑定service
        bindService();

        findViewById(R.id.bt_send).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //发送消息到服务器
                Message msg = Message.obtain(null, MyConstants.MSG_FROM_CLIENT);
                Bundle data = new Bundle();
                data.putString("msg", "hello, this is client");
                msg.setData(data);
                msg.replyTo = mGetReplyMessenger;

                try {
                    mService.send(msg);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

    }

    private void bindService() {
        Intent intent = new Intent(this, MessagerService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);
    }
}

3.AndroidMainfest.xml

        <service
            android:name=".binderaidl.messenger.MessagerService"
            android:enabled="true"
            android:exported="true"
            android:process=":messager" />

运行结果:

服务器
12-12 15:57:42.288 17870-17870/com.study.ipcdemo:messager I/MessagerService: handleMessage: client:hello, this is client
客户端
12-12 15:57:42.288 17800-17800/com.study.ipcdemo I/Main2Activity: handleMessage: service:ok, i recived, i will reply to you later 1

ContentProvider

ContentProvider是Android中提供的专门用于不用应用间进行数据共享的方式。ContentProvider的底层实现也是Binder。

系统预置了许多ContentProvider,比如通讯录等,要跨进程访问这些信息,只需要通过ContentProvider的query、update、insert和delete方法即可。

自定义一个ContnetProvider只需要继承ContentProvider,并且实现onCreate、query、update、insert、delete和getType方法。

onCreate代表ContentProvider的创建,一般来说我们需要做一些初始化工作。
getType用来返回Uri请求对应的MIME类型(媒体类型),比如图片、视频等。可以直接返回null。
剩下的就是CRUD操作,即对数据表的增删改查功能。

实现:
1.AndroidManifest.xml

        <provider
            android:name=".contentprovider.BookProvider"
            android:authorities="com.study.ipcdemo.contentprovider.provider"
            android:permission="com.study.ipcdemo.PROVIDER"
            android:process=":provider" />

2.创建DbOpenHelper

package com.study.ipcdemo.contentprovider;

import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by ygdx_lk on 17/12/11.
 */

public class DbOpenHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "book_provider.db";
    public static final String BOOK_TABLE_NAME = "book";
    public static final String USER_TABLE_NAME = "user";

    private static final int DB_VERSION = 1;

    private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS " + BOOK_TABLE_NAME + "(_id INTEGER PRIMARY KEY, name Text)";
    private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS " + USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY, name TEXT, sex INT)";

    public DbOpenHelper(Context context){
        this(context, DB_NAME, null, DB_VERSION);
    }

    public DbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        this(context, name, factory, version, null);
    }

    public DbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK_TABLE);
        db.execSQL(CREATE_USER_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

3.创建BookProvider

package com.study.ipcdemo.contentprovider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

/**
 * Created by ygdx_lk on 17/12/11.
 */

public class BookProvider extends ContentProvider {
    private static final String TAG = "BookProvider";

    public static final String AUTHORITY = "com.study.ipcdemo.contentprovider.provider";
    public static final Uri BOOK_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/book");
    public static final Uri USER_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/user");
    public static final int BOOK_URI_CODE = 0;
    public static final int USER_URI_CODE = 1;

    private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        uriMatcher.addURI(AUTHORITY, "book", BOOK_URI_CODE);
        uriMatcher.addURI(AUTHORITY, "user", USER_URI_CODE);
    }

    private SQLiteDatabase mDb;

    private String getTableName(Uri uri){
        String tableName;
        switch (uriMatcher.match(uri)){
            case BOOK_URI_CODE:
                tableName = DbOpenHelper.BOOK_TABLE_NAME;
                break;
            case USER_URI_CODE:
                tableName = DbOpenHelper.USER_TABLE_NAME;
                break;
            default:
                tableName = "";
                break;
        }
        return tableName;
    }

    @Override
    public boolean onCreate() {
        Log.i(TAG, "onCreate: " + Thread.currentThread().getName());
        new Thread(new Runnable() {
            @Override
            public void run() {
            }
        }).start();
        initProviderData();

        return true;
    }

    private void initProviderData() {
        mDb = new DbOpenHelper(getContext()).getWritableDatabase();
        mDb.execSQL("delete from " + DbOpenHelper.USER_TABLE_NAME);
        mDb.execSQL("delete from " + DbOpenHelper.BOOK_TABLE_NAME);
        mDb.execSQL("insert into book values(3, 'android');");
        mDb.execSQL("insert into book values(4, 'ios');");
        mDb.execSQL("insert into book values(5, 'php');");
        mDb.execSQL("insert into user values(1, 'jake', 1);");
        mDb.execSQL("insert into user values(2, 'danny', 0);");
        Log.i(TAG, "initProviderData: " + mDb);
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        Log.i(TAG, "query: " + Thread.currentThread().getName());
        String table = getTableName(uri);
        if(!TextUtils.isEmpty(table)){
            return mDb.query(table, projection, selection, selectionArgs, null, null, sortOrder, null);
        }
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        Log.i(TAG, "getType: " + uri);
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        Log.i(TAG, "insert: ");
        String table = getTableName(uri);
        mDb.insert(table, null, values);
        getContext().getContentResolver().notifyChange(uri, null);
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        Log.i(TAG, "delete: ");
        String table = getTableName(uri);
        int count = mDb.delete(table, selection, selectionArgs);
        if(count > 0){
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return count;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        Log.i(TAG, "update: ");
        String table = getTableName(uri);
        int row = mDb.update(table, values, selection, selectionArgs);
        if(row > 0){
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return row;
    }
}

4.Main3Activity.java

package com.study.ipcdemo;

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class Main3Activity extends AppCompatActivity {
    private static final String TAG = "Main3Activity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);



        Uri uri = Uri.parse("content://com.study.ipcdemo.contentprovider.provider/book");
        ContentValues values = new ContentValues();
        values.put("_id", 6);
        values.put("name", "html");
        getContentResolver().insert(uri, values);

        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        if(cursor != null){
            while (cursor.moveToNext()){
                Log.i(TAG, "onCreate: " + cursor.getInt(0) + " " + cursor.getString(1));
            }
        }
        cursor.close();


        Uri userUri = Uri.parse("content://com.study.ipcdemo.contentprovider.provider/user");
        Cursor userCursor = getContentResolver().query(userUri, new String[]{"_id", "name", "sex"}, null, null,null);
        while (userCursor.moveToNext()){
            Log.i(TAG, "onCreate: " + userCursor.getInt(0) + " " + userCursor.getString(1) + " " + userCursor.getInt(2));
        }
        userCursor.close();
    }
}

运行结果:
服务器

12-12 16:14:35.798 18494-18494/com.study.ipcdemo:provider I/BookProvider: onCreate: main
12-12 16:14:35.828 18494-18494/com.study.ipcdemo:provider I/BookProvider: initProviderData: SQLiteDatabase: /data/user/0/com.study.ipcdemo/databases/book_provider.db
12-12 16:14:35.828 18494-18505/com.study.ipcdemo:provider I/BookProvider: insert: 
12-12 16:14:35.828 18494-18506/com.study.ipcdemo:provider I/BookProvider: query: Binder_2
12-12 16:14:35.838 18494-18506/com.study.ipcdemo:provider I/BookProvider: query: Binder_2

客户端

12-12 16:14:35.838 18481-18481/com.study.ipcdemo I/Main3Activity: onCreate: 3 android
12-12 16:14:35.838 18481-18481/com.study.ipcdemo I/Main3Activity: onCreate: 4 ios
12-12 16:14:35.838 18481-18481/com.study.ipcdemo I/Main3Activity: onCreate: 5 php
12-12 16:14:35.838 18481-18481/com.study.ipcdemo I/Main3Activity: onCreate: 6 html
12-12 16:14:35.838 18481-18481/com.study.ipcdemo I/Main3Activity: onCreate: 1 jake 1
12-12 16:14:35.838 18481-18481/com.study.ipcdemo I/Main3Activity: onCreate: 2 danny 0

需要注意的是:
由于采用的是SQLite并且只有一个SQLiteDatabase的连接,所以可以正确应对多线程的情况,因为SQLiteDatabase内部对数据库的操作是有同步处理的,但是如果通过多个SQLiteDatabase对象来操作数据库,就无法保证线程同步,因为SQLiteDatabase对象之间无法进行线程同步。

Socket

Socket,也成为套接字,它分为流式套接字和用户数据报套接字两种,分别对应网络的传输控制层中的TCP和UDP。
TCP协议是面向连接的协议,提供稳定的双向通信功能,TCP连接的建立需要经过三次握手才能完成,为了提供稳定的数据传输功能,其本身提供了超时重传机制,因此具有很高的稳定性。
UDP是无连接的,提供不稳定的单向通信功能。

使用Socket进行通信,需要声明权限

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

实现:
1.创建TCPServerService

package com.study.ipcdemo.socket;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

/**
 * Created by ygdx_lk on 17/12/11.
 */

public class TCPService extends Service {
    private static final String TAG = "TCPService";
    //service是否销毁了
    private boolean mIsServiceDestroyed = false;
    //随机回复内容
    private String[] mDefinedMessages = new String[]{
            "hello, aaa",
            "hello, bbb",
            "hello, ccc",
            "hello, ddd",
            "hello, eee"
    };

    @Override
    public void onCreate() {
        super.onCreate();
        //socket需要在子线程执行
        //启动socket
        new Thread(new TcpServer()).start();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        mIsServiceDestroyed = true;
        super.onDestroy();
    }

    private class TcpServer implements Runnable{
        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try {
                //创建8888端口的socket
                serverSocket = new ServerSocket(8888);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }

            //如果service没有销毁,则循环读取消息
            while (!mIsServiceDestroyed){
                try {
                    Log.i(TAG, "run: 等待获取消息");
                    final Socket client = serverSocket.accept();
                    Log.i(TAG, "run: 获取到消息");
                    new Thread(){
                        @Override
                        public void run() {
                            super.run();
                            try {
                                //回应客户端
                                responseClient(client);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void responseClient(Socket client) throws IOException {
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
            while (!mIsServiceDestroyed){//循环读取客户端的消息
                Log.i(TAG, "responseClient: 循环读取客户端发来的消息");
                String str = in.readLine();//这里是阻塞的方式,没有消息就会一直阻塞。
                if(str == null){
                    break;
                }
                Log.i(TAG, "接收到客户端发来的消息: " + str);
                int i = new Random().nextInt(mDefinedMessages.length);
                String msg = mDefinedMessages[i];
                out.println(msg);
            }
            //断开消息
            Log.i(TAG, "responseClient: 断开连接");
            out.close();
            out = null;
            in.close();
            in = null;
            client.close();
        }
    }

}

2.Main4Activity

package com.study.ipcdemo;

import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.study.ipcdemo.socket.TCPService;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main4Activity extends AppCompatActivity implements View.OnClickListener{

    private static final int MESSAGE_RECEIVE_NEW_MSG = 1;
    private static final int MESSAGE_SOCKET_CONNETED = 2;
    private TextView tv_msg;
    private EditText et_msg;
    private Button bt_send;
    private PrintWriter printWriter;
    private Socket client;
    private static final String TAG = "Main4Activity";
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MESSAGE_RECEIVE_NEW_MSG:
                    tv_msg.setText(tv_msg.getText() + (String)msg.obj);
                    break;
                case MESSAGE_SOCKET_CONNETED:
                    bt_send.setEnabled(true);
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);

        tv_msg = findViewById(R.id.tv_msg);
        et_msg = findViewById(R.id.et_msg);
        bt_send = findViewById(R.id.bt_send);

        bt_send.setOnClickListener(this);


        //启动服务器
        startService(new Intent(this, TCPService.class));


        //连接服务器
        new Thread(){
            @Override
            public void run() {
                super.run();
                connectTCPServer();
            }
        }.start();

    }

    @Override
    protected void onDestroy() {
        if(client != null){
            try {
                client.shutdownInput();
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        super.onDestroy();
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_send:
                //发送消息
                String msg = et_msg.getText().toString();
                if(!TextUtils.isEmpty(msg) && printWriter != null){
                    printWriter.println(msg);
                    et_msg.setText("");
                }
                String time = formatDateTime(System.currentTimeMillis());
                final String showedMsg = "self " + time + ":" + msg + "\n";
                tv_msg.setText(tv_msg.getText()  + showedMsg);

                break;
        }
    }

    //格式化时间
    private String formatDateTime(long l) {
        return new SimpleDateFormat("(HH:mm:ss)").format(new Date(l));
    }

    //连接服务器
    private void connectTCPServer() {
        Socket socket = null;
        while (socket == null){
            try {
                //连接到远程服务器8888端口
                socket = new Socket("localhost", 8888);
                client = socket;
                //获取输出流
                printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNETED);
                Log.i(TAG, "connectTCPServer: connect success");
            } catch (IOException e) {
                SystemClock.sleep(1000);
                Log.i(TAG, "connectTCPServer: connect tcp server failed, retry...");
                e.printStackTrace();
            }
        }

        try {
            //获取输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (!Main4Activity.this.isFinishing()){//循环读取服务器发来的消息
                Log.i(TAG, "connectTCPServer: 循环读取服务器发来的消息");
                String msg = br.readLine();//这里会一直阻塞,直到获取到消息
                Log.i(TAG, "connectTCPServer: 读取到:" + msg);
                if(msg != null){
                    String time = formatDateTime(System.currentTimeMillis());
                    msg = "server " + time + ":" + msg + "\n";
                    mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, msg).sendToTarget();
                }
            }
            Log.i(TAG, "connectTCPServer: quit...");
            br.close();
            br = null;
            printWriter.close();
            printWriter = null;
            socket.close();
            socket = null;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

3.AndroidManifest.xml

        <service
            android:name=".socket.TCPService"
            android:enabled="true"
            android:exported="true"
            android:process=":socket" />

运行结果:
客户端:

12-12 16:38:06.368 19660-19678/com.study.ipcdemo I/Main4Activity: connectTCPServer: connect tcp server failed, retry...
12-12 16:38:06.368 19660-19678/com.study.ipcdemo W/System.err: java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 8888): connect failed: ECONNREFUSED (Connection refused)
12-12 16:38:06.368 19660-19678/com.study.ipcdemo W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:114)
12-12 16:38:06.368 19660-19678/com.study.ipcdemo W/System.err:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at java.net.Socket.startupSocket(Socket.java:566)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at java.net.Socket.tryAllAddresses(Socket.java:128)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at java.net.Socket.<init>(Socket.java:178)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at java.net.Socket.<init>(Socket.java:150)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at com.study.ipcdemo.Main4Activity.connectTCPServer(Main4Activity.java:125)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at com.study.ipcdemo.Main4Activity.access$200(Main4Activity.java:28)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err:     at com.study.ipcdemo.Main4Activity$2.run(Main4Activity.java:76)
12-12 16:38:06.378 19660-19678/com.study.ipcdemo W/System.err: Caused by: libcore.io.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
12-12 16:38:06.388 19660-19678/com.study.ipcdemo W/System.err:     at libcore.io.Posix.connect(Native Method)
12-12 16:38:06.388 19660-19678/com.study.ipcdemo W/System.err:     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85)
12-12 16:38:06.388 19660-19678/com.study.ipcdemo W/System.err:     at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
12-12 16:38:06.388 19660-19678/com.study.ipcdemo W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:112)
12-12 16:38:06.388 19660-19678/com.study.ipcdemo W/System.err:  ... 9 more
12-12 16:38:06.398 19660-19678/com.study.ipcdemo I/Main4Activity: connectTCPServer: connect success
12-12 16:38:06.398 19660-19678/com.study.ipcdemo I/Main4Activity: connectTCPServer: 循环读取服务器发来的消息
12-12 16:38:18.908 19660-19678/com.study.ipcdemo I/Main4Activity: connectTCPServer: 读取到:hello, bbb
12-12 16:38:18.908 19660-19678/com.study.ipcdemo I/Main4Activity: connectTCPServer: 循环读取服务器发来的消息

服务器:


12-12 16:38:05.418 19674-19689/com.study.ipcdemo:socket I/TCPService: run: 等待获取消息
12-12 16:38:06.398 19674-19689/com.study.ipcdemo:socket I/TCPService: run: 获取到消息
12-12 16:38:06.428 19674-19689/com.study.ipcdemo:socket I/TCPService: run: 等待获取消息
12-12 16:38:06.428 19674-19692/com.study.ipcdemo:socket I/TCPService: responseClient: 循环读取客户端发来的消息
12-12 16:38:18.888 19674-19692/com.study.ipcdemo:socket I/TCPService: 接收到客户端发来的消息: 1
12-12 16:38:18.918 19674-19692/com.study.ipcdemo:socket I/TCPService: responseClient: 循环读取客户端发来的消息

Binder连接池

Binder连接池的作用是控制Service的数量,通过一个Service来管理所有的AIDL。将每个业务模块的Binder请求统一发送到远程Service去执行,从而避免重复创建Service。

工作机制:
每个业务模块创建自己的AIDL接口并实现。
然后向服务端提供自己的唯一标识和其对应的Binder对象。
对于服务端来说,只需要一个Service,服务端提供一个queryBinder接口,这个接口根据业务模块的标识来返回相应的BInder对象给它们,不同的业务模块拿到所需的Binder对象后就可以进行远程方法调用。

1.新建IBinderPool.aidl、ICompute.aidl、ISecurityCenter.aidl

// IBinderPool.aidl
package com.study.ipcdemo.binderpool;

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}

//ICompute.aidl
package com.study.ipcdemo.binderpool;

interface ICompute {
    int add(int a, int b);
}


//ISercurityCenter.aidl
package com.study.ipcdemo.binderpool;

interface ISercurityCenter {
    String encrypt(String content);
    String decrypt(String password);
}

2.实现上面的aidl方法,分别创建BinderPool.java、Computelmpl.java、SecurityCenterImpl.java

package com.study.ipcdemo.binderpool;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;

import java.util.concurrent.CountDownLatch;

/**
 * Created by ygdx_lk on 17/12/12.
 */

public class BinderPool extends IBinderPool.Stub{
    public static final int BINDER_COMPUTE = 0;
    public static final int BINDER_SECURITY_CENTER = 1;
    private final Context mContext;

    private static volatile BinderPool instace;
    private CountDownLatch countDownLatch;
    private IBinderPool iBinderPool;

    private BinderPool(Context context){
        mContext = context.getApplicationContext();
        connectBinderPoolService();
    }

    public static BinderPool getInstace(Context context){
        if(instace == null){
            synchronized (BinderPool.class){
                if(instace == null){
                    instace = new BinderPool(context);
                }
            }
        }
        return instace;
    }


    private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定服务器成功,获取服务器返回的IBinderPool
            iBinderPool = IBinderPool.Stub.asInterface(service);
            try {
                //添加重连机制
                iBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            countDownLatch.countDown();
        }


        @Override
        public void onServiceDisconnected(ComponentName name) {}
    };

    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient(){

        @Override
        public void binderDied() {
            //绑定失败后,重新连接
            iBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
            iBinderPool = null;
            connectBinderPoolService();
        }
    };

    //绑定Service
    private void connectBinderPoolService() {
        countDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //解除service绑定
    public void quit(){
        mContext.unbindService(mBinderPoolConnection);
    }

    @Override
    public IBinder queryBinder(int binderCode) throws RemoteException {
        IBinder binder = null;
        if(iBinderPool != null){
            binder = iBinderPool.queryBinder(binderCode);
        }
        return binder;
    }



    //服务器返回的Binder
    public static class BinderPoolImpl extends IBinderPool.Stub{

        public BinderPoolImpl(){}

        //根据不同code返回相应的binder
        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {
            Binder binder = null;
            switch (binderCode){
                case BINDER_COMPUTE:
                    binder = new ComputeImpl();
                    break;
                case BINDER_SECURITY_CENTER:
                    binder = new SecurityCenterImpl();
                    break;
                default:
                    break;
            }
            return binder;
        }
    }

}
package com.study.ipcdemo.binderpool;

import android.os.RemoteException;

/**
 * Created by ygdx_lk on 17/12/12.
 */

public class ComputeImpl extends ICompute.Stub {
    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }
}
package com.study.ipcdemo.binderpool;


import android.net.Uri;
import android.os.RemoteException;

/**
 * Created by ygdx_lk on 17/12/12.
 */

public class SecurityCenterImpl extends ISercurityCenter.Stub {

    @Override
    public String encrypt(String content) throws RemoteException {
        return Uri.encode(content);
    }

    @Override
    public String decrypt(String password) throws RemoteException {
        return Uri.decode(password);
    }
}

3.创建服务器BinderPoolService

package com.study.ipcdemo.binderpool;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class BinderPoolService extends Service {
    private static final String TAG = "BinderPoolService";

    public BinderPoolService() {}

    @Override
    public void onCreate() {
        super.onCreate();
    }


    @Override
    public IBinder onBind(Intent intent) {
        return new BinderPool.BinderPoolImpl();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

4.Main5Activity.java

package com.study.ipcdemo;

import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.study.ipcdemo.binderpool.BinderPool;
import com.study.ipcdemo.binderpool.ComputeImpl;
import com.study.ipcdemo.binderpool.ICompute;
import com.study.ipcdemo.binderpool.ISercurityCenter;
import com.study.ipcdemo.binderpool.SecurityCenterImpl;

public class Main5Activity extends AppCompatActivity {

    private static final String TAG = "Main5Activity";
    private BinderPool binderPool;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        new Thread(new Runnable() {
            @Override
            public void run() {
                doWork();
            }
        }).start();
    }

    private void doWork(){
        binderPool = BinderPool.getInstace(this);
        try {
            //读取类型为BINDER_SECURITY_CENTER的binder
            IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
            ISercurityCenter mSercurityCenter = SecurityCenterImpl.asInterface(securityBinder);

            String msg = "hello-安卓=666";

            Log.i(TAG, "doWork: " + msg);
            String psw = mSercurityCenter.encrypt(msg);
            Log.i(TAG, "encrypt: " + psw);
            msg = mSercurityCenter.decrypt(psw);
            Log.i(TAG, "decrypt: " + msg);

        } catch (RemoteException e) {
            e.printStackTrace();
        }


        try {
            //读取类型为BINDER_COMPUTE的binder
            ICompute compute = ComputeImpl.asInterface(binderPool.queryBinder(BinderPool.BINDER_COMPUTE));
            int result = compute.add(1, 3);
            Log.i(TAG, "result: " + result);
        } catch (RemoteException e) {
            e.printStackTrace();
        }


    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(binderPool != null){
            binderPool.quit();
        }
    }
}

执行结果:

12-12 16:58:27.778 20328-20342/com.study.ipcdemo I/Main5Activity: doWork: hello-安卓=666
12-12 16:58:27.778 20328-20342/com.study.ipcdemo I/Main5Activity: encrypt: hello-%E5%AE%89%E5%8D%93%3D666
12-12 16:58:27.778 20328-20342/com.study.ipcdemo I/Main5Activity: decrypt: hello-安卓=666
12-12 16:58:27.788 20328-20342/com.study.ipcdemo I/Main5Activity: result: 4

源码下载

猜你喜欢

转载自blog.csdn.net/likuan0214/article/details/78781393