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 ...
随机推荐
- Java 简单算法--打印乘法口诀(只使用一次循环)
package cn.magicdu.algorithm; /** * 九九乘法口诀表 * * @author xiaoduc * */ public class NineNineMulitTable ...
- Web开发知识点总结
前言:这是一篇简单的web开发知识点的总结,适用于刚开始学习编程的人来学习的.我是为了能够在熟记熟记这些知识点而总结的一篇文章. 1 什么是浏览器? (1) 浏览器就是接收浏览者的操作(打 ...
- Cisco交换机中的flash,Rom,RAM,nvram的区别
Flash内存,也叫闪存,是路由器当中常用的一种内存类型.它是可读写的存储器,在系统重新启动或关机之后仍能保存数据.Flash中存放着当前使用中的IOS(路由器操作系统). 只读内存(ROM)在Cis ...
- 【html】【17】高级篇--loading加载
参考: http://aspx.sc.chinaz.com/query.aspx?keyword=%E5%8A%A0%E8%BD%BD&classID=835 下载: http://sc. ...
- const char*、char*、char* const、char[]、string的区别
1.const char* p: p is a pointer to const char(char const* p 一样) 意思就是不能通过p指针来修改p指向的内容(但是内容可以修改). 2. ...
- QML动态加载组件
QML中的组件可以重复使用,并且可以通过Loader加载.如下示例: import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Win ...
- Qwt的编译与配置
QWT,全称是Qt Widgets for Technical Applications,是一个基于LGPL版权协议的开源项目, 可生成各种统计图.它为具有技术专业背景的程序提供GUI组件和一组实用类 ...
- [PHP] chr和ord函数实现字符串和ASCII码互转
chr和ord函数是用来字符串和ASCII码互转的. ASCII码是计算机所能显示字符的编码,它的取值范围是0-255,其中包括标点.字母.数字.汉字等.在编程过程中,经常把指定的字符转化为ASCI ...
- python【第五篇】常用模块学习
一.主要内容 模块介绍 time &datetime模块 random os sys shutil json & pickle shelve xml处理 yaml处理 configpa ...
- dota 路人水平鉴定器
测试的dota水平...目的是学习一下tornado框架 #coding:utf8 import tornado.web,tornado.httpserver,tornado.ioloop,torna ...