2019-08-13-Android进程通信方式总结
2019-08-14 本文已影响0人
王元
首先,我们可以想一些通信的方式,
- 第一种方式就是需要有一个消息的发送方(client,指发送消息),消息的接收方(server-接收并处理消息)
- 第二种方式就是发送方和接收方都向同一个消息中心发送消息,消息中心负责将消息转发给对应的接收方
- 第三种方式就是通过访问共享对象,达到通信
大部分通信基于以上俩种方式来实现的,接下来我们看下Android
为我们提供的进程通信方式有哪些
一,广播
通过系统AMS的机制实现多进程通信
二,ContentProvider
通过共享内容的方式
三,共享文件
并发不多或者无并发的情况可以使用
四,Socket
服务端建立severSocket,客户端建立连接,实现相互通信。socket常用于网络通信
五,使用Bundle的方式
-
传输的数据必须基本数据类型或者能够被序列化
- 基本数据类型(int, long, char, boolean, double等)
- String和CharSequence
- List:只支持ArrayList,并且里面的元素都能被AIDL支持
- Map:只支持HashMap,里面的每个元素能被AIDL支持
- Parcelable:所有实现Parcelable接口的对象
-
利用Bundle进行进程间通信
Intent intent = new Intent(MainActivity.this, MyActivity.class); Bundle bundle = new Bundle(); bundle.putString("data", "data"); intent.putExtras(bundle); startActivity(intent);
利用Bundle进行进程间通信是很容易的,大家应该注意到,这种方式进行进程间通信只能是单方向的简单数据传输,它使用时有一定的局限性。
六,Messenger(信息员)
消息是单向的,使用的是handler来实现,因此并发的效率不高,适合消息较少的情况下使用
1,消息的发送方:
public class ClientActivity extends AppCompatActivity {
private Messenger mPutMessage;
private final WeakHandler mClientHandler = new WeakHandler(msg -> {
try {
// msg.replyTo = new Messenger()
if(mPutMessage != null)mPutMessage.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
});
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent i = new Intent(this, MessagerService.class);
bindService(i, conn, Service.BIND_AUTO_CREATE);
Button btn = new Button(this);
setContentView(btn);
btn.setText("send");
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Message pool = Message.obtain();
pool.what = 1;
Bundle bundle = new Bundle();
bundle.putString("key", "test messager");
pool.obj = bundle;
mClientHandler.sendMessage(pool);
}
});
}
private final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mPutMessage = new Messenger(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mPutMessage = null;
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
2,消息的接收方
public class MessagerService extends Service {
private final WeakHandler mServiceHandler = new WeakHandler(msg -> {
switch (msg.what) {
case 1:
Log.e("MessagerService", "服务端收到客户端的消息=" + msg.obj);
Bundle b = (Bundle) msg.obj;
Toast.makeText(getApplicationContext(), "服务端收到客户端的消息=" + b.getString("key"), Toast.LENGTH_LONG).show();
break;
default:
break;
}
});
private Messenger messenger;
@Override
public void onCreate() {
super.onCreate();
messenger = new Messenger(mServiceHandler);
}
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
}
注意:这种方式的消息不仅是单向的,而且发送的所有消息类型必须是实现Parcelable序列化的,否则会 Can't marshal non-Parcelable objects across processes.异常
七,AIDL
Android系统内的大部分进程通信都是基于AIDL来实现的
1,创建进程通信桥梁-AIDl文件
MediaInfo.aidl
package com.aidl.data;
// Declare any non-default types here with import statements
parcelable MediaInfo;
IMeidia.aidl
package com.aidl;
import com.aidl.data.MediaInfo;
// Declare any non-default types here with import statements
interface IMeidia {
MediaInfo getMeidiaInfo();
void playMedia(String url);
void stopMedia();
}
2,声明进程通信访问对象
public class MediaInfo implements Parcelable {
public int mediaId;
public String mediaName;
public String url;
public MediaInfo(int mediaId, String mediaName, String url) {
this.mediaId = mediaId;
this.mediaName = mediaName;
this.url = url;
}
protected MediaInfo(Parcel in) {
mediaId = in.readInt();
mediaName = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mediaId);
dest.writeString(mediaName);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<MediaInfo> CREATOR = new Creator<MediaInfo>() {
@Override
public MediaInfo createFromParcel(Parcel in) {
return new MediaInfo(in);
}
@Override
public MediaInfo[] newArray(int size) {
return new MediaInfo[size];
}
};
@Override
public String toString() {
return "MediaInfo{" +
"mediaId=" + mediaId +
", mediaName='" + mediaName + '\'' +
'}';
}
}
2,建立服务端
/**
* 进程通信服务端
*/
public class MediaService extends Service {
public static final String ACTION = "service.com.aidl.MediaService";
private final com.aidl.IMeidia.Stub mBinder = new com.aidl.IMeidia.Stub() {
@Override
public MediaInfo getMeidiaInfo() throws RemoteException {
return new MediaInfo(10001, MediaService.class.getSimpleName(), "");
}
@Override
public void playMedia(String url) throws RemoteException {
startPlayer(url);
}
@Override
public void stopMedia() throws RemoteException {
stopMPlayer();
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
2,客户端绑定server,获取消息或者发送消息
public class AidlClientActivity extends Activity {
private com.aidl.IMeidia mMedia;
private final ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMedia = com.aidl.IMeidia.Stub.asInterface(service);
try {
//获取消息
mMedia.getMeidiaInfo();
//发送消息
mMedia.playMedia("url");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
try {
mMedia.stopMedia();
mMedia = null;
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent i = new Intent(this, MediaService.class);
bindService(i, mConn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConn);
}
}