1. MTK6737平台蓝牙名称修改实战指南
在Android设备开发过程中,定制蓝牙名称是一个常见需求。MTK6737作为联发科的中端芯片方案,其蓝牙模块的命名机制与原生Android存在一些差异。本文将基于Q版本系统源码,详细解析如何通过修改系统层代码实现蓝牙名称的永久定制。
1.1 蓝牙名称的底层存储机制
Android系统的蓝牙名称默认存储在以下两个位置:
- Settings数据库:用户通过设置界面修改的蓝牙名称会保存在Settings.Global.BLUETOOTH_NAME中
- 系统属性:部分厂商实现会额外将名称保存在persist.bluetooth.name等属性中
MTK平台的特殊性在于:
- 默认会优先读取persist.sys.bluetooth.name系统属性
- 如果该属性为空,则回退到Settings数据库的值
- 在蓝牙服务启动时,会通过AdapterProperties.java进行初始化
1.2 关键代码文件定位
需要修改的核心文件位于:
code复制vendor/mediatek/proprietary/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
这个文件控制着蓝牙适配器属性的初始化流程,包括名称、扫描模式、可见性等参数的设置。
2. 蓝牙名称修改方案实现
2.1 直接硬编码方案
原始代码中提供的方案是在两个关键位置插入名称设置代码:
java复制// 位置1:init()方法中
public void init(RemoteDevices remoteDevices) {
// ...原有代码...
setName("MTR M17 Plus"); // 强制设置名称
// ...原有代码...
}
// 位置2:onBluetoothReady()方法中
void onBluetoothReady() {
// ...原有代码...
String currentName = getName();
if (!"MTR M17 Plus".equals(currentName)) {
boolean result = setName("MTR M17 Plus");
Log.i(TAG, "Set Bluetooth name result: " + result);
}
// ...原有代码...
}
这种方案的优缺点:
- 优点:修改简单直接,名称固定无法被用户修改
- 缺点:需要重新编译系统镜像,名称变更不灵活
2.2 进阶方案:通过系统属性控制
更优雅的实现方式是读取系统属性:
java复制// 修改init()方法
public void init(RemoteDevices remoteDevices) {
// ...原有代码...
String btName = SystemProperties.get("persist.sys.bt.default_name", "MTR M17 Plus");
setName(btName);
// ...原有代码...
}
// 修改onBluetoothReady()方法
void onBluetoothReady() {
// ...原有代码...
String defaultName = SystemProperties.get("persist.sys.bt.default_name", "MTR M17 Plus");
if (!defaultName.equals(getName())) {
setName(defaultName);
}
// ...原有代码...
}
配套需要添加系统属性定义:
code复制# device/mediatek/mt6737/init.project.rc
on boot
setprop persist.sys.bt.default_name "MTR M17 Plus"
这种方案的改进点:
- 名称可通过adb命令动态修改:
bash复制adb shell setprop persist.sys.bt.default_name "NewDeviceName" - 保持与MTK原有架构的一致性
- 便于产线批量烧录时灵活配置
3. 实现原理深度解析
3.1 蓝牙名称设置调用链
完整的名称设置流程涉及多个层次:
- HAL层:通过bluetooth.default.so与蓝牙芯片通信
- Framework层:BluetoothAdapterService处理跨进程调用
- JNI层:com_android_bluetooth_btservice_AdapterService.cpp
- App层:Bluetooth应用包管理用户界面
关键调用关系:
code复制setName() -> BluetoothAdapterService.setName() ->
AdapterService.setNameNative() -> HAL_set_property()
3.2 MTK平台的特殊处理
MT6737芯片的蓝牙协议栈采用组合方案:
- 基础协议栈使用Android开源代码
- 射频控制使用MTK闭源库(libbluetooth_mtk.so)
- 名称设置需要同步到NVRAM区域
因此仅修改Java层代码可能在某些情况下失效,需要确保:
- NVRAM分区有写入权限
- 修改后执行
adb shell sync确保写入持久化 - 部分机型需要重启蓝牙服务:
bash复制
adb shell am broadcast -a android.bluetooth.adapter.action.STATE_CHANGED
4. 常见问题与调试技巧
4.1 修改无效排查步骤
当名称修改未生效时,建议按以下流程排查:
- 确认修改的代码确实被编译:
bash复制grep -r "setName(" out/target/product/xxx/system/priv-app/Bluetooth/Bluetooth.apk - 检查系统属性值:
bash复制
adb shell getprop persist.sys.bt.default_name - 查看蓝牙服务日志:
bash复制
adb logcat | grep -i bluetooth - 验证NVRAM存储:
bash复制adb shell cat /proc/nvram/BT_Addr
4.2 厂商定制兼容处理
不同厂商可能对蓝牙模块有二次开发,需要注意:
- ODM厂商可能重写AdapterProperties类
- 系统签名问题可能导致权限不足
- 双模蓝牙(BT+BLE)需要分别设置名称
推荐兼容性处理方式:
java复制try {
Class<?> clazz = Class.forName("com.mediatek.bluetooth.BleNameManager");
Method method = clazz.getMethod("setBleName", String.class);
method.invoke(null, "MTR M17 Plus");
} catch (Exception e) {
Log.w(TAG, "BleNameManager not found, skip BLE name setting");
}
5. 生产环境优化建议
5.1 产线批量烧录方案
对于量产设备,建议采用以下流程:
- 在device.mk中配置默认名称:
makefile复制PRODUCT_PROPERTY_OVERRIDES += \ persist.sys.bt.default_name=$(TARGET_BT_DEFAULT_NAME) - 使用PCBA工具预烧录MAC地址和名称:
bash复制mtk_bt_init_tool -n "MTR M17 Plus" -m 11:22:33:44:55:66 - 在首次开机脚本中校验:
bash复制if [ -z "$(getprop persist.sys.bt.default_name)" ]; then setprop persist.sys.bt.default_name "MTR M17 Plus" fi
5.2 动态名称更新机制
实现名称可配置化的进阶方案:
- 添加SettingsProvider配置项:
xml复制<bluetooth_default_name>MTR M17 Plus</bluetooth_default_name> - 监听属性变化:
java复制SystemProperties.addChangeCallback(() -> { String newName = SystemProperties.get("persist.sys.bt.default_name"); if (!newName.equals(getName())) { setName(newName); } }); - 提供厂商API接口:
java复制public void setBluetoothDefaultName(String name) { SystemProperties.set("persist.sys.bt.default_name", name); }
通过这种实现,可以做到:
- 出厂默认名称可配置
- 支持售后OTA修改名称策略
- 满足不同地区法规要求(如必须包含型号信息)
6. 技术细节注意事项
-
名称长度限制:
- 经典蓝牙:248字节(UTF-8编码)
- BLE:31字节(UTF-8编码)
- 实际显示可能受对方设备限制
-
特殊字符处理:
java复制// 建议增加过滤逻辑 name = name.replaceAll("[^a-zA-Z0-9 _-]", ""); -
多语言支持:
java复制// 从资源文件读取 String defaultName = getResources().getString(R.string.bt_default_name); -
版本兼容性:
- Android Q之后引入BluetoothDevice.ACTION_NAME_CHANGED广播
- 需要处理名称变更通知:
java复制IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED); registerReceiver(mNameReceiver, filter);
在MTK6737平台上,蓝牙名称的修改看似简单,实则涉及系统架构的多个层次。通过本文介绍的方案,开发者可以灵活实现从基础硬编码到高级动态配置的各种需求场景。建议在实际项目中根据产品定位选择适合的实现方式,并充分测试不同蓝牙协议下的兼容性表现。