以往开发过多款安卓嵌入式设备,这些设备与PC通讯主要通过设备上的以太网网口进行网络通讯,最近一个项目设备没有以太网网口,设备与PC通讯要求使用普通安卓数据线连接设备与PC完成数据通讯。

查阅相关资料以及对adb操作指令的了解,最终实现了项目需求。

方案实现思路:

1.设备端开启一个socket服务,服务端口12345;

2.设备端监听USB插拔事件来启动关闭设备端的socket服务;

3.PC端使用adb命令:adb forward tcp:54321 tcp:12345,将PC端口54321上发来的数据转换到设备socket服务端口;

4.PC端启动socket客户端与PC端口54321进行数据通讯。

因为项目代码保密,故对方案实现特意写了一个demo程序。

Demo实现了:

1.安卓设备端socket服务,服务监听端口12345,收到任何消息,均回复设备的毫秒时间戳。

2.PC 实现使用adb命令将PC端口54321消息转发到设备服务端口12345,之后,连接socket连接,并监听端口54321的消息,每隔3s发送PC毫秒时间戳,并监听设备端服务回应的数据。

以下以代码进行进行介绍。

Android端:

package com.yx.usb2pc;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.util.Log;/*** UsbConnectReceiver* 主要监听ACTION_USB_STATE,启动关闭socket服务** @author yx* @date 2019/10/30 20:39*/
public class UsbConnectReceiver extends BroadcastReceiver {private static final String TAG = "UsbConnectReceiver";@Overridepublic void onReceive(Context context, Intent intent) {if (intent.hasExtra(UsbManager.EXTRA_PERMISSION_GRANTED)) {boolean permissionGranted =intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);Log.v(TAG, "permissionGranted : " + permissionGranted);}String action = intent.getAction();Log.v(TAG, "action:" + action);switch (action) {case UsbManager.ACTION_USB_ACCESSORY_ATTACHED:case UsbManager.ACTION_USB_ACCESSORY_DETACHED:UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);Log.v(TAG, accessory.toString());break;case UsbManager.ACTION_USB_DEVICE_ATTACHED:Log.v(TAG, UsbManager.ACTION_USB_DEVICE_ATTACHED);break;case UsbManager.ACTION_USB_DEVICE_DETACHED:UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);Log.v(TAG, device.toString());break;case UsbManager.ACTION_USB_STATE:boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);boolean functionAdb = intent.getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false);Log.v(TAG, "connected:" + connected + " function_adb : " + functionAdb);// 断开停止服务if (!connected) {SocketServer.getSocketServerInstant().stopServer();} else {// 开启adb调试功能,开启服务if (functionAdb) {SocketServer.getSocketServerInstant().startServer();}}break;default:break;}}
}
UsbConnectReceiver,广播接收器,监听UsbManager.ACTION_USB_STATE状态变化,如果连接断开(connected==false),关闭设备端的socket服务,当然已连接上需要判断adb功能是否使能才能开启服务。
package com.yx.usb2pc;import android.util.Log;import com.yx.usb2pc.utils.ThreadPoolManager;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;/*** SocketServer* 服务端接收socket信息,回复设备端的时间戳信息** @author yx* @date 2019/10/30 20:39*/
public class SocketServer {private static final String TAG = "SocketServer";private static final int PORT = 12345;private ServerSocket mServerSocket = null;private boolean mRunning = false;private static SocketServer sSocketServer;public static SocketServer getSocketServerInstant() {if (sSocketServer == null) {sSocketServer = new SocketServer();}return sSocketServer;}private SocketServer() {}/*** 启动服务*/public void startServer() {stopServer();ThreadPoolManager.getInstance().startTaskThread(new ServerThread(), "server-thread");}/*** 关闭服务*/public void stopServer() {if (mServerSocket != null) {mRunning = false;try {mServerSocket.close();Log.d(TAG, "stopServer server ");} catch (Exception e) {e.printStackTrace();}mServerSocket = null;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}class ServerThread extends Thread {@Overridepublic void run() {mRunning = true;try {mServerSocket = new ServerSocket(PORT);Log.d(TAG, "start server port = " + PORT);while (mRunning) {Socket socket = mServerSocket.accept();Log.d(TAG, "accept ");ThreadPoolManager.getInstance().startTaskThread(new ReceiveThread(socket), "receive-thread");}} catch (Exception e) {e.printStackTrace();} finally {if (mServerSocket != null) {try {mServerSocket.close();} catch (Exception e) {e.printStackTrace();}}}}}class ReceiveThread extends Thread {private Socket socket;public ReceiveThread(Socket socket) {this.socket = socket;Log.d(TAG, " socket:" + socket.toString());}@Overridepublic void run() {try {DataInputStream dis = new DataInputStream(socket.getInputStream());DataOutputStream dos = new DataOutputStream(socket.getOutputStream());while (true) {String data = dis.readUTF();Log.d(TAG, "receive:" + data);// 接收到后回复设备的毫秒时间戳String s = "device:" + System.currentTimeMillis();dos.writeUTF(s);dos.flush();}} catch (Exception e) {e.printStackTrace();} finally {try {socket.close();} catch (Exception e) {e.printStackTrace();}}}}}
SocketServer设备端socket服务,主要提供服务开启关闭方法,服务开启后ServerThread会循环侦听数据消息,每侦听到消息开启一个ReceiveThread线程处理数据,demo中数据接收到后回复设备的毫秒时间戳。

PC端:

package com.yx.soclectclient;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;/*** SocketClient* <p>* PC端每隔3s给监听端口发送PC时间戳信息** @author yx* @date 2019/5/17 13:57*/
public class SocketClient {private Socket mSocket = null;private static final int PORT = 54321;/*** adb 命令绑定端口** @return*/private boolean adbForward() {String cmd = "adb forward tcp:54321 tcp:12345";try {Runtime.getRuntime().exec(cmd);} catch (IOException e) {e.printStackTrace();}Process process = null;try {process = Runtime.getRuntime().exec(cmd);process.waitFor();return true;} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();} finally {if (process != null) {process.destroy();}}return false;}private void test() {try {mSocket = new Socket("127.0.0.1", PORT);System.out.println("socket:" + mSocket.toString());DataInputStream dis = new DataInputStream(mSocket.getInputStream());DataOutputStream dos = new DataOutputStream(mSocket.getOutputStream());while (true) {String data = "sendTime:" + System.currentTimeMillis();dos.writeUTF(data);dos.flush();String s = dis.readUTF();System.out.println("receive:" + s);Thread.sleep(3000);}} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {SocketClient client = new SocketClient();if (client.adbForward()) {client.test();}}
}
SocketClient为PC端测试类,主要完成adb命令完成端口绑定,建立socket客户端连接,连接指向端口54321。连接后,每隔3s向端口发送PC时间戳,并侦听端口数据恢复。

ps:

1.本demo代码,android sdk版本为25;

2.因为测试时连接相对稳定,故未考虑socket长连接心跳问题及断线重连问题,可靠性应用需考虑心跳及断线重连问题。

3.PC端需要按照adb环境,使用时android设备需要打开adb调试模式。

4.USB数据线模拟网线进行socket通讯关键点是利用adb端口绑定命令:adb forward tcp:[pc port] tcp:[device port]。

5.demo源码:https://github.com/TomcatXiong/UsbPcCommunicationDemo

扫描关注更精彩

Android中通过USB接口与和PC进行通讯的demo程序相关推荐

