Android USB Host Usage Details

Source: Internet
Author: User

I must declare that this article was recently migrated from my own X-level space, not plagiarism.

[Nonsense]
Some time ago, my team developed an android host system, which requires an external USB Fingerprint machine, card reader, and USB flash disk. The hardware already exists. The host is a rich set of development board interfaces, android USB Host Mode is also supported, which is not required for peripherals.
But there was a problem, driver! Originally, this project originated from windows and all peripherals were developed for Windows. If a dedicated driver is used, developing Android requires a complicated process. Later, after the transformation of hardware engineers, we switched USB to the hid mode to reduce the development difficulty.
After a period of searching for online materials, there are very few Android usb host materials, not a few, but almost identical. I am Baidu + Google, changing countless Chinese and English keywords, and finally I completed my project as expected, communicated with the HID device normally, and recognized the USB flash disk. I decided to write an article on my own to reduce the number of Chinese documents on the Internet.
My code references some materials from "Open Source China". If you cannot solve this problem, you can query it there.
[Basic functions]
Note: The steps in this article may require you to have the root permission. Otherwise, some operations may fail. We strongly recommend that you first use the root device.
Step 1: Make sure that your Android device supports USB host. For more information, see your manual. It is necessary to read this article.
Step 2: Check whether USB access is enabled for Android. This step is very important. Operation: Go to the system and find the directory "/system/etc/Permissions". You can use the es or Re File Manager to perform operations. Check whether there is a file "android. Hardware. USB. Host. xml" in this directory. If not, create a file with the same name. The content is as follows:

<permissions>     <feature name="android.hardware.usb.host"/> </permissions>

Copy the file to the "/system/etc/Permissions" directory. (You can use ddms of eclipse for help and push it in)
Step 3: Actually, with step 3, you can do it, but I am not very sure, so I have step 4. Check the directory "/system/etc/Permissions" and drag "handheld_core_hardware.xml (mobile phone) or tablet_core_hardware.xml (tablet)" to open the file, see if there is any of the following nodes under the <permissions> node:

<feature name="android.hardware.usb.host" />

If not, add a new line, save it, and push it to replace the original file. For example, the content of my file is:

<?xml version="1.0" encoding="utf-8"?><permissions>    <feature name="android.hardware.camera" />    <feature name="android.hardware.location" />    <feature name="android.hardware.location.network" />    <feature name="android.hardware.sensor.compass" />    <feature name="android.hardware.sensor.accelerometer" />    <feature name="android.hardware.bluetooth" />    <feature name="android.hardware.touchscreen" />    <feature name="android.hardware.microphone" />    <feature name="android.hardware.screen.portrait" />    <feature name="android.hardware.screen.landscape" />    <feature name="android.hardware.usb.host" /></permissions>

Step 4: restart your Android device.
[Detailed code]
As a matter of fact, after completing the above steps, the rest of the code is very simple, and the content I found is basically the same.


We strongly recommend that you refer to the Google example below in the SDK document: adbtest. The classes written by adbtest are very useful. The following content can be ignored. I later referred to the adbtest, converted into a general class, can let my host to receive multiple USB-HID peripherals, to achieve asynchronous transmission and receiving at the same time. Of course, you can use the following code to draw the opposite picture.


First, let's look at the androidmanifest. xml file. In order to write this article, I made a lot of comments:

<Manifest xmlns: Android = "http://schemas.android.com/apk/res/android" package = "com. example. usbmanager" Android: versioncode = "1" Android: versionname = "1.0"> <! -- This permission is required; otherwise, the hardware cannot be operated. Google's documents are not mentioned. It is said that it is automatically obtained after a filter is available, but my project does not succeed. --> <Uses-Permission Android: Name = "android. Permission. hardware_test"/> <! -- This sentence is also required --> <uses-feature Android: Name = "android. Hardware. USB. Host" Android: required = "true"/> <! -- The SDK must be 12 or above, Because USB host --> <uses-SDK Android: minsdkversion = "12" Android: targetsdkversion = "17"/> <application Android: icon = "@ drawable/ic_launcher" Android: Label = "@ string/app_name" Android: theme = "@ style/apptheme"> <activity Android: Name = ". mainactivity "Android: Label =" @ string/app_name "> <intent-filter> <action Android: Name =" android. intent. action. main "/> <category Android: Nam E = "android. Intent. Category. launcher"/> </intent-filter> <! -- The following filter is manually added. If it is not added, it can be dynamically registered in the code, but my code is registered here --> <intent-filter> <action Android: name = "android. hardware. USB. action. usb_device_attached "/> </intent-filter> <! -- The following meta-data is manually added. It is used to filter your specific USB device. The device_filter is an XML file. --> <meta-data Android: name = "android. hardware. USB. action. usb_device_attached "Android: Resource =" @ XML/device_filter "/> <! -- <Intent-filter> <action Android: Name = "android. intent. action. view "> </Action> <category Android: Name =" android. intent. category. default "> </Category> <data Android: mimetype =" "> </data> </intent-filter> --> </activity> </Application> </manifest>

