最近项目中有一个功能需要用到Android与PC端同步数据。查阅了相关资料后,采取了一种建立在adb基础之上的Usb通信方式:由于adb可以将Usb模拟为网卡,所以可以利用socket通信的方式实现Android与PC机的通信,以完成同步功能。

一、Android与PC通信的实现

在《PC客户端与Android服务端的Sockect同步通信》一文详细介绍了建立在adb基础之上的usb(socket)实现的具体方法。大体上的思路如下:

①Android作为server,侦探socket连接请求;添加一个服务类来实现侦听功能。

②PC端作为Client,请求建立socket连接。

③Android端添加一个广播接收类,接受PC端通过Adb发送的广播消息,以启动或者停止①中添加的服务。

④PC端通过Adb发送广播消息通知Android端启动或停止用来侦听socket连接的服务。1、PC端通过Adb发送广播,使Android端开启侦听Socket的服务,然后再请求连接。代码如下:

//连接

public bool DoConnect()

{

string strCmd = 'adb shell am broadcast -a NotifyServiceStop';

Execute(strCmd, wait_ms);

Thread.Sleep(wait_ms);

strCmd = 'adb forward tcp:12580 tcp:10086';

Execute(strCmd, wait_ms);

Thread.Sleep(wait_ms);

strCmd = 'adb shell am broadcast -a NotifyServiceStart';

Execute(strCmd, wait_ms);

Thread.Sleep(wait_ms);

IPAddress ipaddress = IPAddress.Parse('127.0.0.1');

tcpClient.Connect(ipaddress, 12580);

Thread.Sleep(wait_ms);

if (tcpClient != null)

{

NetworkStream networkkStream = tcpClient.GetStream();

networkkStream.ReadTimeout = timeOut;

networkkStream.WriteTimeout = timeOut;

reader = new BinaryReader(networkkStream);

writer = new BinaryWriter(networkkStream);

return true;

}

else

return false;

}其中,Execute()函数用来执行cmd命令,private string Execute(string command, int seconds)

{

string output = ''; //输出字符串

if (command != null && !command.Equals(''))

{

Process process = new Process();//创建进程对象

ProcessStartInfo startInfo = new ProcessStartInfo();

startInfo.FileName = 'cmd.exe';//设定需要执行的命令

startInfo.Arguments = '/C ' + command;//“/C”表示执行完命令后马上退出

startInfo.UseShellExecute = false;//不使用系统外壳程序启动

startInfo.RedirectStandardInput = false;//不重定向输入

startInfo.RedirectStandardOutput = true; //重定向输出

startInfo.CreateNoWindow = true;//不创建窗口

process.StartInfo = startInfo;

try

{

if (process.Start())//开始进程

{

if (seconds == 0)

{

process.WaitForExit();//这里无限等待进程结束

}

else

{

process.WaitForExit(seconds); //等待进程结束,等待时间为指定的毫秒

}

output = process.StandardOutput.ReadToEnd();//读取进程的输出

}

}

finally

{

if (process != null)

process.Close();

}

}

return output;

}

2、在Android端,首先需要添加一个广播接收类来处理广播消息,当接受到广播消息是“启动”消息时启动侦听服务,“关闭“消息时停止服务:

public class ServiceBroadcastReceiver extends BroadcastReceiver{

private static String START_ACTION = 'NotifyServiceStart';

private static String STOP_ACTION = 'NotifyServiceStop';

@Override

public void onReceive(Context context, Intent intent){

Log.d(ConnectService.TAG, Thread.currentThread().getName() + '---->'

+ 'ServiceBroadcastReceiver onReceive');

String action = intent.getAction();

if (START_ACTION.equalsIgnoreCase(action)) {

context.startService(new Intent(context, ConnectService.class));

Log.d(ConnectService.TAG, Thread.currentThread().getName() + '---->'

+ 'ServiceBroadcastReceiver onReceive start end');

} else if (STOP_ACTION.equalsIgnoreCase(action)) {

context.stopService(new Intent(context, ConnectService.class));

Log.d(ConnectService.TAG, Thread.currentThread().getName() + '---->'

+ 'ServiceBroadcastReceiver onReceive stop end');

}

}

}

然后,添加一个服务类,用来侦听客户端的连接请求:public class ConnectService extends Service{

public static final String TAG = 'chl';

public static Boolean mainThreadFlag = true;

public static Boolean ioThreadFlag = true;

ServerSocket serverSocket = null;

final int SERVER_PORT = 10086;

@Override

public IBinder onBind(Intent intent)

{

return null;

}

@Override

public void onCreate()

{

super.onCreate();

Log.d(TAG, 'androidService--->onCreate()');

}

@Override

public int onStartCommand(Intent intent, int flags, int startId)

{

mainThreadFlag = true;

new Thread()

{

public void run()

{

doListen();

};

}.start();

return START_NOT_STICKY;

}

private void doListen()

{

serverSocket = null;

try

{

serverSocket = new ServerSocket(SERVER_PORT);

while (mainThreadFlag)

{

Socket socket = serverSocket.accept();

new Thread(new ThreadReadWriterIOSocket(this, socket)).start();

}

} catch (IOException e)

{

e.printStackTrace();

}

}

@Override

public void onDestroy()

{

super.onDestroy();

mainThreadFlag = false;

ioThreadFlag = false;

try

{

if (serverSocket != null)

serverSocket.close();

} catch (IOException e)

{

e.printStackTrace();

}

}

}还需要添加一个线程类,来处理客户端的连接请求。建立一个连接后,启动一个此线程来完成与客户端的通信。在这里可以定义与实际需求相应的通信协议。

