android 4.0 蓝牙分析之一
Code:
// Skip Bluetooth if we have an emulator kernel
223 // TODO: Use a more reliable check to see if this product should
224 // support Bluetooth - see bug 988521
225 if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
226 Slog.i(TAG, "No Bluetooh Service (emulator)");
227 } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
228 Slog.i(TAG, "No Bluetooth Service (factory test)");
229 } else {
230 Slog.i(TAG, "Bluetooth Service");
231 bluetooth = new BluetoothService(context);
232 ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth);
233 bluetooth.initAfterRegistration();
234 bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
235 ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
236 bluetoothA2dp);
237 bluetooth.initAfterA2dpRegistration();
238
239 int airplaneModeOn = Settings.System.getInt(mContentResolver,
240 Settings.System.AIRPLANE_MODE_ON, 0);
241 int bluetoothOn = Settings.Secure.getInt(mContentResolver,
242 Settings.Secure.BLUETOOTH_ON, 0);
243 if (airplaneModeOn == 0 && bluetoothOn != 0) {
244 bluetooth.enable();
245 }
246 }
SystemServer.Java 里,在addService()时
bluetooth = new BluetoothService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth);
bluetooth.initAfterRegistration();
bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
bluetooth.initAfterA2dpRegistration();
addService后,执行了红色initAfterRegistration()方法,该方法里发送了一个消息
mBluetoothState.sendMessage(BluetoothAdapterStateMachine.TURN_HOT),进入BluetoothAdapterStateMachine之后,TURN_HOT的处理有两处,到底是哪一处的处理呢,我们到BluetoothAdapterStateMachine的构造函数里去看,在BluetoothAdapterStateMachine的构造函数里,设置了初始化状态为setInitialState(mPowerOff);因此addService后的TURN_HOT,
进入的是PowerOff里的TURN_HOT。
1.1 蓝牙的状态
这就是蓝牙模块没有初始化的状态,这时候硬件模块是出于没有上电的状态。
1.2 蓝牙的使能
在上层应用中,蓝牙界面类是BluetoothSettins.java,在actionBar上还有一个开关,另外MENU里也有四个菜单项。
实现蓝牙开关逻辑处理的类是BluetoothEnabler.java,当我们打开或关闭开关时,会执行onCheckedChanged()方法,
mLocalAdapter.setBluetoothEnabled(isChecked);
由此可以知道,是通过进程间通信,调用到了BluetoothService.java里的enable(),BluetoothService.java里的enable()里,我们很高兴看到如下代码:
mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
// starts turning on BT module, broadcast this out
broadcastState(BluetoothAdapter.STATE_TURNING_ON);
// this is user request, save the setting
// We will continue turn the BT on all the way to the BluetoothOn state
deferMessage(obtainMessage(TURN_ON_CONTINUE));
Log.e(TAG, "failed to prepare bluetooth, abort turning on");
broadcastState(BluetoothAdapter.STATE_OFF);
上一小节中讲到的蓝牙的状态,透过代码可以看到,是通过transitionTo()方法来切换蓝牙的状态的。
1.3 调用流程
BluetoothEnable.java( onCheckedChanged() ) ------>
LocalBlutoothAdapter.java ( setBluetoothEnable() ) ------>
BluetoothAdapter.java( enable()) ------>
IBluetooth.aidl( enable() ) ------>
BluetoothService.java( enable() ) ------>
BluetoothAdapterStateMachine.java( enableNative() ) ------>
android_server_BluetoothService.cpp
2. 蓝牙的扫描
2.1 蓝牙扫描
蓝牙扫描的流程,结构比较清晰,根据代码,分析打描的流程如下:
2.2 调用流程
LocalBlutoothAdapter.java (startScanning () ) ------>
BluetoothAdapter.java(startDiscovery ()) ------>
IBluetooth.aidl(startDiscovery () ) ------>
BluetoothService.java(startDiscovery () ) ------>
BluetoothAdapterStateMachine.java(startDiscoveryNative () ) ------>
android_server_BluetoothService.cpp
2.3 扫描结果
当扫描到了设备时,在android_server_BluetoothEventLoop.cpp里有一个方法:
static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
if (dbus_message_is_signal(msg,
jobjectArray str_array = NULL;
if (dbus_message_iter_init(msg, &iter)) {
dbus_message_iter_get_basic(&iter, &c_address);
if (dbus_message_iter_next(&iter))
parse_remote_device_properties(env, &iter);
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
这里会有一个标识“DeviceFound”,调用到方法则是 method_onDeviceFound,接下来的处理是
method_onDeviceFound = env->GetMethodID(clazz, "onDeviceFound",
"(Ljava/lang/String;[Ljava/lang/String;)V");
private void addDevice(String address, String[] properties) {
BluetoothDeviceProperties deviceProperties =
mBluetoothService.getDeviceProperties();
deviceProperties.addProperties(address, properties);
2.4 进程间通信
AIDL进程间通信,在BluetoothAdapter.java里,enable()方法如下:
} catch (RemoteException e) {Log.e(TAG, "", e);}
3. 蓝牙的配对与连接
3.1 蓝牙的配对
3.1.1 master
扫描到可用的蓝牙设备后,在BluetoothDevicePreference.java里,点击列表中的某一蓝牙设备,会根据各个设备的bondState,会有不同的流程:
int bondState = mCachedDevice.getBondState();
if (mCachedDevice.isConnected()) {
} else if (bondState == BluetoothDevice.BOND_BONDED) {
} else if (bondState == BluetoothDevice.BOND_NONE) {
即如果已边接,则会断开边接disconnect(profile),如果状态是已配对,则会去连接connect(true),如果状态是NONE,则会先配对pair()。这里配对和连接需要注意的是,
都会进入startPairing(),进一步进入调用到BluetoothServcie.java里的createBond();
3.1.2 slave
被要求配对的一方,在BluetoothPairingRequest.java这个广播里,会接收到来自底层的一个配对请求,接收到BluetoothDevice.ACTION_PAIRING_REQUEST的ACTION,并弹出提示框(BluetoothPairingDialog.java),提示用户配对。
3.1.3 取消配对
在DeviceProfilesSettings.java中,取消配对直接调用unpairDevice,最终会调用到CachedBluetoothDevice.java的unpair()方法,取消配对时,会直接断开连接了,调用disconnect(),取消配对时,也会根据状态,分别做不同的处理
if (state == BluetoothDevice.BOND_BONDING) {
if (state != BluetoothDevice.BOND_NONE) {
final BluetoothDevice dev = mDevice;
final boolean successful = dev.removeBond();
Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null));
Log.v(TAG, "Framework rejected command immediately:REMOVE_BOND " +
3.2 蓝牙的连接
3.3 相关的界面类:
DeviceListPreferenceFragment.java
4. 重命名蓝牙设备
4.1 调用流程
5. 蓝牙可见时间
5.1 调用流程
可被检测到的主要逻辑处理在BluetoothDiscoverableEnabler.java里,这个流程较为简单,直接在BluetoothDiscoverableEnabler.java这个类里调用setEnable(),然后一步一步调用到BluetoothAdapter.java里的mService.setDiscoverableTimeout(timeout),进而调用到BluetoothService.java里的setDiscoverableTimeout()。
6. 接收到的文件
6.1 调用流程
Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
getActivity().sendBroadcast(intent);
这个广播将会被BluetoothOppReceiver.java接收到,进一步跳转到BluetoothOppTransferHistory.java中,列出所有接收到的文件。
Intent in = new Intent(context, BluetoothOppTransferHistory.class);
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND);
in.putExtra(Constants.EXTRA_SHOW_ALL_FILES, true);
接收到的文件功能实现是OPP里实现的,具体在OPP的分析中,会有进一步详细的分析。
7. 界面
蓝牙设置只有两个界面,其他的都是一些 dialog ,menu.。
7.1 蓝牙设置界面
进入蓝牙设置的界面:BluetoothSettings.java
已配对的蓝牙,进入后,可进行重命名,取消配对的界面:DeviceProfilesSettings
android 4.0 蓝牙分析之一相关推荐
- android 4.0 蓝牙分析之二
原址 packages/apps/Settings/src/com/Android/settings/bluetooth/BluetoothSettings.Java onCreateOptionsM ...
- aptx android8,秒杀苹果无线音频!Android 8.0蓝牙音质支持aptxHD/LDAC
原标题:秒杀苹果无线音频!Android 8.0蓝牙音质支持aptxHD/LDAC [TechWeb报道]8月25日消息,本周将迎来Android 8.0"奥利奥"系统推送,目前已 ...
- Android 9.0 蓝牙功能之一:蓝牙音乐
Android 9.0 蓝牙功能之一:蓝牙音乐 本章节记录如何构建蓝牙音乐. 文章目录 Android 9.0 蓝牙功能之一:蓝牙音乐 主要流程 相关代码 其他要点: 蓝牙AG_EVENT广播 (手机 ...
- android 6.0蓝牙服务开启,Android应用开发之Android 6.0 蓝牙搜索不到设备原因,MIUI权限申请机制方法...
本文将带你了解Android应用开发Android 6.0 蓝牙搜索不到设备原因,MIUI权限申请机制方法,希望本文对大家学Android有所帮助. 为提供更高的数据保护 Android6.0版本 ...
- android 6.0 蓝牙进程,Android6.0-蓝牙权限问题
在Android 6.0,原来的蓝牙功能,发现扫描蓝牙设备时,无法获取到蓝牙设备:因为在6.0后,蓝牙这块增加一个动态权限:需要在程序中动态申请. 1) 在6.0版本前,使用蓝牙功能,只 ...
- Android 8.0 蓝牙唤醒 Ble 锁屏 保活 后台 持续扫描 进程拉活 自动唤醒
主要是api的说明,嫌啰嗦的可以直接看demo,demo中有个检测锁屏时间重复开启扫描的代码,主要是如果APP没有获得电量或者后台运行的权限,只能持续后台运行几小时. 这个demo的作用是实现8.0以 ...
- android Ble4.0蓝牙开发之搜索慢、startLeScan()过时,6.0以上不需要定位权限也能快速搜索到蓝牙设备
项目中需要用到android Ble蓝牙4.0开发技术,于是开启了蓝牙填坑之旅,说实话,蓝牙开发坑真多,跳出一个又进入下一个,每次遇到 问题,就觉得不可能解决了,还好在自己的摸索中,都一一的化解了,以 ...
- android 6.0蓝牙,Android 6.0 蓝牙搜索不到设备原因,MIUI权限申请机制方法
为提供更高的数据保护 Android6.0版本上增加了关于Wifi和蓝牙的权限. 蓝牙搜索到设备需要用到定位服务,所以在开发中 targetSdkVersion 大于等于23(6.0) 需要在代码中进 ...
- Android 9.0 蓝牙通讯录 BluetoothPbapClient
蓝牙通讯录主要包含联系人和通话记录 一.BluetoothPbapClient功能介绍 1.主要实现电话簿下载 2.电话号码簿访问协议(Phonebook Access Profile) 二.Blue ...
最新文章
- 注解方式使用 Redis 缓存
- 前端学习(3323):高级设计说闭包
- php 时间戳获取周几,PHP实现根据时间戳获取周几的方法,php戳获取周_PHP教程
- 云原生数据仓库TPC-H第一背后的Laser引擎大揭秘
- 挖漏经验:在密码重置请求包中添加X-Forwarded-Host实现受害者账户完全劫持
- JimuReport积木报表——如何设计一张带二维码的打印报表?
- 楼宇计算机网络是如何工作的,【干货】建筑楼宇智能化如何应用 4C 技术
- mysql sql语句 datediff_MySQL数据库之MySQL DATEDIFF 函数
- C#中的方法(函数),委托和事件
- 苏大计算机技术招生人数,苏大省内招生计划比去年增加86名
- 基于WEB的达内学子书城/商城源代码
- 坐标转换-换带计算(附软件下载)
- utf8字符集中漢字默認占三個字節
- narwal机器人_Narwal云鲸首创“基站+机器人”,智能扫拖干净省心
- Linux攻关之基础模块五 Vim
- 资本并非全部,新家装风口下如何迎风起舞?丨Xtecher 观察
- 牛客练习赛24 B凤 凰(并查集考察)
- 机器阅读理解算法集锦
- 无人驾驶之MATLAB无人驾驶工具箱学习(1)
- 根据url获取文件流MultipartFile
热门文章
- SQL SERVER 锁定的实例
- Linux 管道(pipe)原理及使用
- xcode 4,2 for Mac 10.6.8
- pad点餐系统 内存管理的一点总结
- 【ZooKeeper Notes 5】单机启动多个zk实例注意点
- GPT-J 自然语言处理 AI 模型
- .NET开发框架 ABP
- 基线理解_使用递归神经网络的上下文口语理解论文阅读
- webbrowser控件 加载为空白_OpenLayers教程五:地图控件之坐标拾取控件和鹰眼控件...
- linux上编译sdl,Linux下安装、编译SDL