Note: The above file mentioned a file named "device_filter", which is also an important file for your success, "device_filter.xml". This file must be created by yourself:
Create a new folder named "XML" at the res node in the project (no operation ???? Right-click it !), Create an XML file named "device_filter" in the XML folder. The content is as follows:

<? XML version = "1.0" encoding = "UTF-8"?> <Resources> <! -- The vendor-ID and product-ID in the following content are the USB vid and PID. Please find the properties of this device in windows and check the vid_pid value of the device. --> <! -- Note that the id value displayed in Windows Device properties is in hexadecimal notation and must be converted to hexadecimal notation and configured. --> <! -- Yijie USB flash drive used for testing. The vid displayed in Windows is 090c, and the conversion to decimal is 2316, the other principles are the same --> <USB-device vendor-id = "2316" product-id = "4096"/> <! -- M1 card reader for testing --> <USB-device vendor-id = "1155" product-id = "22352"/> <! -- USB-HUB --> <USB-device vendor-id = "1507" product-id = "1544"/> </resources>

I must make it clear that the above devices are used for testing. They are basically different from the devices on hand. Please check the USB device vid \ PID and convert it.

Let's take a look at the layout file activity_main.xml. This layout is used for testing and is very casual. Please test it based on your project layout. You do not have to use this layout, don't ask me why I want to design the layout like this. I just want to play with it. Don't be so serious ~~~~~

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >       <TextView        android:id="@+id/tvtitle"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/title" />       <EditText        android:id="@+id/etxsend"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/tvtitle"        android:layout_below="@+id/tvtitle"        android:ems="10"        android:hint="@string/sendhint"        android:visibility="invisible" />       <EditText        android:id="@+id/etxreceive"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/btsend"        android:layout_below="@+id/btsend"        android:layout_marginTop="37dp"        android:ems="10"        android:hint="@string/receivehint"        android:visibility="invisible" />       <Button        android:id="@+id/btreceive"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/etxreceive"        android:layout_below="@+id/etxreceive"        android:text="@string/btreceive" />       <Button        android:id="@+id/btsend"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/etxsend"        android:layout_below="@+id/etxsend"        android:layout_marginTop="16dp"        android:text="@string/btsend" />       <ListView        android:id="@+id/lsv1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/btreceive"        android:layout_below="@+id/btreceive" >    </ListView>   </RelativeLayout>

In particular, the text on some buttons mentioned above, people use their imagination, and I don't want to post those files under values any more. Some buttons are not used at all. I used it for debugging.

This time, we entered the direct code module: mainactivity. Java

