转载请注明出处:http://blog.csdn.net/zrf1335348191/article/details/50995466
Android4.42-Settings源码分析之蓝牙模块Bluetooth(上)
Android4.42-Setting源码分析之蓝牙模块Bluetooth(下)
ONE,SWITCH蓝牙开关
switch从创建到动作状态监听过程如下
- 创建switch实例
- 将实例添加到actionbar
- 通过构造方法将switch实例传递给BluetoothEnabler实例
- 在fragment中调用添加菜单的方法
- 在onResume方法中对BluetoothEnabler的实例调用resume方法
以上一系列的代码都是在BluetoothSettings.Java中完成,接下来就是在BluetoothEnabler.java中进行处理
- 判断蓝牙是否可用,不可用就把switch设置成不可点击
- 根据本地蓝牙状态来更新switch状态
- 注册过滤BluetoothAdapter.ACTION_STATE_CHANGE的广播,当蓝牙状态发生变化时更新switch状态
- 为switch添加监听事件,更改本地蓝牙适配器,当本地蓝牙适配器发生改变后更新switch状态
总结,switch相关的逻辑实现就这些,在BluetoothSettings中创建switch实例,在BluetoothEnabler.java中对switch的状态监听及更新,查看代码不难发现BluetoothEnabler.java类中是专门对switch进行处理的类。
TWO,本地蓝牙相关
- 创建本地蓝牙的preference
- 显示到屏幕
- 构造BluetoothDiscoverableEnabler的实例对mMyDevicePreference的副标题summary进行显示更新
以上代码是在BluetoothSettings中完成,preference包括title--蓝牙名称、summary---蓝牙可检测性的更新
蓝牙名称--title的更新过程在BluetoothSettings.java中完成,过程如下
- 获取到本机蓝牙名称
- 对蓝牙进行重命名操作时弹出对话框进行处理
在BluetoothNameDialogFragment.java中监听对话框中的编辑框,如果被编辑就修改本地蓝牙的名称,该类专用于为本机蓝牙重命名,
在当前的activity弹出对话框消失后程序不会执行onResume方法,所以在BluetoothSettings.java中注册广播
- 当本地蓝牙名称改变后会发送BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED的广播,BluetoothSettings.java监听到广播后对mMyDevicePreference的title进行更新
蓝牙可检测性---summary的更新显示
对于summary的显示更新的操作在BluetoothDiscoverableEnabler.java中完成,该类专用于更新summary以及处理mMyDevicePreference的点击事件
- 注册广播监听蓝牙扫描状态的改变,当蓝牙扫描状态发生改变时会发送BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE广播,对summary进行更新显示,调用第三步的方法
- 为preference设置点击监听,更改扫描状态
- 根据本地蓝牙的扫描状态来显示summary
在显示summary时有两种情况,
i>,如果本地蓝牙既可以扫描又可以被检测到即处于SCAN_MODE_CONNECTABLE_DISCOVERABLE状态时,则根据可检测性时间的长短来显示,显示内容为:附近所有设备可以检测到+timeout
ii>,如果是别的状态,则要根据是否已经有已配对的设备进行显示,显示为“已配对设备可见”或者是“对所有设备不可见”
既然说到了可检测性,直接说一说可检测时间,在程序启动时注册了广播BluetoothDiscoverableTimeoutReceiver,当可检测时间结束后就会将蓝牙的扫描状态设置为BluetoothAdapter.SCAN_MODE_CONNECTABLE,即取消对所有设备的可检测性
当设定了可检测性为固定的一段时间后则会设置一个闹钟,用于触发广播,当所规定的时间到达时会触发广播,将手机蓝牙的可检测性关闭,如果想要永久的可以被检测到,则只需讲闹钟取消掉,不再触发广播即可
对于可检测性时间到达时对蓝牙可检测性的设置在BluetoothDiscoverableTimeoutReceiver.java中,该类为广播组件,专门用于开启或者关闭可检测性的闹钟计时、关闭可检测性。
THREE,设备列表相关
添加已配对设别列表
- 创建PreferenceCategory类型可配对设备列表对象mPairedDevicesCategory
- 添加可配对设备列表mPairedDevicesCategory
- 调用如下方法将可配对设备列表传递给DeviceListPreferenceFragment进行管理
以上代码在BluetoothSettings中完成,接下来在DeviceListPreferenceFragment中对列表进行管理
- 获取到设备缓存列表,该列表中存放已配对设设备和未配对设备,在程序安装成功后会通过BluetoothAdapter的getBondedDevices方法读取到已配对设备保存到缓存列表中
- 为列表添加已配对的设备,所添加的对象为BluetoothDevicePreference构造的preference,也就是说单个设备的preference的管理在BluetoothDevicePreference中
添加附近可用设备列表
- 点击扫描附近可用设备
- 将附近可用设备列表显示到屏幕
- 扫描到设备后缓存到缓存列表,然后显示到附近可用设备列表
- 若附近可用设备列表为空,则移除
设备的点击事件在BluetoothDevicePreference中处理,设备状态不同则动作不同:如果是已配对设备则点击后就进行连接,如果是为配对的设备点击后进行配对,如果是已连接的设备点击后断开连接。
ONE,传统蓝牙
- BluetoothAdapter:本地蓝牙设备适配器,用于管理蓝牙的开启/关闭、重命名、扫描、配对、连接
- BluetoothClass:蓝牙设备类,用于描述蓝牙设备类型
- BluetoothDevice:远程蓝牙设备类
- BluetoothSocket:与tcpSocket类似,进行蓝牙连接
- BluetoothServerSocket:与tcpServerSocket类似,等待连接
获取本地蓝牙适配器
打开/关闭本地蓝牙
通过监听BluetoothAdapter.ACTION_STATE_CHANGED监听蓝牙状态的改变
通过监听BluetoothAdpater.ACTION_LOCAL_NAME_CHANGED监听本机蓝牙名称的改变
有两种方案,
首先第一种实现,简单但对可检测时间有限制
第二种实现方案,就是Android源码中的实现方案,可以任意规定可检测时长,甚至永不超时均可(参考Android4.42源码)
这是源码中的实现方案,但是BluetoothAdapter.setScanMode()没有办法去调用,只能利用反射
获取已配对设备列表
开启扫描/关闭扫描
在扫描到设备时系统会发送BluetoothDevice.ACTION_FOUND的广播,通过监听该广播可以获取到设备信息
获取到设备后调用如下方式进行连接
获取到socket后可以获取到输入输出流,这里的uuid可以在网页的uuid生成器在线生成,remotedevice和本机蓝牙设备的uuid必须相同
TWO,BLE低功耗蓝牙
获取蓝牙适配器的步骤同上,扫描ble设备的方法如下:
其中mlLeScanCallback为BluetoothAdapter.LeScanCallback对象,
扫描到设备后可以进行连接,方法如下
其中mGattCallback为BluetoothGattCallback对象
连接成功后如果要进行通信还必须搜索服务
搜索服务后会回调onServicesDiscovered方法。
至此,就可以进行读写数据了
关于低功耗蓝牙的理论知识可以参考 Android蓝牙BLE低功耗相关简单总结