Android中通过USB接口与和PC进行通讯的demo程序
以往开发过多款安卓嵌入式设备,这些设备与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程序相关推荐
- Android中的USB中的UsbAccessory和UsbDevice的区别
Android中的USB中的UsbAccessory和UsbDevice的区别 [背景] 之前折腾android中的USB相关的东西. 遇到两个东西: UsbAccessory和UsbDevice 但 ...
- 安卓设备通过USB接口实现与pc端的简单数据通信
安卓设备通过USB接口实现与pc端的简单数据通信 最近突发奇想,想实现手机和电脑的交互,但考虑到网络限制,想要基于USB数据线实现与pc的通信,查阅很多资料,最终初步实现.以下某些思路来源于网络,大部 ...
- Android中的Parcelable接口和Serializable用法和区别
Parcelable接口: Interface for classes whose instances can be written to and restored from a Parcel. Cl ...
- 多态在android中(利用接口调用服务中方法)的应用
首先我们已经了解了java中多态的基本概念 1方法重载. 2向上转型,向下转型 今天我们主要讲向上转型在android中的应用范例. 在java中向上向下转型的图解: 重点:子类对象向上转型为父类对象 ...
- usb计算机连接无法连接电脑,电脑中的USB接口无法使用怎么办?USB设备连接电脑没有反应如何解决...
我们知道很多设备需要通过USB接口来与电脑连接.如果出现了USB接口无法使用的情况,我们应该如何解决呢?对于这样的问题,可能有各种不同的情况,如禁用USB接口.USB驱动等原因都有可能会导致USB ...
- Android中谷歌翻译接口使用(使用谷歌翻译接口,App做文本翻译)
原文章:https://blog.csdn.net/pifutan/article/details/78554691.结合原文按照自己需求,实现功能.效果如下: 功能实现: 使用Android自带Sp ...
- Android方法的概括,android中的Filter接口简介
一.结构 public abstract class Filter extends Object java.lang.Object android.widget.Filter 二.概述 过滤器通过过滤 ...
- android中的Filter接口简介
一.结构 public abstract classFilterextendsObject java.lang.Object android.widget.Filter 二.概述 过滤器通过过滤模式来 ...
- android usb软件自动安装监控,Android中监控USB的插拔
一.需求 在Android应该开发过程中,用到了USB通讯,需要应用监控USB设备的插入和拔出,从而刷新USB设备列表. 二.实现 在使用时,需要register和unregister. public ...
最新文章
- python 字符串内容
- ATEN—第十章OSPF的高级配置(4)
- 0x16.基本数据结构 — Trie树(字典树)+ A C 自 动 机
- pip 安装指定版本
- ElasticSearch之Java Api 测试
- 10.27 afternoon similated match
- char str[] 和 char *str 的区别
- 服务器选购seo优化规则,网站seo优化注意事项1—域名和服务器选择
- 计算机网络技术教材多少钱,计算机网络技术课程标准教材.doc
- 《算法导论》第二章 入门
- Linux下如何用GDB调试c++程序 [版本2]
- HTTP请求与响应协议
- Google广告数据分析与优化总结
- 4.2 分类效果的评价
- pl/sql Developer 1303注册码
- 【数论】扩展欧几里得算法(EXTENDED-EUCLID)
- 笔记本电脑散热风扇声音比较大解决方法
- 【tph-yolov5】tph-Yolov5的Pytorch环境配置和运行错误记录
- Python调用WPS进行文档转换PDF及PDF转图片
- paperpaper论文查重入口?