一.前言
Android长连接应用于服务器需要主动通知客户端的一些场景,例如推送消息和即时通讯。除了接入第三方SDK来实现外,在业务要求不是很高的情况下,完全可以自己编写一套实现方案。
二.正文
Android客户端长连接通信通过TCP协议的套接字(Socket)实现。下面通过对Socket的封装来实现长连接通信:
-
ClientSocket:Socket创建、连接和数据传输;
-
SocketInterface:Socket运行周期回调接口;
-
ClientService:业务逻辑处理。
(1)ClientSocket通过开启一个线程来进行Socket的创建和连接,连接成功后,等待服务器信息,并按照text协议(以“\n”结尾的字符串)来读取输入流。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
public class ClientSocket {
//连接超时时间(ms)
private int TIME_OUT = 3000;
//远程ip地址
private String host;
//远程端口
private int port;
//socket对象
private Socket socket;
//输出流
private BufferedWriter bufferedWriter;
//输入流(text协议)
private BufferedReader bufferedReader;
//回调接口
private SocketInterface socketInterface;
//socket是否正常运行中
private boolean isRunning = false;
/**
* 设置通信地址
*
* @param host 主机ip
* @param port 端口
*/
public void setAddress(String host, int port) {
this.host = host;
this.port = port;
}
/**
* 开启(子线程)
*/
public void start() {
new Thread(this::connect).start();
}
/**
* 开始连接
*/
private void connect() {
//连接
try {
this.socket = new Socket();
this.socket.connect(new InetSocketAddress(this.host, this.port), this.TIME_OUT);
this.socketInterface.onConnect();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(this.socket.getOutputStream());
this.bufferedWriter = new BufferedWriter(outputStreamWriter);
InputStreamReader inputStreamReader = new InputStreamReader(this.socket.getInputStream());
this.bufferedReader = new BufferedReader(inputStreamReader);
this.isRunning = true;
this.socketInterface.onReady();
} catch (Exception e) {
this.isRunning = false;
this.socketInterface.onConnectFailure(e.getLocalizedMessage());
return;
}
//接收数据
try {
while (isRunning) {
String msg = bufferedReader.readLine();
socketInterface.onMessage(msg);
}
} catch (Exception e) {
isRunning = false;
}
//连接关闭
socketInterface.onClose();
}
/**
* 发送信息
*
* @param msg 信息体
*/
synchronized public void send(String msg) {
if (!this.isRunning) {
return;
}
try {
this.bufferedWriter.write(msg + "\n");
this.bufferedWriter.flush();
} catch (IOException e) {
isRunning = false;
}
}
/**
* 关闭Socket连接
*/
public void close() {
if (isRunning) {
try {
socket.close();
isRunning = false;
} catch (IOException ignored) {
}
}
}
/**
* @return 当前Socket运行状态
*/
public boolean isRunning() {
return this.isRunning;
}
/**
* 设置Socket运行周期回调
*/
public void setSocketInterface(SocketInterface socketInterface) {
this.socketInterface = socketInterface;
}
}
(2) SocketInterface 声明了简单接口,可按照实际情况来更改。
public interface SocketInterface {
void onConnect();
void onConnectFailure(String error);
void onReady();
void onMessage(String msg);
void onClose();
}
(3)ClientService 采用单例模式,只进行一个Socket通信,通过设置回调来进行逻辑处理。
public class ClientService {
static ClientSocket clientSocket;
static SocketInterface socketInterface;
static {
clientSocket = new ClientSocket();
initSocketInterface();
}
/**
* 开启通信服务
*
* @param host 主机ip
* @param port 端口
*/
static public void startService(String host, int port) {
if (clientSocket.isRunning()) {
return;
}
clientSocket.setAddress(host, port);
clientSocket.setSocketInterface(socketInterface);
clientSocket.start();
}
/**
* 发送信息
*/
static public void sendMessage(String msg) {
if (clientSocket.isRunning()) {
clientSocket.send(msg);
}
}
/**
* 关闭通信服务
*/
static public void closeService() {
clientSocket.close();
}
/**
* 初始化回调
*/
static private void initSocketInterface() {
socketInterface = new SocketInterface() {
@Override
public void onConnect() {
//成功连接
LogUtil.log("onConnect");
}
@Override
public void onConnectFailure(String error) {
//连接失败,可根据错误类型进行相应处理,如重连
LogUtil.log("onConnectFailure:" + error);
}
@Override
public void onReady() {
//已准备完毕,可进行发送信息,开启心跳线程等
LogUtil.log("onReady");
}
@Override
public void onMessage(String msg) {
//服务器信息到达,进行业务处理
LogUtil.log("onMessage:" + msg);
}
@Override
public void onClose() {
//连接关闭,此处可进行重连或清理操作
LogUtil.log("onClose");
}
};
}
}
在需要开启时候传入服务器ip和端口即可。
//开启服务
ClientService.startService("192.168.1.102", 8080);
这只是Android长连接通信的一个基本实现,实际情况还要考虑通信数据协议和通信保活问题。
三.结语
本文基于自身知识经验编写,只供参考学习,不足之处还请指正,欢迎伙伴们来一起探讨交流!