换到了一家新公司,于是就有了新的项目。这次的项目 要用Android SDK与USB HID设备进行通信。第一次接触Android SDK,以及USB,记录下源程序、开发过程以及一些心得。

首先,要感谢网上“先行者”们的无私帮助,使得开始的工作进展比较顺利。这里提及两个非常好的网址,我的源码借鉴了这两个网址很多:

http://blog.csdn.net/tianruxishui/article/details/38338087

http://www.android-doc.com/guide/topics/connectivity/usb/host.html

以下是程序源码(目前只开发到探测部分,具体通信部分有待完善):

USB_Access.java:

  1. package com.example.vrgate_usb;
  2. import android.os.Bundle;
  3. import android.app.Service;
  4. import android.app.Activity;
  5. import android.content.Intent;
  6. import android.hardware.usb.*;
  7. import java.util.HashMap;
  8. import java.util.Hashtable;
  9. import java.util.Iterator;
  10. import android.widget.Toast;
  11. import android.content.Context;
  12. import android.widget.TextView;
  13. import android.content.BroadcastReceiver;
  14. import android.content.Intent;
  15. import android.content.IntentFilter;
  16. import android.app.PendingIntent;
  17. import android.os.Handler;
  18. public class USBAccess extends Activity {
  19. TextView View1 = null;
  20. TextView View2 = null;
  21. TextView View3 = null;
  22. TextView View4 = null;
  23. TextView View5 = null;
  24. TextView View6 = null;
  25. TextView View7 = null;
  26. TextView View8 = null;
  27. TextView View9 = null;
  28. TextView View10 = null;
  29. TextView View11 = null;
  30. UsbManager myUsbManager;
  31. UsbDevice myUsbDevice;
  32. UsbInterface Interface[];
  33. UsbDeviceConnection myDeviceConnection;
  34. UsbEndpoint epBulkOut, epBulkIn;
  35. UsbEndpoint epControl;
  36. UsbEndpoint epIntOut, epIntIn;
  37. int VendorID;
  38. int ProductID;
  39. //private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
  40. private static int TIMEOUT = 300;
  41. int ret = -1;
  42. byte[] recvBuffer = new byte[256];
  43. usb_hid usbHid;
  44. protected void onCreate(Bundle savedInstanceState) {
  45. super.onCreate(savedInstanceState);
  46. setContentView(R.layout.usb_access);
  47. /*
  48. //usbHid = new usb_hid(this);
  49. usbHid = usb_hid.getInstance(this);
  50. if (usbHid.getUsbDevice() == 0)
  51. {
  52. this.setTitle("已连接0设备");
  53. }
  54. else if(usbHid.getUsbDevice() == -1)
  55. {
  56. this.setTitle("已连接-1设备");
  57. }
  58. else if(usbHid.getUsbDevice() == -2)
  59. {
  60. this.setTitle("已连接-2设备");
  61. }
  62. else if(usbHid.getUsbDevice() == -3)
  63. {
  64. this.setTitle("已连接-3设备");
  65. }
  66. else
  67. {
  68. this.setTitle("已连接-9设备");
  69. }*/
  70.  
  71. View1 = (TextView) findViewById(R.id.Vendor_ID);
  72. View2 = (TextView) findViewById(R.id.Product_ID);
  73. View3 = (TextView) findViewById(R.id.Count);
  74. View4 = (TextView) findViewById(R.id.Interface_ID);
  75. View5 = (TextView) findViewById(R.id.Control_Endpoint);
  76. View6 = (TextView) findViewById(R.id.BulkIn_Endpoint);
  77. View7 = (TextView) findViewById(R.id.BulkOut_Endpoint);
  78. View8 = (TextView) findViewById(R.id.InterruptIn_Endpoint);
  79. View9 = (TextView) findViewById(R.id.InterruptOut_Endpoint);
  80. View10 = (TextView) findViewById(R.id.Serial_Number);
  81. View11 = (TextView) findViewById(R.id.Recv_Data);
  82.  
  83. // 获取UsbManager
  84. myUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
  85. // 枚举设备
  86. enumerateDevice(myUsbManager);
  87. // 查找设备接口
  88. ret = getDeviceInterface();
  89. // 获取设备endpoint
  90. if(ret == 0)
  91. assignEndpoint(Interface[0]);
  92. // 打开conn连接通道
  93. if(ret == 0)
  94. {
  95. ret = openDevice(Interface[0]);
  96. }
  97. // 开始USB数据收发
  98. if(ret == 0)
  99. {
  100. UsbReadThread thread = new UsbReadThread();
  101. thread.start();
  102.  
  103. final Handler handler= new Handler();
  104. final Runnable runnable = new Runnable() {
  105. public void run() {
  106. View11.setText("data 0:" + recvBuffer[0] + '\n'
  107. + "data 1:" + recvBuffer[1] + '\n'
  108. + "data 2:" + recvBuffer[2] + '\n'
  109. + "data 3:" + recvBuffer[3] + '\n');
  110. }
  111. };
  112.  
  113. final Thread t = new Thread() {
  114. @Override
  115. public void run() {
  116. while(true)
  117. {
  118. handler.post(runnable); //加入到消息队列  这样没有启动新的线程,虽然没有报异常。但仍然阻塞ProgressDialog的显示
  119. try
  120. {
  121. sleep(10); //直接调用
  122. }
  123. catch (InterruptedException e)
  124. {
  125. return;
  126. }
  127. }
  128. }
  129. };
  130. t.start();
  131. }
  132. }
  133.  
  134. public class UsbReadThread extends Thread {
  135. @Override
  136. public void run()
  137. {
  138. byte[] data = new byte[256];
  139. while(true)
  140. {
  141. receiveMessageFromEndpoint();
  142. //sendMessageToEndpoint(data);
  143. }
  144. }
  145. }
  146.  
  147. @Override
  148. public void onResume() {
  149. super.onResume();
  150. }
  151.  
  152. // 枚举设备函数
  153. private void enumerateDevice(UsbManager mUsbManager)
  154. {
  155. System.out.println("开始进行枚举设备!\n");
  156. if (mUsbManager == null)
  157. {
  158. System.out.println("创建UsbManager失败,请重新启动应用!");
  159. Context context = getApplicationContext();
  160. Toast.makeText(context, "创建UsbManager失败,请重新启动应用!", Toast.LENGTH_SHORT).show();
  161. return;
  162. }
  163. else
  164. {
  165. HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
  166. if (!(deviceList.isEmpty()))
  167. {
  168. // deviceList不为空
  169. System.out.println("已连接USB设备至PAD!\n");
  170. System.out.println("deviceList is not null!");
  171. Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
  172. while (deviceIterator.hasNext())
  173. {
  174. UsbDevice device = deviceIterator.next();
  175. // 输出设备信息
  176. //Log.i(TAG, "DeviceInfo: " + device.getVendorId() + " , " + device.getProductId());
  177. System.out.println("DeviceInfo:" + device.getVendorId() + " , " + device.getProductId());
  178. // 保存设备VID和PID
  179. VendorID = device.getVendorId();
  180. ProductID = device.getProductId();
  181. View1.setText("制造商 ID:" + VendorID); //东芝U盘:2352; VrGate Hid: 1155
  182. View2.setText("产品ID:" + ProductID); //东芝U盘:25924; VrGate Hid: 22352
  183. // 保存匹配到的设备
  184. if (VendorID == 1155 && ProductID == 22352) {
  185. //if (VendorID == 2352 && ProductID == 25924) {
  186. myUsbDevice = device; // 获取USBDevice
  187. System.out.println("发现待匹配设备:" + device.getVendorId() + "," + device.getProductId());
  188. Context context = getApplicationContext();
  189. Toast.makeText(context, "发现待匹配设备。", Toast.LENGTH_SHORT).show();
  190. }
  191. }
  192. }
  193. else
  194. {
  195. System.out.println("请连接USB设备至PAD!");
  196. Context context = getApplicationContext();
  197. Toast.makeText(context, "请连接USB设备至PAD!", Toast.LENGTH_SHORT).show();
  198. }
  199. }
  200. }
  201.  
  202. // 寻找设备接口
  203. private int getDeviceInterface()
  204. {
  205. if (myUsbDevice != null)
  206. {
  207. int count = -1;
  208.  
  209. //Log.d(TAG, "interfaceCounts : " + myUsbDevice.getInterfaceCount());
  210. count = myUsbDevice.getInterfaceCount();
  211. System.out.println("设备接口数:" + count);
  212. View3.setText("设备接口数:" + count);
  213. if (count <= 0)
  214. return -2;
  215. Interface = new UsbInterface[count];
  216. for (int i = 0; i < myUsbDevice.getInterfaceCount(); i++)
  217. {
  218. //UsbInterface intf = myUsbDevice.getInterface(i);
  219. Interface[i] = myUsbDevice.getInterface(i); // 保存设备接口
  220. System.out.println("成功获得设备接口:" + Interface[i].getId());
  221. View4.setText("接口号:" + Interface[i].getId());
  222. View1.setText("制造商 ID:" + VendorID + ";" + myUsbDevice.getInterfaceCount() + ";" + Interface[i].getInterfaceClass() + ";" + Interface[i].getInterfaceSubclass() + ";" + Interface[i].getInterfaceProtocol());
  223. }
  224.  
  225. return 0;
  226. }
  227. else
  228. {
  229. System.out.println("设备为空!");
  230. return -1;
  231. }
  232. }
  233. // 分配端点,IN | OUT,即输入输出;可以通过判断
  234. private void assignEndpoint(UsbInterface mInterface)
  235. {
  236. if ((myUsbDevice != null) && (mInterface != null))
  237. {
  238. for (int i = 0; i < mInterface.getEndpointCount(); i++)
  239. {
  240. UsbEndpoint ep = mInterface.getEndpoint(i);
  241. int type = ep.getType();
  242. int direction = ep.getDirection();
  243. // look for bulk endpoint
  244. if (type == UsbConstants.USB_ENDPOINT_XFER_BULK)
  245. {
  246. if (direction == UsbConstants.USB_DIR_OUT)
  247. {
  248. epBulkOut = ep;
  249. System.out.println("Find the BulkEndpointOut," + "index:" + i + "," + "使用端点号:" + epBulkOut.getEndpointNumber());
  250. View7.setText("Find the BulkEndpointOut," + "index:" + i + "," + "使用端点号:" + epBulkOut.getEndpointNumber());
  251. }
  252. else
  253. {
  254. epBulkIn = ep;
  255. System.out.println("Find the BulkEndpointIn:" + "index:" + i + "," + "使用端点号:" + epBulkIn.getEndpointNumber());
  256. View6.setText("Find the BulkEndpointIn:" + "index:" + i + "," + "使用端点号:" + epBulkIn.getEndpointNumber());
  257. }
  258. }
  259. // look for control endpoint
  260. else if (type == UsbConstants.USB_ENDPOINT_XFER_CONTROL)
  261. {
  262. epControl = ep;
  263. System.out.println("find the ControlEndPoint:" + "index:" + i + "," + "使用端点号:" + epControl.getEndpointNumber());
  264. View5.setText("find the ControlEndPoint:" + "index:" + i + "," + "使用端点号:" + epControl.getEndpointNumber());
  265. }
  266. // look for interrupt endpoint
  267. else if (type == UsbConstants.USB_ENDPOINT_XFER_INT)
  268. {
  269. if (direction == UsbConstants.USB_DIR_OUT)
  270. {
  271. epIntOut = ep;
  272. System.out.println("find the InterruptEndpointOut:" + "index:" + i + "," + "使用端点号:" + epIntOut.getEndpointNumber());
  273. View9.setText("find the InterruptEndpointOut:" + "index:" + i + "," + "使用端点号:" + epIntOut.getEndpointNumber());
  274. }
  275. else
  276. {
  277. epIntIn = ep;
  278. System.out.println("find the InterruptEndpointIn:" + "index:" + i + "," + "使用端点号:" + epIntIn.getEndpointNumber());
  279. View8.setText("find the InterruptEndpointIn:" + "index:" + i + "," + "使用端点号:" + epIntIn.getEndpointNumber());
  280. }
  281. }
  282. }
  283. if (epBulkOut == null && epBulkIn == null && epControl == null && epIntOut == null && epIntIn == null)
  284. {
  285. throw new IllegalArgumentException("not endpoint is founded!");
  286. }
  287. }
  288. }
  289.  
  290. // 打开设备
  291. public int openDevice(UsbInterface mInterface)
  292. {
  293. if (mInterface != null)
  294. {
  295. UsbDeviceConnection conn = null;
  296.  
  297. Context context = getApplicationContext();
  298. // 在open前判断是否有连接权限;对于连接权限可以静态分配,也可以动态分配权限
  299. if (myUsbManager.hasPermission(myUsbDevice))
  300. {
  301.  
  302. conn = myUsbManager.openDevice(myUsbDevice); //此处与device_filter.xml中的值密切相关!
  303. if (conn == null)
  304. {
  305. Toast.makeText(context, "打开设备失败,未找到该设备!", Toast.LENGTH_SHORT).show();
  306. return -2;
  307. }
  308. }
  309. else
  310. {
  311. Toast.makeText(context, "打开设备失败,无连接权限!", Toast.LENGTH_SHORT).show();
  312. return -3;
  313. }
  314.  
  315. if (conn.claimInterface(mInterface, true))
  316. {
  317. myDeviceConnection = conn;
  318. //if (myDeviceConnection != null)// 到此你的android设备已经连上zigbee设备
  319. {
  320. System.out.println("open设备成功!");
  321. Toast.makeText(context, "打开设备成功!", Toast.LENGTH_SHORT).show();
  322. }
  323. final String mySerial = myDeviceConnection.getSerial();
  324. System.out.println("设备serial number:" + mySerial);
  325. View10.setText("设备序列号:" + mySerial);
  326. //View10.setText("端点数:" + mInterface.getEndpointCount());
  327. return 0;
  328. }
  329. else
  330. {
  331. System.out.println("无法打开连接通道。");
  332. Toast.makeText(context, "无法打开连接通道。", Toast.LENGTH_SHORT).show();
  333. conn.close();
  334. return -4;
  335. }
  336. }
  337.  
  338. return -1;
  339. }
  340. // 发送数据
  341. private void sendMessageToEndpoint(byte[] buffer)
  342. {
  343. //if (buffer == null)
  344. // return;
  345. if(epIntOut != null)
  346. {
  347. // interruptOut传输
  348. if (myDeviceConnection.bulkTransfer(epIntOut, buffer, buffer.length, 0) < 0)
  349. {
  350. System.out.println("interruptOut返回输出为 负数!\n");
  351. recvBuffer[1] = -1;
  352. recvBuffer[2] = -5;
  353. return;
  354. }
  355. recvBuffer[1] = 4;
  356. recvBuffer[2] = 6;
  357. //System.out.println("Send Message Succeed.");
  358. }
  359. else if(epBulkOut != null)
  360. {
  361. // bulkOut传输
  362. if (myDeviceConnection.bulkTransfer(epBulkOut, buffer, buffer.length, 0) < 0)
  363. {
  364. recvBuffer[1] = -7;
  365. recvBuffer[2] = -5;
  366. System.out.println("bulkOut返回输出为 负数!\n");
  367. return;
  368. }
  369. recvBuffer[1] = 6;
  370. recvBuffer[2] = 4;
  371. //System.out.println("Send Message Succeed.");
  372. }
  373.  
  374. }
  375.  
  376. // 从设备接收数据bulkIn
  377. private byte[] receiveMessageFromEndpoint()
  378. {
  379. if(epIntIn != null)
  380. {
  381. if (myDeviceConnection.bulkTransfer(epIntIn, recvBuffer, 64, 0) < 0)
  382. {
  383. System.out.println("interruptIn返回输出为负数!\n");
  384. recvBuffer[0] = -3;
  385. recvBuffer[3] = -9;
  386. return null;
  387. }
  388. //System.out.println("Receive Message Succeed!" + "数据返回" + myDeviceConnection.bulkTransfer(epBulkIn, recvBuffer, recvBuffer.length, 3000));
  389. }
  390. else if(epBulkIn != null)
  391. {
  392. recvBuffer[0] = 3;
  393. recvBuffer[3] = 3;
  394. if (myDeviceConnection.bulkTransfer(epBulkIn, recvBuffer, recvBuffer.length, 0) < 0)
  395. {
  396. recvBuffer[0] = -2;
  397. recvBuffer[3] = -7;
  398. System.out.println("BulkIn返回输出为 负数!\n");
  399. return null;
  400. }
  401. //System.out.println("Receive Message Succeed!" + "数据返回" + myDeviceConnection.bulkTransfer(epBulkIn, recvBuffer, recvBuffer.length, 3000));
  402. }
  403. return recvBuffer;
  404. }
  405. }

