换到了一家新公司,于是就有了新的项目。这次的项目 要用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 通信程序的更多相关文章

  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. C# 3.0 基本框架

    使用TimeZoneInfo: static void Main() { TimeZoneInfo wa = TimeZoneInfo.FindSystemTimeZoneById ("W. ...

  2. ASP.NET Web Service如何工作(2)

    ASP.NET Web Service如何工作(2) [日期:2003-06-26] 来源:CSDN  作者:sunnyzhao(翻译) [字体:大 中 小] HTTP管道一旦调用了.asmx句柄,便 ...

  3. Ext.Net学习笔记19:Ext.Net FormPanel 简单用法

    Ext.Net学习笔记19:Ext.Net FormPanel 简单用法 FormPanel是一个常用的控件,Ext.Net中的FormPanel控件同样具有非常丰富的功能,在接下来的笔记中我们将一起 ...

  4. android开发 锁屏 真正的锁屏,是go锁屏那种。

    想做个锁屏界面很久了,最近一周,历经千辛万苦,越过种种挫折,终于完美实现了这一要求,在此将锁屏思路分享出来. 注意:这不是什么一键锁屏,是类似“go锁屏”那样的锁屏界面. 准备:本程序共需要 两个ac ...

  5. Java 7 新的 try-with-resources 语句,自动资源释放

    Java 7 的编译器和运行环境支持新的 try-with-resources 语句,称为 ARM 块(Automatic Resource Management) ,自动资源管理. 新的语句支持包括 ...

  6. python isinstance 判断各种类型的小细节

    1. 基本语法 isinstance(object, classinfo) Return true if the object argument is an instance of the class ...

  7. Linux C 程序 空语句-gcc编译命令(SIX)

    C语言语句1.空语句:当一个if或者while判断部分能完成工作,空语句可以用来表示if或者while内的空循环体 if(a == b ); 2.gcc编译器 //程序的编译过程: // 预处理:pr ...

  8. gb2312编码提交url乱码解决

    gb2312编码提交url,服务器接收时出现乱码,用System.Web.HttpUtility.UrlDecode();解码 ,还是出现乱码,困老了我好长时间,终于在google上找到了解决办法. ...

  9. 少年Vince之遐想

    本文999纯水贴,然转载仍需注明: 转载至http://www.cnblogs.com/VinceYang1994/ 昨天去姑姑家拜年,表哥房间的角落里有一架缠有蜘蛛网的遥控直升飞机. 打开飞机及遥控 ...

  10. CSS实现文字上标、下标

    .sup{vertical-align:super; color:red; font-size:9px; font-family:Arial, Helvetica, sans-serif; margi ...