Android · 2015年2月11日 0

Android USB编程基础知识

USB编程
USB编程分为USB HOST(主机模式)和USB Accessory(配件模式)
USB相关操作的类都集中在android.hardware.usb命名空间中

1.USB Accessory API简介
配件模式中两个重要的类:UsbAccessory和UsbMnanger,其中通过UsbManager可以获得USB状态信息,并负责和USB配件进行通信;UsbAccessory代表一个USB配件并且包含获取配件特定信息的方法。
定义UsbManager对话和UsbAccessory对象的方法.
通过Context.USB_SERVICE可以实例化UsbManager对象
UsbManager manager=(UsbManager)getSystemService(Context.USB_SERVICE);
通过以下方式获取UsbAccessory对象
UsbAccessory accessory=(UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
2.Android manifest文件配置
因为不是所有的设备都支持USB accessory API需要在manifest中使用<uses-feature>元素声明应用支持它,值为:android.hardware.usb.accessory.支持的最小的api是API Level 12。
如果希望应用在USB配件连接时能够接收通知,则在主Activity中需要为android.hardware.usb.action.USB_ACCESSORY_ATTACHED这个Intent中指定一对<intent-filter>和<meta-data>。
<meta-data>元素指向里一个xml资源文件,该文件包含希望得到的配件的一些特定信息。
这个XML资源文件中为希望过滤的配件声明<usb-accessory>元素。每一个<usb-accessory>都可以包含“制造商”、“模式”和“版本”这3个属性。资源文件要保存在res/xml/目录下,资源文件的名称必须和在<meta-data>元素中指定的名称相同。
例如:
android manifest文件
<manifest ….>
<uses-feture android:name=”android.hardware.usb.accessory”/>
<uses-sdk android:minSdkVersion=”12″/>

<application>
<uses-library android:name=”com.android.future.usb.accessory” />
<activity …>

<intent-filter>
<!–使得应用程序能够发现USB附近设备–>
<action android:name=”android.hardware.usb.action.USB_ACCESSORY_ATTACHED”/>
</intent-filter>
<meta-data android:name=”android.hardware.usb.action.USB_ACCESSORY_ATTACHED” android:resource=”@accessory_filter”/>
</activity>
</application>
</manifest>
res/xml/有个xml文件accessory_filter.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<!–model 属性表明模式–>
<!–manufacturer表明制造商–>
<!–version表明版本–>
<usb-accessory model=”Demokit” manufacturer=”Google,Inc.” version=”1.0″/>
</resoutces>

配件使用
1.通过一个可以过滤配件附加事件的意图过滤器来找到合适的连接配件,或者枚举所有已连接的配件来找到合适的某个配件
2.尚未获得许可的用户在与配件通信前需要获得权限
3.通过合适的端口与配件进行读写通信

用户可以通过两种方式发现配件:一种是使用Intent过滤器在用户连接配件时对其进行通知,另一种通过枚举已经连接的所有配件。

意图过滤使用android.hardware.usb.action.USB_ACCESSORY_ATTACHED指定一个意图进行过滤。在这个意图过滤中需要指定一个资源文件来特别说明这个usb配件的属性,例如制造商、模式和版本,当连接的配件和意图过滤条件匹配时,应用会收到一个通知。

在Activity中可以通过以下方式获得UsbAccessory,它代表了所有连接的配件
UsbAccessory accessory=(UsbAccessroy) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
枚举所有支持的配件
当应用在运行的时候,可以在应用中枚举所有能够识别的配件。通过getAccessoryList()方法获得一个包含所有已连接USB配件的数组
UsbManager manager=(UsbManager) getSystemService(Content.USB_SERVICE);
UsbAccessory[] accessoryList=mamager.getAccessoryList();
注意:目前一次只能连接一个USB配件,但是这个API设计的在未来可用于支持多个配件

获得与某个配件通信的权限
在与某个USB配件通信前,应用必须从用户那里获得权限
注意:如果应用在连接配件时是通过一个意图过滤器来发现它们,而用户允许应用来处理这个意图时,它将自动获得权限,如果用户不允许,那么久必须在与配件通信前明确的在应用中请求获得权限。

为了获得权限,首页需要创建一个广播接收器,在调用requestPermission()方法是,这个接收器会监听广播中的意图。通过调用requestPermisson()方法为 用户弹出一个获取权限对话框。
例子:
//定义权限字符串
private static final String ACTION_USB_PERMISSION=”com.android.example.USB_PERMISSION”;
//新建广播接收器
private final BroadcastReceiver mUsbReceiver=new BroadcastReceiver(){
public void onReceive(Context context,Intent intent){
//获得当前Intent的权限字符串
String action=intent.getAction();
//判断权限是否和定义的相同
if(ACTION_USB_PERMISSION.equals(action)){
synchroized(this){
//声明UsbAccessory对象
UsbAccessory accessory=(UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if(intent.getBooleanExtra(UsbManager.EXTRA_PERAMISSION_GRANTED,false)){
if(accessory!=null){
//调用方法建立与某个配件的通信
}
}else{
//没有获取权限
}
}
}
}
}

为了注册广播接收器,需要将下面代码放到activity中的onCreate()方法中
//获得系统服务对象
UsbManager mUsbManage=(UsbManager)getSystemService(Context.USB_SERVICE);
//定义权限字符串
private static final String ACTION_USB_PERMISSION=”com.android.example.USB_PERMISSION”;

//稍后处理配件通信事件
mPermissionIntent=PendingIntent.getBroadcast(this,0,new Intent(ACTION_USB_PERMISSION),0);
//新建过滤器
IntentFilter filter=new IntentFilter(ACTION_USB_PERMISSION);
//注册接收器
registerReceiver(mUsbReceiver,filter);

//当需要弹出获取权限的对话框时,则要调用requestPermission()方法
UsbAccessory accessory;

mUsbManager.requestPermission(accessory,mPermissionIntent);
与配件通信
可以通过使用UsbManager这个类与配件进行通信,通过这个类可以获得一个文件描述符,然后可以利用该描述符设置输入和输出流来读取和写入数据。这些流用来代表输入和输出的批量端口。最好另外建立一个线程来让设备与配件进行通信,因为这样就可以不需要把主线程锁起来了。
列如:
//新建UsbAccessory对象
UsbAccessory mAccessory;
//新建ParelFileDescriptor对象
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;

//打开通信
private void openAccessory(){
//获取设备文件描述
mFileDescriptor=mUsbmanager.openAccessory(mAccessory);
//设备文件描述不为null
if(mFileDescriptor!=null){
//获取文件描述
FileDescriptor fd=mFileDescriptor.getFileDescriptor();
mInputStream=new FileInputStream(fd);
mOutputStream=new FileOutputStream(fd);
//打开新线程
Thread thread=new Thread(null,this,”AccessoryThread”);
//启动线程
thread.start();
}
}
在这个线程run()方法中,可以通过FileInputStream或者FileOutputStream对象来对配件进行读写操作。Android配件协议支持高达16384字节的数据包缓存区,所以设置缓冲字节16384。

终止与配件的通信
当完成与配件的通信之后,或则该配件被移除了,通过调用close()方法来关闭已打开的文件描述符。为了监听分离这样的事件,需要创建广播接收器。
//新建监听
BroadcastReceiver mUsbReceiver=new BroadcastReceiver(){
public void onReceive(Context context,Intent intent){
//获取事件字符串
String action=intent.getAction();
//对比师父为需要处理的事件权限
if(UsbMangaer.ACTION_USB_ACCESSORY_DETACHED.equals(action)){
//新建UsbAccessory对象
UsbAccessory accessory=(UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if(accessory!=null){
//嗲用方法终止与配件的通信,清理内容
}
}
}
};

要在应用中创建这个广播接收器,而不是在manifest文件中创建,且允许应用智能在其运行的时候处理这样的配件分离事件。这样的话,配件分离这个事件就只向在正在运行的应用广播,而不是向所有的应用进行广播。
USB Host Mode
当android设备工作在浙江模式下的时候,Android设备作为主机,为USB总线供电并与USB设备进行通信。同样仅在android3.1以上版本支持这种模式。主机模式使用步骤和配件模式类似。

相关类 1.UsbManager 2.UsbDevice(代表一个USB设备)3.UsbInterface(usb设备的一个接口) 4.USBEndpoint(代表一个接口的摸个端口类) 5.UsbDeviceConnection(USB连接类,用此连接可以向USB设备传输数据)

 

转载注明:http://www.etongwl.com/?p=642

Share this: