一、Android中的IPC方式
- 使用Bundle
- 使用文件共享
- 使用Messenger
- 使用AIDL
- 使用ContentProvider
- 使用Socket
1.使用Bundle
Bundle实现了Parcelable接口,当我们在一个进程中启动了另一个进程的Activity、Service和BroadcastReceiver,可以在Bundle中附加我们需要传输的信息,通过Intent发送出去。、
传输的数据必须能被序列化,可以是 基本类型,实现了 Parcelable或Serializable接口的对象,或一些Android支持的特殊对象。、
2.使用文件共享
Android基于Linux,支持并发读/写文件,两个进程可以通过 读/写同一个文件来交换数据
MainActivity的onResume中序列化一个User对象到sd卡,SecondActivity的onResume中反序列化,恢复User对象。
Manifest中,MainActivity跑在包名进程中,SecondActivity跑在remote进程中
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:label="@string/app_name"
android:process=":remote">
User.java
public class User implements Serializable {
private static final long serialVersionUID = 287483306032875107L;
public int userId;
public String userName;
public boolean isMale;
public User(int userId, String userName, boolean isMale){
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", isMale=" + isMale +
'}';
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnOpenSecondActivity = (Button) findViewById(R.id.btn_open_second_activity);
btnOpenSecondActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onResume() {
super.onResume();
persistToFile();
}
public static final String FILE_NAME ="user.txt";
private void persistToFile(){
new Thread(new Runnable() {
@Override
public void run() {
User user = new User(1, "helloWorld", false);
File dir = new File(Environment.getExternalStorageDirectory(),FILE_NAME);
if(!dir.exists()){
try {
dir.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
ObjectOutputStream objectOutputStream = null;
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream(dir));
objectOutputStream.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null != objectOutputStream){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
SecondActivity.java
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
@Override
protected void onResume() {
super.onResume();
recoverFromFile();
}
private void recoverFromFile(){
new Thread(new Runnable() {
@Override
public void run() {
User user = null;
File dir = new File(Environment.getExternalStorageDirectory() + "/" + MainActivity.FILE_NAME);
if(dir.exists()){
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(new FileInputStream(dir));
user = (User) objectInputStream.readObject();
Log.d("SecondActivity", "### user = " + user);//### user = User{userId=1, userName='helloWorld', isMale=false}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(null != objectInputStream){
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}).start();
}
}
序列化和反序列化 对象的内容是一样的,本质是2个对象
上边的例子,如果并发读/写,读出的内容可能不是最新的,并发写就更严重了,要尽量避免并发写或者使用线程同步来限制多个线程的写操作。
- 多进程通信不要使用SharedPreferences
SharedPreferences通过键值对的方式来存储数据,目录位于/data/data/包名/shared_prefs下,系统对SharedPreferences的读/写有一定的缓存策略,内存中会有一份SharedPreferences文件的缓存,多进程模式下,系统对它的读/写就会变得不可靠,当高并发读/写访问,就有很大几率会丢失数据。
3.使用Messenger
Messenger是一种轻量级的IPC方案,底层实现是AIDL,可以在不同进程中传递Message对象。
Messenger对AIDL做了封装,使进程间通信更简便;Messenger一次处理一个请求,服务端不存在并发执行的情形。
Messenger的使用步骤
- 在服务端创建一个Service 用于处理客户端请求,创建一个Handler 通过这个Handler创建一个Messenger对象;在onBind方法中返回Messenger的Binder
- 客户端进程中,首先绑定服务端的Service,onServiceConnected中用 服务端返回的IBinder创建一个Messenger,Message可以通过这个Messenger向服务端发送消息。
如果服务端要回应客户端,客户端要创建一个Handler和一个新多Messenger,Message的replyTo参数将这个Messenger传递给服务端,服务端通过replyTo参数回应客户端。
<service
android:name=".messenger.MessengerService">
<intent-filter>
<action android:name="com.jieqiong.MessengerService.launch" />
</intent-filter>
</service>
<activity android:name=".messenger.MessengerActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
服务端代码:MessengerService.java
public class MessengerService extends Service {
private static final String TAG = "MessengerService";
public static final int MSG_FROM_CLIENT = 1;
public static final int MSG_FROM_SERVICE = 2;
//MessengerHandler 用来处理客户端发送的消息
private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_FROM_CLIENT:
//收到客户端的消息
Log.i(TAG, "### handleMessage:: receive msg from Client: " + msg.getData().getString("msg"));
//给客户端发消息
Messenger client = msg.replyTo;
Message replyMessage = Message.obtain(null, MSG_FROM_SERVICE);
Bundle bundle = new Bundle();
bundle.putString("reply", "你的消息已经收到");
replyMessage.setData(bundle);
try {
client.send(replyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
break;
}
}
}
//Messenger与Handler关联,Messenger的作用是将客户端发送的消息传递给MessengerHandler处理
private final Messenger mMessenger = new Messenger(new MessengerHandler());
@Override
public IBinder onBind(Intent intent) {
//onBind中返回Messenger的Binder对象
return mMessenger.getBinder();
}
}
客户端代码:MessengerActivity.java
public class MessengerActivity extends Activity {
private static final String TAG = "MessengerActivity";
private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MessengerService.MSG_FROM_SERVICE:
//处理服务端返回的消息
Log.i(TAG, "### handleMessage:: receive msg from Service, " + msg.getData().getString("reply"));
break;
default:
super.handleMessage(msg);
break;
}
}
}
private Messenger mMessenger;
private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler());
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定成功后,根据服务端返回的 Binder 对象创建 Messenger
Log.d(TAG, "### onServiceConnected::");
mMessenger = new Messenger(service);
Message msg = Message.obtain(null, MessengerService.MSG_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg", "Hello,this is client");
msg.setData(bundle);
msg.replyTo = mGetReplyMessenger;//将Messenger通过replyTo 传递给服务端
try {
//Messenger向服务端发消息
mMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messenger);
//绑定service
Intent intent = new Intent(this, MessengerService.class);
intent.setAction("com.jieqiong.MessengerService.launch");
bindService(intent, mConnection, BIND_AUTO_CREATE);
}
}
12-22 16:29:15.110 15143-15143/? D/MessengerActivity: ### onServiceConnected::
12-22 16:29:15.152 15143-15143/? I/MessengerService: ### handleMessage:: receive msg from Client: Hello,this is client
12-22 16:29:15.152 15143-15143/? I/MessengerActivity: ### handleMessage:: receive msg from Service, 你的消息已经收到
Messenger 和 Message都实现了 Parcelable 接口,通过Messenger来传输Message,Message中能使用的载体只有what、arg1、arg2、Bundle 以及 replyTo。Message的object字段,只有当对象实现了Parcelable 接口才能用object。