主题:Linux 应用程序与 Android 应用程序之间如何通信
目录
前言
前提条件:
- 一台 Linux 设备
- 一台 Android 设备
- Linux 设备与 Android 设备之间通过一根 USB 数据线物理连接
在上述条件下,本文记录 Linux 应用和 Android 应用之间如何通信的步骤,仅供参考。
方法
参考:
概括来说,Linux 和 Android 之间通信可分为如下三步(顺序不可更改):
- Linux 端执行 adb forward 建立转发
- Android 端启动 socket server
- Linux 端启动 socket client
接下来详细介绍每一步的工作。
1. Linux 端建立转发
Linux 和 Android 之间的通信是建立在 adb 之上的,所以如果想要在 Linux 和 Android 之间进行通信,首先需要在 Linux 端使用 adb forward 命令建立一个转发。
命令如下:
adb forward tcp:9000 tcp:9001
上述命令的作用是:将 Linux 端的 9000 端口接收到的数据,转发给 Android 端的 9001 端口。
执行此命令后,adb forward 创建了一个监听本地 9000 端口的 server ,然后 adb 将发往此端口的数据,转发到 Android 端的 9001 端口。数据传递是双向的。
借用一张图:
adb forward 相关命令:
# 确认转发是否建立成功:
adb forward -- list
# 查看本地端口状态
netstat -a | grep 9000
# 移除转发
adb forward --remove tcp:9000
2. Android 端启动 server
Android 端启动一个 socket server,监听 client 请求,监听的 socket 为:< 127.0.0.1, 9001 > 。
C++ 工程可借助一个开源的 socket 通信库:HP-Socket
如下是一个基于 HP-Socket 的 Server 代码:
class TcpServerImp : public CTcpServerListener{
// 实现一些事件
}
TcpServerImp s_listener;
pServer = new CTcpPackServer(&s_listener);
pServer->SetMaxPackSize(0x1FFFFF);
pServer->SetPackHeaderFlag(0x169);
pServer->SetKeepAliveTime(60*1000L);
pServer->SetSocketBufferSize(1024*1024);
mStart = pServer->Start("127.0.0.1", 9000) ? true : false;
Log::info("Communication", "TCP连接:%d" , mStart ? 1:0);
3. Linux 端启动 client
Linux 端启动一个 socket client ,连接的 socket 为: < 127.0.0.1, 9000 > 。
如下是一个基于 HP-Socket 的 Client 代码:
/**
* Socket 事件监听器。定义一些事件的处理方法
*/
class ClientListener final : public CTcpClientListener {
// 实现一些事件
}
// 初始化 Socket 监听器
listener = std::make_shared<ClientListener>();
// 初始化 Socket 对象智能指针
clientPtr = std::make_shared<CTcpPackClientPtr>(listener.get());
// 拿到实际的 Socket 对象
auto client = clientPtr->Get();
// 设置 Socket 通信缓冲区大小
const unsigned int socketBufSize = 1 * 1024 * 1024; // 1MB
client->SetSocketBufferSize(socketBufSize);
// 设置正常心跳包间隔。单位:毫秒
const unsigned int keepAliveTime = 60 * 1000;
client->SetKeepAliveTime(keepAliveTime);
// 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000)
client->SetMaxPackSize(0x1FFFFF);
// 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0)
client->SetPackHeaderFlag(0x169);
// 建立 Socket 连接
BOOL ret = client->Start("127.0.0.1", 9000, FALSE);
if (ret == FALSE) {
Log::error(TAG, "Socket 连接失败!Error: %s", SYS_GetLastErrorStr());
return false;
}
//先检查是否已连接
bool isOk = client->IsConnected();
if (isOk) {
Log::info(TAG, "Socket 连接已建立");
return true;
}
问题及解决方法
adv devices 不显示安卓设备
在通过 usb 线将手机和 pc 连接之后,执行 adb devices 如果不显示安卓设备,那么执行如下操作:
# su 用户执行如下命令:
service udev restart
adb kill-server
adb start-server
adb devices
如果还不行,执行如下操作:
- pc 连接安卓设备前:
lixiaoqing@nvidia-desktop:~$ lsusb
Bus 002 Device 002: ID 0bda:0489 Realtek Semiconductor Corp.
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 13d3:3549 IMC Networks
Bus 001 Device 004: ID 046d:c31c Logitech, Inc. Keyboard K120
Bus 001 Device 002: ID 0bda:5489 Realtek Semiconductor Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
- pc 连接安卓设备后:
lixiaoqing@nvidia-desktop:~$ lsusb
Bus 002 Device 002: ID 0bda:0489 Realtek Semiconductor Corp.
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 13d3:3549 IMC Networks
Bus 001 Device 010: ID 12d1:107e Huawei Technologies Co., Ltd.
Bus 001 Device 004: ID 046d:c31c Logitech, Inc. Keyboard K120
Bus 001 Device 002: ID 0bda:5489 Realtek Semiconductor Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
看到差别是:
Bus 001 Device 010: ID 12d1:107e Huawei Technologies Co., Ltd.
然后执行如下命令:
cat ~/.android/adb_usb.ini
输入:
# HUAWEI HONOR 30 PRO
12d1:107e
- 最后执行如下命令:
sudo service udev restart
adb kill-server
adb start-server
adb devices