现在的位置: 首页 > 综合 > 正文

Android的联通性—USB的从属模式(四)

2013年08月08日 ⁄ 综合 ⁄ 共 3304字 ⁄ 字号 评论关闭

获得跟附件通信的权限

在跟USB附件设备进行通信之前,你的应用程序必须要从用户那里获得许可。

注意:如果你的应用程序使用Intent过滤器来发现那些被接入的附件设备,而且用户允许你的应用程序处理该Intent对象,那么会自动的接收许可。否则,在连接附件设备之前,你必须明确的申请接入许可。

明确的申请接入许可,在有些情况下是必须的,如在你的应用程序列举出了已经接入的附件设备,并要跟其中之一进行通信时。在试图跟其通信之前,你必须检查访问该附件设备的权限。否则,如果用户拒绝了你访问该附件设备的请求,你会收到一个运行时错误。

要明确的获得许可,首先就要创建一个广播接收器。这个接收器会监听在调用requestPermission()方法时获得的用于广播的Intent对象。调用requestPermission()方法时会显示一个对话框,向用户请求连接附件设备的权限。以下代码显示了如何创建这个广播接收器:

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) {

       
String action = intent.getAction();

       
if (ACTION_USB_PERMISSION.equals(action)) {

           
synchronized (this) {

               
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

 

               
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {

                   
if(accessory != null){

                       
//call method to set up accessory communication

                   
}

               
}

        
       else {

                   
Log.d(TAG, "permission denied for accessory " + accessory);

               
}

           
}

       
}

   
}

};

在你的Activity的onCreate()方法中注册该广播接收器:

UsbManager mUsbManager = (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);

当用户应答了该对话框,你的广播接收器会收到一个包含了EXTRA_PERMISSION_GRANTED类型附件的Intent对象,它用一个布尔值来代表回答结果。在连接该附件设备之前,要检查该附件的值是否是true。

跟一个附件设备通信

通过使用UsbManagerd对象获取一个文件描述符来跟附件设备通信,你能够使用这个文件描述符建立读写数据的输入和输出流。该流代表了附件设备的输入和数据块端点。你应该在另外一个线程中建立设备和附件之间的通信,以便不至于阻塞主UI线程。下例显示了如何打开跟附件设备的通信:

UsbAccessory mAccessory;

ParcelFileDescriptor mFileDescriptor;

FileInputStream mInputStream;

FileOutputStream mOutputStream;

 ...

private void openAccessory() {

   
Log.d(TAG, "openAccessory: " + accessory);

   
mFileDescriptor = mUsbManager.openAccessory(mAccessory);

   
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对象来读写附件设备。在使用FileInputStream对象从附件设备中读取数据时,要确保有足够大的缓存来存储USB包数据。Android从属模式协议支持的最大包缓存是16384个字节,因此你可以简单的始终把你的缓存声明成这个尺寸。

注意:在底层,对于全速USB附件设备的64字节包和高速USB附件设备的512字节包,Android从属模式协议会简单的把这个两个数据打包成一个逻辑包。

终止跟附件设备的通信

在完成跟附件设备的通信或附件设备被拔出时,你要调用close()方法来关闭被打开的文件描述符。创建以下广播接收器,来监听分离事件:

BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

   
public void onReceive(Context context, Intent intent) {

       
String action = intent.getAction();

 

       
if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {

           
UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

           
if (accessory != null) {

               
// call your method that cleans up and closes communication with the accessory

           
}

       
}

   
}

};

在应用程序中创建的广播接收器,而且不在清单文件中,这样的广播接收器允许你的应用程序只在运行时处理分离事件。这种方式,分离事件只发送给当前正在运行的应用程序,并不会广播给所有的应用程序。

抱歉!评论已关闭.