Package COM. example. USB Manager; import Java. util. arraylist; import Java. util. hashmap; import Java. util. iterator; import Java. util. list; import android. OS. bundle; import android. r. string; import android. app. activity; import android. app. pendingintent; import android. content. broadcastreceiver; import android. content. context; import android. content. dialoginterface; import android. content. intent; import android. CO Ntent. intentfilter; import android. database. datasetobserver; import android. hardware. USB. usbconstants; import android. hardware. USB. USB device; import android. hardware. USB. usbdeviceconnection; import android. hardware. USB. usbendpoint; import android. hardware. USB. USB interface; import android. hardware. USB. USB Manager; import android. util. log; import android. view. view. onclicklistener; import android. view. gravity; I Mport android. view. menu; import android. view. view; import android. view. viewgroup; import android. widget. arrayadapter; import android. widget. button; import android. widget. edittext; import android. widget. listadapter; import android. widget. listview; import android. widget. toast; public class mainactivity extends activity {Private Static final string tag = "mainactivity"; // Record ID private button btsend; // send button Private USB Manager; // USB Manager private USB device musbdevice; // find the USB device private listview lsv1; // Private USB interface minterface that displays USB information; private USB deviceconnection mdeviceconnection; @ override protected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); btsend = (button) findviewbyid (R. id. btsend); btsend. setonclicklistene R (btsendlistener); lsv1 = (listview) findviewbyid (R. id. lsv1); // obtain the USB device manager = (usbmanager) getsystemservice (context. usb_service); If (Manager = NULL) {return;} else {log. I (TAG, "USB device:" + String. valueof (Manager. tostring ();} hashmap <string, usbdevice> devicelist = manager. getdevicelist (); log. I (TAG, "USB device:" + String. valueof (devicelist. size (); iterator <usbdevice> deviceiterator = Devi Celist. values (). iterator (); arraylist <string> usbdevicelist = new arraylist <string> (); // Number of USB devices stored while (deviceiterator. hasnext () {usbdevice device = deviceiterator. next (); usbdevicelist. add (string. valueof (device. getvendorid (); usbdevicelist. add (string. valueof (device. getproductid (); // Add the code for processing the device here if (device. getvendorid () == 1155 & device. getproductid () == 22352) {musbdevice = device; Log. I (TAG, "Find device") ;}// create an arrayadapter lsv1.setadapter (New arrayadapter <string> (this, android. r. layout. simple_list_item_1, usbdevicelist); findintfandept ();} private byte [] sendbytes; // transmission information byte private byte [] receiveytes; // receive information byte private onclicklistener btsendlistener = new onclicklistener () {int ret =-100; @ override public void onclick (view v) {/** note that, this module uses the hid card reader protocol to communicate with other devices. Like * Please refer to your own device information during testing, strictly in accordance with the hid standards to send and receive data * my example uses the device is Guangzhou micro cloud electronic WY-M1RW-01 contactless card reader, outputreport is 64, so the length of the byte I sent is 64 * the content of the byte I sent is to ask the reader to ring the buzzer for two short and one long */string teststring = "yellow"; sendbytes = clspublic. hexstring2bytes (teststring); // 1. Send the prepared command ret = mdeviceconnection. bulktransfer (epout, Sen Dbytes, sendbytes. length, 5000); log. I (TAG, "sent! "); // 2, receiveytes = new byte [64]; // The 64 here is defined by the device, not by me, you need to set ret = mdeviceconnection according to the device. bulktransfer (ePIN, receiveytes, receiveytes. length, 10000); log. I (TAG, "receive return value:" + String. valueof (RET); If (Ret! = 64) {displaytoast ("receive return value" + String. valueof (RET); return;} else {// view the returned value displaytoast (clspublic. bytes2hexstring (receiveytes); log. I (TAG, clspublic. bytes2hexstring (receiveytes) ;}}; // display the prompted function, which saves time. Haha public void displaytoast (charsequence Str) {Toast = toast. maketext (this, STR, toast. length_long); // sets the toast position. setgravity (gravity. top, 0,200); // display Toast toast. show ();} // search Private void findintfandept () {If (musbdevice = NULL) {log. I (TAG, "no device found"); Return ;}for (INT I = 0; I <musbdevice. getinterfacecount ();) {// obtain the device interface, which is generally an interface. You can print the getinterfacecount () method to view the number of interfaces. This interface has two endpoints, out and in usbinterface INTF = musbdevice. getinterface (I); log. D (tag, I + "" + INTF); minterface = INTF; break;} If (minterface! = NULL) {usbdeviceconnection connection = NULL; // you can determine whether you have the permission if (Manager. haspermission (musbdevice) {// open the device, obtain the usbdeviceconnection object, connect the device, and use it for subsequent communication connection = manager. opendevice (musbdevice); If (connection = NULL) {return;} If (connection. claiminterface (minterface, true) {log. I (TAG, "Find interface"); mdeviceconnection = connection; // use USB deviceconnection and USB interface to set the endpoint and communicate with getendpoint (mdeviceconn Ection, minterface);} else {connection. close () ;}} else {log. I (TAG, "no permission") ;}} else {log. I (TAG, "No Interface found") ;}} private USB endpoint epout; private USB endpoint ePIN; // use USB deviceconnection to set the endpoint and communicate with USB interface private void getendpoint (USB deviceconnection connection, usbinterface INTF) {If (INTF. getendpoint (1 )! = NULL) {epout = INTF. getendpoint (1) ;}if (INTF. getendpoint (0 )! = NULL) {ePIN = INTF. getendpoint (0 );}}}


[Debugging]

If everything goes well, after you connect to your USB device, Android will pop up a prompt box for hardware access, and you will click "OK".

I don't need to talk about the debugging content. eclipse will help you solve it.



Okay! I have already told you all the code to be said. To be honest, the Network Stability of csdn is still poor. Currently, I am looking for a new blog platform. It seems that xyuan is quite good.




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.