  1. Android中的USB中的UsbAccessory和UsbDevice的区别

    Android中的USB中的UsbAccessory和UsbDevice的区别 [背景] 之前折腾android中的USB相关的东西. 遇到两个东西: UsbAccessory和UsbDevice 但 ...

  2. 安卓设备通过USB接口实现与pc端的简单数据通信

    安卓设备通过USB接口实现与pc端的简单数据通信 最近突发奇想,想实现手机和电脑的交互,但考虑到网络限制,想要基于USB数据线实现与pc的通信,查阅很多资料,最终初步实现.以下某些思路来源于网络,大部 ...

  3. Android中的Parcelable接口和Serializable用法和区别

    Parcelable接口: Interface for classes whose instances can be written to and restored from a Parcel. Cl ...

  4. 多态在android中(利用接口调用服务中方法)的应用

    首先我们已经了解了java中多态的基本概念 1方法重载. 2向上转型,向下转型 今天我们主要讲向上转型在android中的应用范例. 在java中向上向下转型的图解: 重点:子类对象向上转型为父类对象 ...

  5. usb计算机连接无法连接电脑,电脑中的USB接口无法使用怎么办?USB设备连接电脑没有反应如何解决...

    ‍ 我们知道很多设备需要通过USB接口来与电脑连接.如果出现了USB接口无法使用的情况,我们应该如何解决呢?对于这样的问题,可能有各种不同的情况,如禁用USB接口.USB驱动等原因都有可能会导致USB ...

