源文: http://www.codes51.com/article/detail_4282884_1.html

上篇文章中我们了解了嵌入式设备端将Android手机设置为accessory模式的流程以及嵌入式设备端接收和发送数据的流程,本文将对应介绍Android端accessory模式被激活的过程,以及接下来如何与嵌入式设备端进行通信。本文的源码下载地址:https://git.oschina.net/vonchenchen/aoa_android.git

实现

USBConnStatusManager 底层启动accessory模式

Android系统api通过UsbManager类管理usb相关,这里我们关注一下与accessory模式相关的内容。 
当设备端启动android的accessory模式时,系统将会发送一条广播,设备拔出时也会发送一条广播,同时还有一条申请usb使用权限的广播。所以,要做的第一步就是动态注册这些广播,并编写一个广播接收者来处理对应的事件。这里对于的方法我们封装到了USBConnStatusManager类中,用来管理accessory相关连接。

IntentFilter filter = new IntentFilter();//接收权限信息filter.addAction(ACTION_USB_PERMISSION);//接收accessory连接事件filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);//接收accessory断开事件filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);getContext().registerReceiver(mUsbReceiver, filter);

下面是对应的广播接收者,这里其实只需要监听两个广播,一个是获取usb权限,一旦这个广播发出我们就可以认为设备现在正在启动手机的accessory模式,第一次连接时手机会弹出对话框,让我们选择是否运行usb权限,另外一个就是需要在usb断开时做出反应,告诉设备连接已经断开了。下面是处理广播事件的过程:

