Messenger可以在不同进程中传递Message对象,我们在Message中加入我们想要传的数据就可以在进程间的进行数据传递了。Messenger是一种轻量级的IPC方案并对AIDL 进行了封装,它实现起来比较容易,下面我们来看看如何实现。
首先我们先写服务端,在onBind方法中创建Messenger,关联接收消息的Handler调用getBinder来获取Binder对象,在handleMessage方法中接收客户端发来的信息。
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 MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return new Messenger(handler).getBinder();
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
Log.d("TAG", "我是服务端,接收到客户端的信息..."+msg.getData().get("key"));
Messenger messenger = msg.replyTo;
Message message = Message.obtain(null,2);
Bundle bundle = new Bundle();
bundle.putString("haha","你好,客户端,我是服务端");
message.setData(bundle);
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
};
}
接下来创建客户端,绑定另一个进程的servce,绑定成功以后根据服务端返回的Binder对象创建Messenger,并用Messenger向服务端发送信息。
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
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.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private Messenger mMessenger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent("com.example.zhaol.ipcdemo");
intent.setPackage("com.example.zhaol.ipcdemo");
intent.setAction("com.example.zhaol.ipcdemo");
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMessenger = new Messenger(service);
Message message = Message.obtain(null,1);
Bundle bundle = new Bundle();
bundle.putString("key","服务端,你接收到消息了吗");
message.setData(bundle);
message.replyTo = new Messenger(handler);
try {
mMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 2:
Log.d("TAG", "我是客户端,收到你的响应...");
break;
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
}
Socket也称作“套接字“,是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。它分为流式套接字和数据包套接字,分别对应网络传输控制层的TCP和UDP协议。TCP协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。它使用三次握手协议建立连接,并且提供了超时重传机制,具有很高的稳定性。UDP协议则是是一种无连接的协议,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多。
首先我们来实现服务端,当然要使用Socket我们需要在AndroidManifest.xml声明如下的权限:
接下来我们在Service启动时,在线程中建立TCP服务,我们监听的是8688端口,等待客户端连接,当客户端连接时就会生成Socket。通过每次创建的Socket就可以和不同的客户端通信了。当客户端断开连接时,服务端也会关闭Socket并结束结束通话线程。服务端首先会向客户端发送一条消息:“您好,我是服务端”,并接收客户端发来的消息,将收到的消息进行加工再返回给客户端。
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.text.TextUtils;
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;
public class MyService extends Service {
private boolean isServiceDestroyed = false;
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
private class MyThread implements Runnable{
private ServerSocket serverSocket;
@Override
public void run() {
try {
serverSocket = new ServerSocket(8688);
} catch (IOException e) {
e.printStackTrace();
}
while (!isServiceDestroyed){
try {
final Socket client = serverSocket.accept();
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 socket) throws IOException {
// 用于接收客户端消息
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 用于向客户端发送消息
PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
writer.print("你好,我是服务端");
while (!isServiceDestroyed){
//读取客户端信息
String str = bufferedReader.readLine();
Log.d("TAG", "收到客户端信息..."+str);
if(TextUtils.isEmpty(str)){
Log.d("TAG", "客户端断开连接...");
break;
}
String messge = "你好客户端,收到了你的信息"+str;
writer.print(messge);
}
bufferedReader.close();
writer.close();
socket.close();
}
@Override
public void onDestroy() {
isServiceDestroyed = true;
super.onDestroy();
}
@Override
public void onCreate() {
super.onCreate();
new Thread(new MyThread()).start();
}
}
https://blog.csdn.net/qq_38228254/article/details/79599143
客户端Activity会在onCreate方法中启动服务端,并开启线程连接服务端Socket。为了确保能连接成功,采用了超时重连的策略,每次连接失败时都会重新建立连接。连接成功后,客户端会收到服务端发送的消息:“您好,我是服务端”,我们也可以在EditText输入字符并发送到服务端。