Android USB Host 通信程序
换到了一家新公司,于是就有了新的项目。这次的项目 要用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:
package com.example.vrgate_usb; import android.os.Bundle; import android.app.Service; import android.app.Activity; import android.content.Intent; import android.hardware.usb.*; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import android.widget.Toast; import android.content.Context; import android.widget.TextView; import android.content.BroadcastReceiver; import android.content.Intent; import android.content.IntentFilter; import android.app.PendingIntent; import android.os.Handler; public class USBAccess extends Activity { TextView View1 = null; TextView View2 = null; TextView View3 = null; TextView View4 = null; TextView View5 = null; TextView View6 = null; TextView View7 = null; TextView View8 = null; TextView View9 = null; TextView View10 = null; TextView View11 = null; UsbManager myUsbManager; UsbDevice myUsbDevice; UsbInterface Interface[]; UsbDeviceConnection myDeviceConnection; UsbEndpoint epBulkOut, epBulkIn; UsbEndpoint epControl; UsbEndpoint epIntOut, epIntIn; int VendorID; int ProductID; //private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private static int TIMEOUT = 300; int ret = -1; byte[] recvBuffer = new byte[256]; usb_hid usbHid; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.usb_access); /* //usbHid = new usb_hid(this); usbHid = usb_hid.getInstance(this); if (usbHid.getUsbDevice() == 0) { this.setTitle("已连接0设备"); } else if(usbHid.getUsbDevice() == -1) { this.setTitle("已连接-1设备"); } else if(usbHid.getUsbDevice() == -2) { this.setTitle("已连接-2设备"); } else if(usbHid.getUsbDevice() == -3) { this.setTitle("已连接-3设备"); } else { this.setTitle("已连接-9设备"); }*/ View1 = (TextView) findViewById(R.id.Vendor_ID); View2 = (TextView) findViewById(R.id.Product_ID); View3 = (TextView) findViewById(R.id.Count); View4 = (TextView) findViewById(R.id.Interface_ID); View5 = (TextView) findViewById(R.id.Control_Endpoint); View6 = (TextView) findViewById(R.id.BulkIn_Endpoint); View7 = (TextView) findViewById(R.id.BulkOut_Endpoint); View8 = (TextView) findViewById(R.id.InterruptIn_Endpoint); View9 = (TextView) findViewById(R.id.InterruptOut_Endpoint); View10 = (TextView) findViewById(R.id.Serial_Number); View11 = (TextView) findViewById(R.id.Recv_Data); // 获取UsbManager myUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); // 枚举设备 enumerateDevice(myUsbManager); // 查找设备接口 ret = getDeviceInterface(); // 获取设备endpoint if(ret == 0) assignEndpoint(Interface[0]); // 打开conn连接通道 if(ret == 0) { ret = openDevice(Interface[0]); } // 开始USB数据收发 if(ret == 0) { UsbReadThread thread = new UsbReadThread(); thread.start(); final Handler handler= new Handler(); final Runnable runnable = new Runnable() { public void run() { View11.setText("data 0:" + recvBuffer[0] + '\n' + "data 1:" + recvBuffer[1] + '\n' + "data 2:" + recvBuffer[2] + '\n' + "data 3:" + recvBuffer[3] + '\n'); } }; final Thread t = new Thread() { @Override public void run() { while(true) { handler.post(runnable); //加入到消息队列 这样没有启动新的线程,虽然没有报异常。但仍然阻塞ProgressDialog的显示 try { sleep(10); //直接调用 } catch (InterruptedException e) { return; } } } }; t.start(); } } public class UsbReadThread extends Thread { @Override public void run() { byte[] data = new byte[256]; while(true) { receiveMessageFromEndpoint(); //sendMessageToEndpoint(data); } } } @Override public void onResume() { super.onResume(); } // 枚举设备函数 private void enumerateDevice(UsbManager mUsbManager) { System.out.println("开始进行枚举设备!\n"); if (mUsbManager == null) { System.out.println("创建UsbManager失败,请重新启动应用!"); Context context = getApplicationContext(); Toast.makeText(context, "创建UsbManager失败,请重新启动应用!", Toast.LENGTH_SHORT).show(); return; } else { HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList(); if (!(deviceList.isEmpty())) { // deviceList不为空 System.out.println("已连接USB设备至PAD!\n"); System.out.println("deviceList is not null!"); Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); while (deviceIterator.hasNext()) { UsbDevice device = deviceIterator.next(); // 输出设备信息 //Log.i(TAG, "DeviceInfo: " + device.getVendorId() + " , " + device.getProductId()); System.out.println("DeviceInfo:" + device.getVendorId() + " , " + device.getProductId()); // 保存设备VID和PID VendorID = device.getVendorId(); ProductID = device.getProductId(); View1.setText("制造商 ID:" + VendorID); //东芝U盘:2352; VrGate Hid: 1155 View2.setText("产品ID:" + ProductID); //东芝U盘:25924; VrGate Hid: 22352 // 保存匹配到的设备 if (VendorID == 1155 && ProductID == 22352) { //if (VendorID == 2352 && ProductID == 25924) { myUsbDevice = device; // 获取USBDevice System.out.println("发现待匹配设备:" + device.getVendorId() + "," + device.getProductId()); Context context = getApplicationContext(); Toast.makeText(context, "发现待匹配设备。", Toast.LENGTH_SHORT).show(); } } } else { System.out.println("请连接USB设备至PAD!"); Context context = getApplicationContext(); Toast.makeText(context, "请连接USB设备至PAD!", Toast.LENGTH_SHORT).show(); } } } // 寻找设备接口 private int getDeviceInterface() { if (myUsbDevice != null) { int count = -1; //Log.d(TAG, "interfaceCounts : " + myUsbDevice.getInterfaceCount()); count = myUsbDevice.getInterfaceCount(); System.out.println("设备接口数:" + count); View3.setText("设备接口数:" + count); if (count <= 0) return -2; Interface = new UsbInterface[count]; for (int i = 0; i < myUsbDevice.getInterfaceCount(); i++) { //UsbInterface intf = myUsbDevice.getInterface(i); Interface[i] = myUsbDevice.getInterface(i); // 保存设备接口 System.out.println("成功获得设备接口:" + Interface[i].getId()); View4.setText("接口号:" + Interface[i].getId()); View1.setText("制造商 ID:" + VendorID + ";" + myUsbDevice.getInterfaceCount() + ";" + Interface[i].getInterfaceClass() + ";" + Interface[i].getInterfaceSubclass() + ";" + Interface[i].getInterfaceProtocol()); } return 0; } else { System.out.println("设备为空!"); return -1; } } // 分配端点,IN | OUT,即输入输出;可以通过判断 private void assignEndpoint(UsbInterface mInterface) { if ((myUsbDevice != null) && (mInterface != null)) { for (int i = 0; i < mInterface.getEndpointCount(); i++) { UsbEndpoint ep = mInterface.getEndpoint(i); int type = ep.getType(); int direction = ep.getDirection(); // look for bulk endpoint if (type == UsbConstants.USB_ENDPOINT_XFER_BULK) { if (direction == UsbConstants.USB_DIR_OUT) { epBulkOut = ep; System.out.println("Find the BulkEndpointOut," + "index:" + i + "," + "使用端点号:" + epBulkOut.getEndpointNumber()); View7.setText("Find the BulkEndpointOut," + "index:" + i + "," + "使用端点号:" + epBulkOut.getEndpointNumber()); } else { epBulkIn = ep; System.out.println("Find the BulkEndpointIn:" + "index:" + i + "," + "使用端点号:" + epBulkIn.getEndpointNumber()); View6.setText("Find the BulkEndpointIn:" + "index:" + i + "," + "使用端点号:" + epBulkIn.getEndpointNumber()); } } // look for control endpoint else if (type == UsbConstants.USB_ENDPOINT_XFER_CONTROL) { epControl = ep; System.out.println("find the ControlEndPoint:" + "index:" + i + "," + "使用端点号:" + epControl.getEndpointNumber()); View5.setText("find the ControlEndPoint:" + "index:" + i + "," + "使用端点号:" + epControl.getEndpointNumber()); } // look for interrupt endpoint else if (type == UsbConstants.USB_ENDPOINT_XFER_INT) { if (direction == UsbConstants.USB_DIR_OUT) { epIntOut = ep; System.out.println("find the InterruptEndpointOut:" + "index:" + i + "," + "使用端点号:" + epIntOut.getEndpointNumber()); View9.setText("find the InterruptEndpointOut:" + "index:" + i + "," + "使用端点号:" + epIntOut.getEndpointNumber()); } else { epIntIn = ep; System.out.println("find the InterruptEndpointIn:" + "index:" + i + "," + "使用端点号:" + epIntIn.getEndpointNumber()); View8.setText("find the InterruptEndpointIn:" + "index:" + i + "," + "使用端点号:" + epIntIn.getEndpointNumber()); } } } if (epBulkOut == null && epBulkIn == null && epControl == null && epIntOut == null && epIntIn == null) { throw new IllegalArgumentException("not endpoint is founded!"); } } } // 打开设备 public int openDevice(UsbInterface mInterface) { if (mInterface != null) { UsbDeviceConnection conn = null; Context context = getApplicationContext(); // 在open前判断是否有连接权限;对于连接权限可以静态分配,也可以动态分配权限 if (myUsbManager.hasPermission(myUsbDevice)) { conn = myUsbManager.openDevice(myUsbDevice); //此处与device_filter.xml中的值密切相关! if (conn == null) { Toast.makeText(context, "打开设备失败,未找到该设备!", Toast.LENGTH_SHORT).show(); return -2; } } else { Toast.makeText(context, "打开设备失败,无连接权限!", Toast.LENGTH_SHORT).show(); return -3; } if (conn.claimInterface(mInterface, true)) { myDeviceConnection = conn; //if (myDeviceConnection != null)// 到此你的android设备已经连上zigbee设备 { System.out.println("open设备成功!"); Toast.makeText(context, "打开设备成功!", Toast.LENGTH_SHORT).show(); } final String mySerial = myDeviceConnection.getSerial(); System.out.println("设备serial number:" + mySerial); View10.setText("设备序列号:" + mySerial); //View10.setText("端点数:" + mInterface.getEndpointCount()); return 0; } else { System.out.println("无法打开连接通道。"); Toast.makeText(context, "无法打开连接通道。", Toast.LENGTH_SHORT).show(); conn.close(); return -4; } } return -1; } // 发送数据 private void sendMessageToEndpoint(byte[] buffer) { //if (buffer == null) // return; if(epIntOut != null) { // interruptOut传输 if (myDeviceConnection.bulkTransfer(epIntOut, buffer, buffer.length, 0) < 0) { System.out.println("interruptOut返回输出为 负数!\n"); recvBuffer[1] = -1; recvBuffer[2] = -5; return; } recvBuffer[1] = 4; recvBuffer[2] = 6; //System.out.println("Send Message Succeed."); } else if(epBulkOut != null) { // bulkOut传输 if (myDeviceConnection.bulkTransfer(epBulkOut, buffer, buffer.length, 0) < 0) { recvBuffer[1] = -7; recvBuffer[2] = -5; System.out.println("bulkOut返回输出为 负数!\n"); return; } recvBuffer[1] = 6; recvBuffer[2] = 4; //System.out.println("Send Message Succeed."); } } // 从设备接收数据bulkIn private byte[] receiveMessageFromEndpoint() { if(epIntIn != null) { if (myDeviceConnection.bulkTransfer(epIntIn, recvBuffer, 64, 0) < 0) { System.out.println("interruptIn返回输出为负数!\n"); recvBuffer[0] = -3; recvBuffer[3] = -9; return null; } //System.out.println("Receive Message Succeed!" + "数据返回" + myDeviceConnection.bulkTransfer(epBulkIn, recvBuffer, recvBuffer.length, 3000)); } else if(epBulkIn != null) { recvBuffer[0] = 3; recvBuffer[3] = 3; if (myDeviceConnection.bulkTransfer(epBulkIn, recvBuffer, recvBuffer.length, 0) < 0) { recvBuffer[0] = -2; recvBuffer[3] = -7; System.out.println("BulkIn返回输出为 负数!\n"); return null; } //System.out.println("Receive Message Succeed!" + "数据返回" + myDeviceConnection.bulkTransfer(epBulkIn, recvBuffer, recvBuffer.length, 3000)); } return recvBuffer; } }
Android USB Host 通信程序的更多相关文章
- Android USB Host 与 Hid 设备通信bulkTransfer()返回-1问题的原因
近期一直在做Android USB Host 与USB Hid设备(STM32FXXX)的通信,遇到了很多问题.项目源码以及所遇到的其他问题可以见本博客其他相关文章,这里重点讲一下bulkTransf ...
- Android USB Host与HID通讯
前端时间捣鼓一个HID的硬件, 需要和android通信, 网上搜索了一圈,收获不小. 比较好的文章是: Android USB Host与HID通讯 Android Service创建US ...
- 翻译Android USB HOST API
翻译Android USB HOST API 源代码地址:http://developer.android.com/guide/topics/connectivity/usb/host.html 译者 ...
- Android USB Host与HID通讯 (二)
不好意思,从上一篇到现在确实比较忙,中间又外出了一段时间,虽然也上LOFTER,或者看到一些朋友QQ上加我,给我发信息询问,有些看到了有些可能没看到,偶尔回复了一两个,也不咋的详细,在此我想说,一方面 ...
- Android USB Host与HID通讯 (一)
去年9月份来到现在的公司,接到新公司的第一个项目就是Android USB Host与HID通讯,当时也什么都不懂,就拿着google的api 开发指南 (http://developer.andro ...
- Android USB Host 与 HID 之通讯方法(bulkTransfer()与controlTransfer()方法使用)
转载地址:差满多乃几 Android USB Host与HID通讯,就目前Google Developer提供的方法有bulkTransfer()与controlTransfer(),看是简简单单的两 ...
- Android USB Host 与 HID 之通讯方法
Android USB Host与HID通讯,就目前Google Developer提供的方法有bulkTransfer()与controlTransfer(),看是简简单单的两个方法,要实现真正的通 ...
- 【转】Android Service创建USB HOST通信
之前做了一个关于Android USB通信的Case,通过Android的USB总线给Zigbee供电,和板载的Zigbee(基于Zigbee的自组网)进行通信.要使用Android的USB Host ...
- Android Service创建USB HOST通信
之前做了一个关于Android USB通信的Case,通过Android的USB总线给Zigbee供电,和板载的Zigbee(基于Zigbee的自组网)进行通信.要使用Android的USB Host ...
随机推荐
- ubuntu 16.04 chrome flash player 过期
今天手贱更新了系统,发现chrome flash插件过期了 解决方法: 使用全局代理打开 chrome $: google-chrome --proxy-server="socks5://1 ...
- 数据库字段出现科学计数法e+的情况分析
问题: 有时候,我们在将excel表格中数据导入数据库中时,对于表格中的数字会默认为float的数据类型,这个时候导入到数据库中的这个表的值是正常显示的: 然而如果你要把导入到数据库中的表,再插入到另 ...
- Merge Into For Update Example
Merge Into article aa Using ( SELECT md5_id, Min(article_id) as Min_Article_ID from article )) and s ...
- Objective-C 学习笔记(Day 2)
------------------------------------------- 如何根据题目准确完整清晰的声明一个类并实现给定的行为 /* //下面这个程序教大家如何根据题目去声明一个类,并 ...
- C#基于AE组件二次开发常见问题
由于本人从事的是在.net平台下进行GIS的二次开发,所以第一篇博文就说一下:我最近在项目中出现的常见的问题,如果能够给大家增加一点点便利,也是我的荣幸,如果大家对于这次博文有什么意见和建议,欢迎大家 ...
- 存储占用:Memory Map 汉化去广告版
转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/storage-occupancy-memory-map-localization-to-billboards ...
- 第43条:返回零长度的数组或者集合,而不是null
private final List<Cheese> cheesesInStock = ...; public Cheese[] getCheese() { if(cheesesInSto ...
- Headfirst设计模式的C++实现——迭代器(Iterator)
iterator.h #ifndef _ITERATOR_H_ #define _ITERATOR_H_ #include "menu_item.h" class Iterator ...
- HTML5之图像处理
--- 内嵌图像 - drawImage可以绘制图像context.drawImage(image,dx,dy)context.drawImage(image,dx,dy,dw,dh)context. ...
- C# 读取快捷方式指向的文件
C# 读取快捷方式指向的文件 [Flags()] public enum SLR_FLAGS { SLR_NO_UI = 0x1, SLR_ANY_MATCH = 0x2, SLR_UPDATE = ...