mUsbReceiver =new BroadcastReceiver() {@Overridepublicvoid onReceive(Context context, Intent intent) {String action = intent.getAction();Log.i(TAG, "receive usb connect broadcast:"+ action);if (ACTION_USB_PERMISSION.equals(action)) {synchronized (this) {//UsbAccessory accessory = UsbManager.getAccessory(intent);UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);//获取accessory句柄成功if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {Log.d(TAG, "prepare to open usb stream");sCurStatus = STATUS_CONN_OK;mUsbAccessory = accessory;if (mOnUSBConnStatusChanged !=null) {mOnUSBConnStatusChanged.onUSBConnect(accessory);}} else {Log.d(TAG, "permission denied for accessory "+ accessory);sCurStatus = STATUS_CONN_ERR;mUsbAccessory =null;if (mOnUSBConnStatusChanged !=null) {mOnUSBConnStatusChanged.onUSBConnectFailed(accessory);}}}} elseif (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);//if (accessory != null && accessory.equals(mAccessory)) {//检测到usb断开Log.d(TAG, "USB_ACCESSORY_DETACHED "+ accessory);sCurStatus = STATUS_DISCONN;mUsbAccessory =null;//closeAccessory();//synchronized (USBConnStatusManager.class) {if (mOnUSBConnStatusChanged !=null) {mOnUSBConnStatusChanged.onUSBDisconnect(accessory);}//}//}}}};

这里拿到accessory的引用以后就可以用这个引用获取usb的读写流,然后将accessory交给外部接口,由外部类处理数据的具体读写内容。如果接收到设备拔出广播,则手动释放引用,更新连接状态。 
另外,如果设备已经插入并且处于accessory模式,广播接受者并不会调用,这时可以同步开启设备。可以检查mUsbManager.getAccessoryList(),如果有accessory设备则可以直接获取设备引用。由于一般手机都只有一个U口,此处默认只要有一个accessory连接就是我们的设备。下面代码用于同步开启已经存在的于accessory表中的设备:

publicvoidcheckUSBDevice() {UsbAccessory[] accessories = mUsbManager.getAccessoryList();if(accessories == null){Log.i(TAG, "accessories list is null");return;}Log.i(TAG, "accessories length "+accessories.length);UsbAccessory accessory = (accessories == null ? null : accessories[0]);if (accessory != null) {if (mUsbManager.hasPermission(accessory)) {sCurStatus = STATUS_CONN_OK;mUsbAccessory = accessory;//synchronized (USBConnStatusManager.class) {if (mOnUSBConnStatusChanged != null) {mOnUSBConnStatusChanged.onUSBConnect(accessory);}//}} else {//synchronized (mUsbReceiver) {if (!mPermissionRequestPending) {mUsbManager.requestPermission(accessory, mPermissionIntent);mPermissionRequestPending = true;}//}            }}}

USBHelper 具体操作usb的开关和读写等功能

USBHelper类具体操作usb的功能,这个类中持有USBConnStatusManager的单例对象,有了USBConnStatusManager就可以拿到accessroy,通过USBConnStatusManager获取到读写流,这个类就是在外层调用USBConnStatusManager方法,对usb进行操作。

openAsync

这个方法用来开启usb,首先注册广播接收者回调,用来检测usb插拔信息,注册完毕后检查当前系统中存在的accessory设备,如果已经连接了accessroy设备,则直接获取其accessroy的引用,通过这个引用获取读写流,者就是usb的打开过程。

/*** accessory模式打开android的 usb设备* 如果当前列表有处于accessory模式的句柄则直接打开* 如果当前没有则回监听usb插拔,监听到对应事件后检查系统列表* @param onUSBConnStatusChanged*/@OverridepublicvoidopenAsync(final OnUSBConnStatusChanged onUSBConnStatusChanged) {mReciveBuffer = newbyte[RECIVE_BUF_SIZE];//注册USB连接状态监听mUSBConnStatusManager.registOnUSBConnStatusChangedListener(new OnUSBConnStatusChanged() {@OverridepublicvoidonUSBConnect(UsbAccessory accessory) {openAccessory(accessory);if (onUSBConnStatusChanged != null) {onUSBConnStatusChanged.onUSBConnect(accessory);}}@OverridepublicvoidonUSBConnectFailed(UsbAccessory accessory) {closeAccessory();if (onUSBConnStatusChanged != null) {onUSBConnStatusChanged.onUSBConnectFailed(accessory);}}@OverridepublicvoidonUSBDisconnect(UsbAccessory accessory) {closeAccessory();if (onUSBConnStatusChanged != null) {onUSBConnStatusChanged.onUSBDisconnect(accessory);}}});//检查usb列表 查看是否已经连接accessory设备mUSBConnStatusManager.checkUSBDevice();}/*** 通过accessory句柄拿到usb设备的输入输出流* @param accessory*/privatevoidopenAccessory(UsbAccessory accessory) {mFileDescriptor = mUsbManager.openAccessory(accessory);if (mFileDescriptor != null) {mAccessory = accessory;FileDescriptor fd = mFileDescriptor.getFileDescriptor();//usb读写流mInputStream = new FileInputStream(fd);mOutputStream = new FileOutputStream(fd);if (mOnDataTranPrepared != null) {Log.d(TAG, "accessory opened DataTranPrepared");mOnDataTranPrepared.onDataTranPrepared(mInputStream, mOutputStream);}Log.d(TAG, "accessory opened");} else {Log.d(TAG, "accessory open fail");}}

另外这个类还提供了usb数据读写和关闭设备等方法,大家可以参考项目源码。

SimpleTcpWrapper 封装上层通信协议

打通底层数据通道,下面就是封装我们自己协议了,在项目中使用tcp头简单封装了一个协议,可以实现三次握手,数据包通过序列号校验以及根据不同端口分发数据的功能。本章只讨论Android设备底层通信的实现,所以删除了协议部分,只是将usb发送过来的数据原样发送回去。

SimpleTcpWrapper中创建一个USBHelper对象用来管理usb数据通信,调用openAsync异步打开数据。一旦数据连接成功,我们就是开启一个数据接收线程,读取这个accessory的inputstream,一旦收到数据就将数据写入accessory的outputstrem中。

Android AOA协议Android端 流程总结相关推荐

  1. Android usb学习笔记:Android AOA协议Android端 流程总结

    背景 上篇文章中我们了解了嵌入式设备端将Android手机设置为accessory模式的流程以及嵌入式设备端接收和发送数据的流程,本文将对应介绍Android端accessory模式被激活的过程,以及 ...

  2. Android USB的AOA协议设备端(主机模式,配件模式),ADB连接

    USB的ADB/AOA协议(一种是ADB模式,一种是AOA模式).AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议. ADK中与USB配件模式相关的两个类是U ...

  3. android 许可协议,Android 基本控件的使用二(注册许可协议)(CheckBox)

    需要注意的是:按钮部分,在复选框选中之前是显示不可点击状态,一旦被选中之后就会变成可点击按钮. 为复选框设置的监听为:setOnCheckedChangeListener 实现的方法有两种: 方法一: ...

  4. android自定义协议,Android / iOS-自定义URI /协议处理

    编辑5/2014,因为这似乎是一个受欢迎的问题,所以我在回答中添加了很多细节: Android: 对于Android,请单击单击自定义URI时,请参阅意图过滤器以启动我的活动. 您使用一个意图过滤器: ...

  5. Android onvif协议 服务端

    先做个大致分析:这篇文章是把Android设备当做摄像机,通过onvif协议,可以让nvr进行访问,传输rtsp流. 先说下我的思路:第一步:先看文档,了解到onvif协议是通过http建立的连接.第 ...

  6. android spp协议,Android蓝牙开发SPP协议通信

    最近项目中使用到蓝牙SPP协议通信,然后在网上看了很多资料,进行学习使用,为了加深印象,做个简单的整理. 1.使用蓝牙权限< uses-permission android:name=" ...

  7. android蓝牙协议,Android蓝牙协议-蓝牙扫描 startDiscovery

    蓝牙开启位于setting中,即 package:com.android.settings.bluetooth BluetoothSettings.java 中. 菜单选项MENU_ID_SCAN: ...

  8. Andriod AOA协议通信总结

    Andriod AOA协议通信总结 Android从3.1版本可开始引进了对 AOA协议 ( Android Open Accessory Protocol) 的支持,这是一种允许外部USB硬件与An ...

  9. 【Android RTMP】Android Camera 视频数据采集预览 ( 图像传感器方向设置 | Camera 使用流程 | 动态权限申请 )

    文章目录 安卓直播推流专栏博客总结 一. Camera 传感器方向简介 二. Camera 图像传感器横向显示数据 三. Camera 图像传感器纵向显示数据 四. 设置 Camera 预览数据方向 ...

最新文章

  1. c语言返回一个数的任意倍数,几道基础C语言题
  2. 批量复制文件名-修改文件路径小工具
  3. oracle百万级数据导入,用Perl从oracle导出百万级数据到excel
  4. Tomcat执行start文件后有乱码
  5. HashMap的key可以是可变的对象吗???
  6. DVWA教程实践之Brute Force
  7. word 插入公式技巧
  8. 怎么用html创建表格,HTML创建表格
  9. Exp3 免杀原理与实践 20154328 常城
  10. UC刘兰奇极速版制动刷金币
  11. 内存屏障 Memery Barrier
  12. DI高速计数器编码器脉冲计数器PNPNPN输入模块高低电平
  13. JS面向对象/继承/原型链/this指向/call方法
  14. html5单位转换器,液体单位在线换算工具
  15. 安全、智慧是 Oppo 快充技术最新的发展方向
  16. FineReport 填报报表数据自定义提交
  17. 7-1 验证哥德巴赫猜想
  18. 员工与客户之间就是一个微信
  19. 智能车竞赛技术报告 | 全向行进组 - 东北林业大学- 进取号E
  20. Nginx入门与实践

热门文章

  1. 云运维是什么?具体有什么服务内容?
  2. Vue实现拖拽穿梭框功能四种方式
  3. 麒麟服务器系统搭建nfs共享
  4. 按位取反的概念和计算方法
  5. 网络安全入门到精通(总结篇) 最终篇(上)
  6. hiho 1051 : 补提交卡
  7. 5-3中央处理器-数据通路的功能和基本结构
  8. Python概述:C++程序员眼中的Python
  9. 中标麒麟桌面版7.0 u盘安装
  10. 作文总结思维导图怎么画?分享作文类型总结思维导图模板