本文基于《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