Android AOA协议Android端 流程总结
2017-04-25 13:37
1071 查看
源文: 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相关连接。
下面是对应的广播接收者,这里其实只需要监听两个广播,一个是获取usb权限,一旦这个广播发出我们就可以认为设备现在正在启动手机的accessory模式,第一次连接时手机会弹出对话框,让我们选择是否运行usb权限,另外一个就是需要在usb断开时做出反应,告诉设备连接已经断开了。下面是处理广播事件的过程:
mUsbReceiver =new BroadcastReceiver() {
@Override
publicvoid 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表中的设备:
USBHelper 具体操作usb的开关和读写等功能
USBHelper类具体操作usb的功能,这个类中持有USBConnStatusManager的单例对象,有了USBConnStatusManager就可以拿到accessroy,通过USBConnStatusManager获取到读写流,这个类就是在外层调用USBConnStatusManager方法,对usb进行操作。
4000
这个方法用来开启usb,首先注册广播接收者回调,用来检测usb插拔信息,注册完毕后检查当前系统中存在的accessory设备,如果已经连接了accessroy设备,则直接获取其accessroy的引用,通过这个引用获取读写流,者就是usb的打开过程。
另外这个类还提供了usb数据读写和关闭设备等方法,大家可以参考项目源码。
SimpleTcpWrapper 封装上层通信协议
打通底层数据通道,下面就是封装我们自己协议了,在项目中使用tcp头简单封装了一个协议,可以实现三次握手,数据包通过序列号校验以及根据不同端口分发数据的功能。本章只讨论Android设备底层通信的实现,所以删除了协议部分,只是将usb发送过来的数据原样发送回去。
SimpleTcpWrapper中创建一个USBHelper对象用来管理usb数据通信,调用openAsync异步打开数据。一旦数据连接成功,我们就是开启一个数据接收线程,读取这个accessory的inputstream,一旦收到数据就将数据写入accessory的outputstrem中。
上篇文章中我们了解了嵌入式设备端将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() {
@Override
publicvoid 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
4000这个方法用来开启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 usb学习笔记:Android AOA协议设备端 流程总结
- Android usb学习笔记:Android AOA协议Android端 流程总结
- Android_项目上线流程总结
- Android View的事件分发流程总结
- Android知识点总结:Android选取、拍照与裁剪图片相关流程分析
- 将Gsensor lis301 driver 升级到 lis331 driver 过程总结,以及android中Gsensor相关流程
- EasyPusher安卓Android手机直播推送之RTSP流媒体协议流程
- android 休眠唤醒流程及定位唤醒问题总结
- Android Sip学习(准备知识)SIP 协议完整的呼叫流程
- 对Android中集成支付宝支付流程的总结
- Android--Pin流程,飞行模式相关流程总结【工作日记一】
- Android开发流程总结
- android 休眠唤醒流程及定位唤醒问题总结
- (总结篇)Android 牛不牛?决定于自定义View控件(一)——view绘制流程(onMeasure,onLayout,onDraw)
- S5PV210 Android2.3 休眠唤醒流程及定位唤醒问题总结
- android HTTp协议获取数据总结
- 从流程上对rtmp协议经行总结
- 积跬步-至千里系列之二:Android中Activity的启动流程分析和总结