public class ThreadReadWriterIOSocket implements Runnable{

private Socket client;

private Context context;

private PigProtocol pigProtocol;

public ThreadReadWriterIOSocket(Context context, Socket client)

{

this.client = client;

this.context = context;

pigProtocol = new PigProtocol();

}

@Override

public void run(){

BufferedOutputStream out;

BufferedInputStream in;

try {

Header header = null;

out = new BufferedOutputStream(client.getOutputStream());

in = new BufferedInputStream(client.getInputStream());

ConnectService.ioThreadFlag = true;

while (ConnectService.ioThreadFlag){

try {

if(!client.isConnected()){

break;

}

header = pigProtocol.readHeaderFromSocket(in);

switch (header.CmdId) {

case 0x0001:

//

break;

case 0x0002:

//

break;

default:

break;

}

}

catch (Exception e)

{

// TODO: handle exception

e.printStackTrace();

}

}

out.close();

in.close();

}

catch (Exception e)

{

// TODO: handle exception

e.printStackTrace();

}

finally

{

try

{

if (client != null)

{

client.close();

}

} catch (IOException e)

{

e.printStackTrace();

}

}

}

}最后,还需要修改程序清单manifest.xml,加入代码,使程序能够接收到广播消息,并且指定处理消息的类。注意,在指定接收广播消息类、服务类时,一定要指出完整名称,如com.example.connect.ServiceBroadcastReceiver。

android:name='.ConnectService'>

二、Android与PC端传通过socket传递对象

有了上面的工作,就可以实现Android与PC端通过socket(usb)传递简单的字符串了。但是在实际使用过程中,我们更多的往往是传递对象而不是简单的字符串。最简单的方法是定义相应的协议,在发送端将对象拼接为字符串,然后在接收将接收到的字符串端拆分组合为对象。但是这样实现起来不是很方便,《C#(服务器)与Java(客户端)通过Socket传递对象》一文介绍了利用Json来传递对象的方法。利用文中介绍的方法可以很方便的实现对象传递。《DataContractJsonSerializer类操作json类型数据》一文介绍了C#端json类型数据的具体使用方法。

我们知道,C#和Java都是完全面向对象的语言,它们都提供了List泛型,所以我们可以利用List泛型实现一次发送一组对象。

1、在PC端,首先需要完成Json类型与List类型的相互转换。转换得到的Json字符串通过socket发送给Android端,或者读取得到的Json字符串转换为相应的泛型对象,这样就实现了一次发送一组对象的功能。下面是Json字符串与泛型对象相互转换的实现过程,实现了Json类型字符串与C#对象(包括List类型的对象)的相互转换。

public static string Obj2Json(T data)

{

try

{

DataContractJsonSerializer json = new DataContractJsonSerializer(data.GetType());

using (MemoryStream ms = new MemoryStream())

{

json.WriteObject(ms, data);

return Encoding.UTF8.GetString(ms.ToArray());

}

}

catch (System.Exception ex)

{

throw ex;

}

}

public static object Json2Obj(string strJson, Type t)

{

try

{

DataContractJsonSerializer json = new DataContractJsonSerializer(t);

using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(strJson)))

{

return json.ReadObject(ms);

}

}

catch (System.Exception ex)

{

throw ex;

}

}

2、Android端Json与对象的相互转换通过开源项目google-gson实现。下载包后在项目中导入,并且添加引用import com.google.gson.Gson;就可以使用了。

对象转换为Json字符串:try {

String strTmp = gson.toJson(content);

out.write(strTmp.getBytes());

out.flush();

} catch (Exception e) {

// TODO: handle exception

Log.d('error','writeHeaderFromSocket' + e.getMessage());

}

Json字符串转换为对象:

byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];

try

{

int numReadedBytes = in.read(tempbuffer, 0, MAX_BUFFER_BYTES);

String strJson = new String(tempbuffer, 0, numReadedBytes, 'utf-8');

MyType myType = gson.fromJson(strJson, MyType.class);

tempbuffer = null;

} catch (Exception e)

{

e.printStackTrace();

}

Json字符串转换为List:byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];

try

{

int numReadedBytes = in.read(tempbuffer, 0, MAX_BUFFER_BYTES);

String strJson = new String(tempbuffer, 0, numReadedBytes, 'utf-8');

List listMyType = gson.fromJson(strJson,

new TypeToken>(){}.getType());

tempbuffer = null;

} catch (Exception e)

