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

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

   

    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;
  }}