Android USB Host 通信程序的更多相关文章

  1. Android USB Host 与 Hid 设备通信bulkTransfer()返回-1问题的原因

    近期一直在做Android USB Host 与USB Hid设备(STM32FXXX)的通信,遇到了很多问题.项目源码以及所遇到的其他问题可以见本博客其他相关文章,这里重点讲一下bulkTransf ...

  2. Android USB Host与HID通讯

    前端时间捣鼓一个HID的硬件, 需要和android通信, 网上搜索了一圈,收获不小. 比较好的文章是:      Android USB Host与HID通讯 Android Service创建US ...

  3. 翻译Android USB HOST API

    翻译Android USB HOST API 源代码地址:http://developer.android.com/guide/topics/connectivity/usb/host.html 译者 ...

  4. Android USB Host与HID通讯 (二)

    不好意思,从上一篇到现在确实比较忙,中间又外出了一段时间,虽然也上LOFTER,或者看到一些朋友QQ上加我,给我发信息询问,有些看到了有些可能没看到,偶尔回复了一两个,也不咋的详细,在此我想说,一方面 ...

  5. Android USB Host与HID通讯 (一)

    去年9月份来到现在的公司,接到新公司的第一个项目就是Android USB Host与HID通讯,当时也什么都不懂,就拿着google的api 开发指南 (http://developer.andro ...

  6. Android USB Host 与 HID 之通讯方法(bulkTransfer()与controlTransfer()方法使用)

    转载地址:差满多乃几 Android USB Host与HID通讯,就目前Google Developer提供的方法有bulkTransfer()与controlTransfer(),看是简简单单的两 ...

  7. Android USB Host 与 HID 之通讯方法

    Android USB Host与HID通讯,就目前Google Developer提供的方法有bulkTransfer()与controlTransfer(),看是简简单单的两个方法,要实现真正的通 ...

  8. 【转】Android Service创建USB HOST通信

    之前做了一个关于Android USB通信的Case,通过Android的USB总线给Zigbee供电,和板载的Zigbee(基于Zigbee的自组网)进行通信.要使用Android的USB Host ...

  9. Android Service创建USB HOST通信

    之前做了一个关于Android USB通信的Case,通过Android的USB总线给Zigbee供电,和板载的Zigbee(基于Zigbee的自组网)进行通信.要使用Android的USB Host ...

随机推荐

  1. ASP 生成带日期的随机数

    <% Function getRnd() '**************************************** '返回值:如getRnd(),即输出2008082415534646 ...

  2. 0708_Java如何设置输入流

    1.Java如何设置输入流:?(以解决看下面实例代码) 2.Java如何设置全局变量:(以解决public static即可) 3.Java为什么在做那种机试题目的时候都要设置成静态的:(以解决,因为 ...

  3. sql的游标使用(转)

    游标是邪恶的! 在关系数据库中,我们对于查询的思考是面向集合的.而游标打破了这一规则,游标使得我们思考方式变为逐行进行.对于类C的开发人员来着,这样的思考方式会更加舒服. 正常面向集合的思维方式是: ...

  4. 备份BinLog并压缩 全备份

    Rem Backup Mysql Binlog Rem Backup Yesterday and RAR Rem Backup every day 00:01 begin backup yesterd ...

  5. Jquery Ajax Get示例

      $.ajax({ type: "GET", url:"ajax_url.php", cache: false, data:{'action':'ABC',' ...

  6. 06_init()和destroy()方法

    [工程截图] [HelloWorld.java] package com.HigginCui; public class HelloWorld { public HelloWorld(){ Syste ...

  7. LevelDb原理剖析

    在说LevelDb之前,先认识两位大牛,Jeff Dean和Sanjay Ghemawat,这两位是Google公司重量级的工程师,为数甚少的Google Fellow之二. Jeff Dean其人: ...

  8. MyBatis入门教程(基于Mybatis3.2)

    MyBatis和Hibernate一样都是基于ORM的关系型数据库框架 ORM工具的基本思想: 1.从配置文件(通常是XML配置文件中)得到 sessionfactory. 2. 由sessionfa ...

  9. IE10访问Apache2.4卡死的问题

    windows环境下,使用IE10访问Apache2.4时,服务器经常卡死 找到EnableSendfile on,在下一行添加如下配置解决: AcceptFilter http none Accep ...

  10. 【HeadFirst设计模式】12.复合模式

    定义: 复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题. 要点: MVC模式是复合模式,结合了观察者模式.策略模式和组合模式. 模型使用了观察者模式,以便观察者更新,同时保存 ...