{

e.printStackTrace();

}

安卓通过usb互相通信_Android通过USB与PC通信相关推荐

  1. 多通路fpga 通信_基于USB通信的FPGA高速数据采集系统研究

    摘要:现阶段,在经济高速发展以及科学技术不断进步的大背景下,我国各行各业都得到了快速发展的良机,对数据采集系统的实际需求也越来越多,也对高速数据采集系统的实用性和精度等都提出了更高的要求.基于此,本文 ...

  2. Android通过USB与PC通信

    最近项目中有一个功能需要用到Android与PC端同步数据.查阅了相关资料后,采取了一种建立在adb基础之上的Usb通信方式:由于adb可以将Usb模拟为网卡,所以可以利用socket通信的方式实现A ...

  3. c rs232 mysql,[C#源代码]使用SCPI指令对通信端口(RS232/USB/GPIB/LAN)进行仪器编程

    本文为原创文章.源代码为原创代码,如转载/复制,请在网页/代码处明显位置标明原文名称.作者及网址,谢谢! 本软件是基于NI-VISA/VISA32(Virtual Instrument Softwar ...

  4. Android连上USb不充电,为什么手机usb连不上电脑只显示充电 安卓手机解决方法

    您可能感兴趣的话题: 手机 usb 核心提示:为什么手机usb连不上电脑只显示充电 安卓手机解决方法 经常遇到手机usb链接电脑后没有反应,但是显示手机充电,这种问题该怎么解决呢? 一般情况下,手机通 ...

  5. android连接usb外设通讯_Android设备使用USB的硬件接口

    最近业界的发展显示,智能手机/便携系统与自动化系统或机械系统之间存在巨大的市场潜力.2011年春季谷歌引入的Android开放访问架构,开启了基于Android操作系统的设备的巨大可能--允许智能手机 ...

  6. Linux usb bus日志如何打开,从linux usb bus节点来认识usb linux usb认识

    首先从linux dmesg来认识usb: <6>[   19.610046] msm_hsic_host msm_hsic_host: Qualcomm EHCI Host Contro ...

  7. java usb 无驱打印_Windows Usb 无驱动打印

    \?\USB#VID_8866&PID_0100#0001B0000000#{a5dcbf10-6530-11d2-901f-00c04fb951ed} USB小票打印解决办法 一.需要驱动, ...

  8. Linux USB设备驱动程序设计 和 USB下载线驱动设计

    Linux USB设备驱动程序设计 和 USB下载线驱动设计 USB设备驱动模型 USB设备包括配置(configuration).接口(interface)和端点(endpoint),一个USB设备 ...

  9. usb gen1 gen2_什么是USB Gen 1,Gen 2和Gen 2×2?

    usb gen1 gen2 Talaj/Shutterstock Talaj /快门 Finding the fastest USB connection used to be easy: choos ...

最新文章

  1. 研发管理101军规#003 实战规模化敏捷:从8人到百人的敏捷之路
  2. 微生物预测年龄,皮肤比肠道更准确
  3. 论文笔记 Medical Entity Linking using Triplet Network
  4. 【jquery仿datalist的一个问题,求助】——设置每行显示几列,块状DIV的解决办法...
  5. 【深度学习】sigmoid - 二次代价函数 - 交叉熵 - logistic回归 - softmax
  6. C语言中malloc为字符型指针分配内存引起的缓冲区泄露
  7. wxWidgets:wxSimpleHtmlListBox类用法
  8. CompletableFuture详解~join与get的区别
  9. php div行内块元素,行内元素与块级元素的区别详细介绍
  10. labelme新版本的使用须知
  11. +0.5(加0.5)配合int()实现四舍五入
  12. 献给自己技术成长的第二年
  13. 为了背单词,我花了两天写了一款背单词小程序
  14. visio流程图的叉号_【转】Visio绘制WEB流程图的心得
  15. 模型矩阵、视图矩阵、投影矩阵
  16. 在线教育和线下教育的优劣势
  17. HTML表单、表格制作个人简历
  18. 在测试tensorBroad中在运行mnist_with_summaries.py时URLError:urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答
  19. 基于FPGAd的FIR数字滤波器的设计和实现——刘朋全(西北工业大学)
  20. 潘正磊谈微软研发团队管理之道

热门文章

  1. IOS学习之道:使用UIButton纯手工打造的黑白快小游戏.
  2. 元气骑士科学计算机造出来了在哪,元气骑士超级科学计算器怎么用_超级科学计算器输出方法技巧_3DM手游...
  3. Transformer解读
  4. C# 读取utf-8文本文件
  5. jquery定义ajax函数吗,jQuery AJAX自定义函数和自定义回调?
  6. Android二维码名片生成扫码识别
  7. ps抠图二:背景橡皮擦,通道抠图
  8. 【专业的图像后期处理软件】飞思 Capture One 12.1 for Mac
  9. python 可视化图表 联动_Vue2+Echarts实现多种图表数据可视化Dashboard详解(附源码)...
  10. Python入门程序【十】