android中Bluetooth属性获取代码分析
来源:互联网 发布:海马模拟器有mac版 编辑:程序博客网 时间:2024/05/20 22:00
1 Bluetooth属性获取流程
在BluetoothAdapterProperties.java中,有一个Map类型的变量:mPropertiesMap,该变量中就保存着当前运行中蓝牙的所有的属性值。所有需要读取当前蓝牙属性的地方都需要从该变量中获得。而该变量的值有两种获得方法,一个是直接从Kernel中读取,另外一种是由驱动上报属性值的变动,然后由Framework层进行获取。
1.1属性直接从Kernel读取
在BluetoothAdapterProperties->getAllProperties()中有:
这里既是其获取具体属性的地方,而”GetProperties”则是后续继续调用的地方。不过到了这里,可能会发现,找不到这个函数了,其实这个函数是在蓝牙的底层实现里面,具体的文件位置可能根据android版本的不同而有所不同,我的版本下文件位置在:external\bluetooth\bluez\src\adapter.c里面。
在该文件里有:
既与GetProperties对应的函数实现是:get_properties(),进去看看:
那么,这些属性又是从哪里获取的呢?利用adb shell连上手机,进入/data/misc/bluetoothd,可以看到好多个MAC地址形式的文件夹,随便进入一个文件夹,可以看到里面有很多的配置文件,而那些属性值就是在这里面读取出来的。比如在profiles里面就保存了上次连接过的设备信息,在config里面保存了蓝牙的名称,可否配对等一些信息。
1.2驱动上报属性改变
在BluetoothEventLoop.java中有方法:onPropertyChanged(),对其解释是:
/**
* Called by native code on a PropertyChanged signal from
* org.bluez.Adapter. This method is also called from
* {@link BluetoothAdapterStateMachine} to set the "Pairable"
* property when Bluetooth is enabled.
* @param propValues a string array containing the key and one or more
* values.
*/
既当从org.bluez.Adapter发出了一个PropertyChanged的信号后,native代码就会调用onPropertyChanged()方法。
当获取蓝牙属性不正确时会导致一些问题,而获取蓝牙属性不正确很大的一个原因就是因为蓝牙的MAC地址没有固定,导致每次打开蓝牙时,MAC地址都不同。而在上面我们看到过,每个MAC地址代表的文件里面都储存了蓝牙的相关属性信息,当重新打开蓝牙,MAC地址和上次不同时,就会导致读取不到上次的一些属性信息,从而导致错误。
那么怎么检查MAC地址是不是固定了呢,一个比较简单的方法是连上手机后用ADB SHELL命令进入/data/misc/bluetoothd文件夹观看是否有多个MAC地址形式的文件夹,如果有,则说明MAC地址有可能是不固定的。
其实,还有一个比较简便的方法,通过命令可以看出:
进入/data/misc/bluetoothd下输入命令:hcitool dev 如下:
在BluetoothAdapterProperties.java中,有一个Map类型的变量:mPropertiesMap,该变量中就保存着当前运行中蓝牙的所有的属性值。所有需要读取当前蓝牙属性的地方都需要从该变量中获得。而该变量的值有两种获得方法,一个是直接从Kernel中读取,另外一种是由驱动上报属性值的变动,然后由Framework层进行获取。
1.1属性直接从Kernel读取
在BluetoothAdapterProperties->getAllProperties()中有:
mPropertiesMap.clear(); String properties[] = (String[]) mService .getAdapterPropertiesNative(); //JNI调用从Kernel获得属性值 // The String Array consists of key-value pairs. if (properties == null) { Log.e(TAG, "*Error*: GetAdapterProperties returned NULL"); return; } for (int i = 0; i < properties.length; i++) { String name = properties[i]; String newValue = null; if (name == null) { Log.e(TAG, "Error:Adapter Property at index " + i + " is null"); continue; } if (name.equals("Devices") || name.equals("UUIDs")) { StringBuilder str = new StringBuilder(); int len = Integer.valueOf(properties[++i]); for (int j = 0; j < len; j++) { str.append(properties[++i]); str.append(","); } if (len > 0) { newValue = str.toString(); } } else { newValue = properties[++i]; } mPropertiesMap.put(name, newValue); //将读取的属性值存入mPropertiesMap中 }下面接着来看mService.getAdapterPropertiesNative();调用,这里mService是一个BluetoothService对象,而getAdapterPropertiesNative()是一个Native方法,所以直接跟到其具体实现android_server_bluetoothservice.cpp的getAdapterPropertiesNative()中去,在其代码里有:
reply = dbus_func_args_timeout(env, nat->conn, -1, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "GetProperties", DBUS_TYPE_INVALID);
这里既是其获取具体属性的地方,而”GetProperties”则是后续继续调用的地方。不过到了这里,可能会发现,找不到这个函数了,其实这个函数是在蓝牙的底层实现里面,具体的文件位置可能根据android版本的不同而有所不同,我的版本下文件位置在:external\bluetooth\bluez\src\adapter.c里面。
在该文件里有:
{ "GetProperties", "", "a{sv}",get_properties },
既与GetProperties对应的函数实现是:get_properties(),进去看看:
/* Address */ property = srcaddr; dict_append_entry(&dict, "Address", DBUS_TYPE_STRING, &property); /* Name */ memset(str, 0, sizeof(str)); strncpy(str, (char *) adapter->name, MAX_NAME_LENGTH); property = str; dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &property); /* Class */ dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &adapter->dev_class); /* Powered */ value = (adapter->up && !adapter->off_requested) ? TRUE : FALSE; dict_append_entry(&dict, "Powered", DBUS_TYPE_BOOLEAN, &value); /* Discoverable */ value = adapter->scan_mode & SCAN_INQUIRY ? TRUE : FALSE; dict_append_entry(&dict, "Discoverable", DBUS_TYPE_BOOLEAN, &value); /* Pairable */ dict_append_entry(&dict, "Pairable", DBUS_TYPE_BOOLEAN, &adapter->pairable); /* DiscoverableTimeout */ dict_append_entry(&dict, "DiscoverableTimeout", DBUS_TYPE_UINT32, &adapter->discov_timeout); /* PairableTimeout */ dict_append_entry(&dict, "PairableTimeout", DBUS_TYPE_UINT32, &adapter->pairable_timeout); if (adapter->state == STATE_DISCOV) value = TRUE; else value = FALSE; /* Discovering */ dict_append_entry(&dict, "Discovering", DBUS_TYPE_BOOLEAN, &value); /* Devices */ devices = g_new0(char *, g_slist_length(adapter->devices) + 1); for (i = 0, l = adapter->devices; l; l = l->next, i++) { struct btd_device *dev = l->data; devices[i] = (char *) device_get_path(dev); } dict_append_array(&dict, "Devices", DBUS_TYPE_OBJECT_PATH, &devices, i); g_free(devices); /* UUIDs */ uuids = g_new0(char *, sdp_list_len(adapter->services) + 1); for (i = 0, list = adapter->services; list; list = list->next) { sdp_record_t *rec = list->data; char *uuid; uuid = bt_uuid2string(&rec->svclass); if (uuid) uuids[i++] = uuid; }可以看到,这里就是蓝牙获取具体属性的地方了。其中Name代表了蓝牙的名称,Discoverable代表了是否可以被发现,Powered代表了是否是打开状态,Devices代表了上次成功配对的设备,UUIDs代表了上次配对的蓝牙支持的一些协议等。
那么,这些属性又是从哪里获取的呢?利用adb shell连上手机,进入/data/misc/bluetoothd,可以看到好多个MAC地址形式的文件夹,随便进入一个文件夹,可以看到里面有很多的配置文件,而那些属性值就是在这里面读取出来的。比如在profiles里面就保存了上次连接过的设备信息,在config里面保存了蓝牙的名称,可否配对等一些信息。
1.2驱动上报属性改变
在BluetoothEventLoop.java中有方法:onPropertyChanged(),对其解释是:
/**
* Called by native code on a PropertyChanged signal from
* org.bluez.Adapter. This method is also called from
* {@link BluetoothAdapterStateMachine} to set the "Pairable"
* property when Bluetooth is enabled.
* @param propValues a string array containing the key and one or more
* values.
*/
既当从org.bluez.Adapter发出了一个PropertyChanged的信号后,native代码就会调用onPropertyChanged()方法。
if (name.equals("Name")) { . } else if (name.equals("Pairable") || name.equals("Discoverable")) { . . } else if (name.equals("Discovering")) { . } else if (name.equals("Devices") || name.equals("UUIDs")) { String value = null; int len = Integer.valueOf(propValues[1]); if (len > 0) { StringBuilder str = new StringBuilder(); for (int i = 2; i < propValues.length; i++) { str.append(propValues[i]); str.append(","); } value = str.toString(); } String adapterObjectPath = adapterProperties.getObjectPath(); if ((value != null) && name.equals("UUIDs")) { adapterProperties.setProperty(name, value); updateBTState(value); } else if ((value != null) && (value.startsWith(adapterObjectPath))) { // Devices Prop expect value starts with obj path adapterProperties.setProperty(name, value); } } else if (name.equals("Powered")) {mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED, propValues[1].equals("true") ? new Boolean(true) : new Boolean(false)); } else if (name.equals("DiscoverableTimeout")) { adapterProperties.setProperty(name, propValues[1]); } else if (name.equals("Class")) { adapterProperties.setProperty(name, propValues[1]); }可以看到,当蓝牙的属性值有了改变以后,就会立即反映到BluetoothAdapterProperties.java的变量mPropertiesMap中去,同时会发送相应的事件广播,来通知关注该属性改变的程序。
当获取蓝牙属性不正确时会导致一些问题,而获取蓝牙属性不正确很大的一个原因就是因为蓝牙的MAC地址没有固定,导致每次打开蓝牙时,MAC地址都不同。而在上面我们看到过,每个MAC地址代表的文件里面都储存了蓝牙的相关属性信息,当重新打开蓝牙,MAC地址和上次不同时,就会导致读取不到上次的一些属性信息,从而导致错误。
那么怎么检查MAC地址是不是固定了呢,一个比较简单的方法是连上手机后用ADB SHELL命令进入/data/misc/bluetoothd文件夹观看是否有多个MAC地址形式的文件夹,如果有,则说明MAC地址有可能是不固定的。
其实,还有一个比较简便的方法,通过命令可以看出:
进入/data/misc/bluetoothd下输入命令:hcitool dev 如下:
root@android:/data/misc/bluetoothd # hcitool devhcitool devDevices: hci0 00:A0:C6:45:86:75hci0后面跟的就是当前蓝牙的MAC地址,然后关闭蓝牙,再打开,再执行一次上面的命令,看蓝牙地址是否一样,如不一样,则说明MAC地址是没有固定的,那用工具将其地址写好就可以了。
- android中Bluetooth属性获取代码分析
- android 4.3 Bluetooth 代码
- android bluetooth分析
- android c和java代码中获取配置属性
- Android-如何在代码中获取attr属性的值
- Android如何在代码中获取attr属性的值
- Android,如何在代码中获取attr属性的值
- Android,如何在代码中获取attr属性的值
- 浅谈Android 中BlueTooth
- Android Bluetooth 分析(精)
- Android Bluetooth 分析(精)
- 4.3 android bluetooth hfp分析
- android 4.4 bluetooth 启动分析
- android中layout_weight属性分析
- Android-C代码获取系统属性
- Android中bluetooth的架构
- Android中bluetooth的架构
- Android中bluetooth的架构
- 并行作业类型
- eclipse和myeclipse快捷键大全
- 解决sqllite的'unable to open database file'错误
- 2 Java学习之 集合框架
- Android内核剖析读书笔记(1)—Framework概述
- android中Bluetooth属性获取代码分析
- LINUX下如何判断CPU和系统是32位还是64位
- CH2 The Graphics Rendering Pipeline —— Real-time Rendering
- android gradle 配置 build.gradle
- hadoop的ssh无密码登陆
- HTM_前期准备
- Spring3.2 MVC框架页面跳转及返回JSON内容
- 2009-07-24 14:17 PERL 语言中的q,qw,qr,qx,qq (zz
- 昨日数学实验