由android ble浅谈服务类SDK设计思路

不喜欢把一些简单的东西说成架构,在我心中架构是很大的一个东西,所以下面说SDK,就不说架构这么玄乎,就叫结构好了。

本文分两部分,头半篇是讲android ble的结构的,对ble不感兴趣的可以直接看下半篇。

android ble接口的结构

android的蓝牙接口是通过系统服务提供的,这个服务是系统服务,如果root 手机会在/system/app里面会看到,类似Bluetooth.apk这样的APK。


既然是服务,又是通过APK方式提供的,必然就是通过AIDL方式调用的了。
所以,蓝牙里面那么多的类,虽然看起来都是业务的类,其实都只是个Wrapper,主要就是封装AIDL调用。

BLE涉及的几个类

BluetoothDevice

其实看定义extends Parcelable就知道,这个所谓的Device,并不是真的device,就是个数据对象而已,内部持有了MacAddress和DeviceName(都是String)。


BluetoothDevice.class

可以通过connect接口+macAddress拿到BluetoothGatt对象,这是一个Ble通讯对象,下面会介绍。

connect函数
connect函数具体实现
BluetoothGatt

可以用来通讯的BLE对象,跟BluetoothDevice略有不同。它是一个Wrapper,可以理解为一个句柄,不是纯数据对象,且持有了callback(所以肯定不能串行化,无法在Activity之间传递,这点很重要)。
这个类主要干了两个事
1.从BluetoothService申请一个ID,以后通过这个ID访问的蓝牙设备都是BluetoothDevice.connect参数MacAddress的蓝牙设备

申请ID并绑定到指定的MacAddress

2.注册一个远程callback,以便从BluetoothService接受BLE回调,并且转换为对外部传参BluetoothGattCallback的回调(看下图)

注册远程回调到远程Service
远程转本地的回调

Ble API结构特点

系统Ble接口这么设计必然是有原因的,主要是因为系统的蓝牙服务是共享的,那么相应的BLE外设的状态(特别这点)、数据发送,对系统所有的APP是应该是共享的。

因此,它的所有类几乎都是个Wrapper。因为BluetoothGatt是一个句柄,是无状态的,要查BluetoothGatt是否连上,只能通过注册到BluetoothGatt的callback得到的通知来存下来,或者通过BluetoothManager(一个连接到BluetoothService的Wrapper)。

BluetoothGatt.class

小结

通过远程服务提供共享,中心化对象管理。通过Manager单例管理设备对象,设备对象全是无状态的Wrapper(可对同一MacAddress创建N个对象都不会冲突)。

最不好用的地方

BluetoothGatt不能串行化,无法在Activity间传递,当基于BluetoothGatt包装自定义的协议设备的时候,一是无法在Activity间传递,二是传递副本导致不同页面得到对象最终不是一个状态,如果不想对同一地址自定义设备创建N个,就得想办法做成静态全局的了。另外,BluetoothGatt无状态导致查询状态不直观太方便。

硬件/服务类SDK设计思路

主要分为单例方式和Manager方式。
单例方式又分为纯单例模式,纯Service模式,单例Wrapper+Service方式
Manager方式分为纯Manager方式,Manager+Service方式

名词都是自己发明的,可能不是学名,明白意思就好了:)

纯单例模式

最简单的方式了,所有业务都在一个单例实现。比如我要实现一个录音APP,
就写一个Recorder单例持有系统的AudioRecord。在App各个Activity之间可以操作。

有人会说了,为什么要写成单例这么复杂,直接用AudioRecord不就行了。

假如我在A的Activity启动了录音,在B Activity想操作录音相关的,由于AudioRecord不可跨页面传递(实际上即使可通过Intent传递,也是副本,不是引用),A和B页面之间的操作是无法共享状态的。

纯单例模式优点是足够简单,缺点是无法同时存在多个业务对象,没有生命周期管理。
这种方式在iOS平台的很多接口也有体现。

纯Service模式

跟单例模式一样,但是实现体是Local Service,还是上面录音APP的例子,对录音的封装就可以做成一个Service,需要用的Activity就Bind Service就可以了。
纯Service模式优点是系统会进行生命周期管理,很android的一种思路。缺点跟纯单例一样,无法同时存在多个业务对象。

单例Wrapper+Service方式

这种模式的Service一般用Remote Service方式多,如果没有多APP数据共享的需求用Local Service也可以。单例Wrapper本质上就是帮用户封装了对Service的远程调用。
比如 小米的支付SDK,集成的时候assets会放一个它的Service APK,如果用户没装过Service则会提示用户安装,如果装过了,就跟别的APP共享一个用户账号。

小米支付SDK的文档

从调用的示例代码来看,很明显就是单例。注意它那里的数据Bundle,这个是可以序列化的,可以用AIDL传给远程Service。

小米SDK调用代码

纯Manager方式

这种方式其实很少用,如果是自己的APP,可以直接用Manager+Service方式,不过有些特殊的场景不得不这样设计。
比如 某种设备,假设叫XDevice,XDevice有状态,有缓存。当做成SDK给别人开发的时候,XDevice无法在页面传递了(传递副本也是无意义的),一般人也无法忍受很复杂的调用。

解决办法就是定义一个XDeviceManager单例,内含一个HashMap<Handler, XDevice>。通过它用设备句柄获取到XDevice,在页面间传递的时候就传递设备句柄,对于同一个句柄永远返回同一个XDevice对象。

其实全是静态全局的套路:(

Manager+Service方式

跟纯Manager方式类似,但是区别在于业务实际都是Service实现的,ManagerDevice都是Wrapper,同样的道理,如果要多App数据共享,就用远程Service,要求用户安装一个独立服务的APK。
其实系统的BLE就是类似这样的一个接口(不完全一致)。举例子?嗯,看图。

微软Band SDK
微软Android SDK

获取流就是Manager=>Info=>Client,但是它们其实还是Wrapper,有兴趣可以反编译看看。。。

总得来说Manager方式适用于有多个业务对象的情况,其余的思路跟单例方式是一样的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,016评论 25 707
  • 最近刚从旧公司离职,为面试在做准备,因为平时开发CV大法用得比较多,很多基础知识掌握得不是很牢靠以及很多工具框架只...
    黎清海阅读 2,180评论 1 19
  • 太阳公公 你知道我在思虑什么吗! 我告诉你吧 我在祈祷夏日的过去 期望秋日快到来 以便 我乘风飘行 离开大地妈妈
    夏霖捷阅读 155评论 0 0
  • 想到这个题目的时候,冷笑了两声,扪心自问,你是吗? 听过这么一个说法:有的人死了葬在墓碑下,有的人活着却成...
    sum7mers阅读 697评论 0 0
  • 一年一度的七夕就要到了,作为中国自己的情人节,七夕可是发狗粮的大好机会。都说孩子上辈子是父母的情人,准爸爸、孕妈妈...
    想不到吧_b182阅读 250评论 0 1