  6. Android中谷歌翻译接口使用(使用谷歌翻译接口,App做文本翻译)

    原文章:https://blog.csdn.net/pifutan/article/details/78554691.结合原文按照自己需求,实现功能.效果如下: 功能实现: 使用Android自带Sp ...

  7. Android方法的概括,android中的Filter接口简介

    一.结构 public abstract class Filter extends Object java.lang.Object android.widget.Filter 二.概述 过滤器通过过滤 ...

  8. android中的Filter接口简介

    一.结构 public abstract classFilterextendsObject java.lang.Object android.widget.Filter 二.概述 过滤器通过过滤模式来 ...

  9. android usb软件自动安装监控,Android中监控USB的插拔

    一.需求 在Android应该开发过程中,用到了USB通讯,需要应用监控USB设备的插入和拔出,从而刷新USB设备列表. 二.实现 在使用时,需要register和unregister. public ...

最新文章

  1. python 字符串内容
  2. ATEN—第十章OSPF的高级配置(4)
  3. 0x16.基本数据结构 — Trie树(字典树)+ A C 自 动 机
  4. pip 安装指定版本
  5. ElasticSearch之Java Api 测试
  6. 10.27 afternoon similated match
  7. char str[] 和 char *str 的区别
  8. 服务器选购seo优化规则,网站seo优化注意事项1—域名和服务器选择
  9. 计算机网络技术教材多少钱,计算机网络技术课程标准教材.doc
  10. 《算法导论》第二章 入门
  11. Linux下如何用GDB调试c++程序 [版本2]
  12. HTTP请求与响应协议
  13. Google广告数据分析与优化总结
  14. 4.2 分类效果的评价
  15. pl/sql Developer 1303注册码
  16. 【数论】扩展欧几里得算法(EXTENDED-EUCLID)
  17. 笔记本电脑散热风扇声音比较大解决方法
  18. 【tph-yolov5】tph-Yolov5的Pytorch环境配置和运行错误记录
  19. Python调用WPS进行文档转换PDF及PDF转图片
  20. paperpaper论文查重入口?

热门文章

  1. streamx编译,streamx-console初始化启动踩坑
  2. 关机或重新启动电脑勾选再次登录时重新打开窗口导致无法上网
  3. 用电脑怎么打开pdf文件阅读
  4. 新华文娱数据发布年度白皮书 口碑成观影首要驱动力
  5. word文档另存为pdf格式,如何设置导航栏
  6. 使用 apifm 插件进行 Flutter 云开发——QQ一键登录/注册
  7. 绕过 iOS 代码签名验证 ldid
  8. 齐了!百度、腾讯、滴滴、抖音的技术大佬都来了
  9. Linux 配置网络案例
  10. 图像修复必读的10篇论文