hamibot 如何通过蓝牙名称获取蓝牙的MAC?怎么写?

HAMI_7968096050 · 7 天前
第 1 条补充
·
7 天前

18:23:46.917/E: Wrapped java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission for android.content.AttributionSource@a41f817e App with package name:com.hamibot.hamibot: AdapterService getBondedDevices (69a914acdf4f97a858c6d4b4.js#22)
Wrapped java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission for android.content.AttributionSource@a41f817e App with package name:com.hamibot.hamibot: AdapterService getBondedDevices
at 69a914acdf4f97a858c6d4b4.js:22:0 出错了

第 2 条补充
·
7 天前

不修改 Hamibot APK 权限行不行?能否绕开这个权限获取蓝牙MAC

回答

Hamibot AI
1
· 7 天前

在 Hamibot 脚本中,可以通过调用 Android 原生蓝牙 API 来获取蓝牙设备的 MAC 地址。由于 Android 系统权限限制,你需要确保脚本拥有蓝牙及相关位置权限,并且建议在已配对的设备列表中查找,因为扫描新设备需要异步处理且较为复杂。

以下是实现通过蓝牙名称获取已配对设备 MAC 地址的示例代码:

// 文档地址 https://docs.hamibot.com/

// 请求必要的权限
// 需要蓝牙权限和位置权限(Android 6.0+ 蓝牙扫描需要位置权限)
runtime.requestPermissions(['BLUETOOTH', 'BLUETOOTH_ADMIN', 'ACCESS_FINE_LOCATION']);

// 获取默认的蓝牙适配器
var BluetoothAdapter = android.bluetooth.BluetoothAdapter;
var adapter = BluetoothAdapter.getDefaultAdapter();

// 检查蓝牙是否开启
if (!adapter.isEnabled()) {
    log('蓝牙未开启,尝试开启...');
    // 注意:部分系统可能不允许脚本直接开启蓝牙,需要用户手动确认
    adapter.enable(); 
}

// 获取已配对的设备列表
var bondedDevices = adapter.getBondedDevices();
var targetName = '目标蓝牙名称'; // 替换为你要查找的蓝牙设备名称
var targetMac = null;

// 遍历已配对设备查找匹配项
if (bondedDevices.size() > 0) {
    for (var i = 0; i < bondedDevices.size(); i++) {
        var device = bondedDevices[i];
        var name = device.getName();
        if (name === targetName) {
            targetMac = device.getAddress();
            log('找到设备:' + name + ', MAC 地址:' + targetMac);
            break;
        }
    }
}

if (targetMac) {
    log('获取成功:' + targetMac);
} else {
    log('未找到名为 ' + targetName + ' 的已配对设备');
}

注意事项

  1. 权限要求:脚本运行需要获取 BLUETOOTHBLUETOOTH_ADMIN 以及 ACCESS_FINE_LOCATION 权限。在 Android 6.0 及以上版本,蓝牙扫描和获取信息通常需要位置权限。
  2. 已配对设备:上述代码仅能获取已配对(Bonded)的设备。如果需要扫描周围未配对的设备,需要注册 BroadcastReceiver 监听蓝牙扫描结果,实现较为复杂且耗时。
  3. Android 版本限制:Android 10 及以上版本对 MAC 地址访问有严格限制,可能无法获取真实的 MAC 地址,而是返回随机地址或固定值。
  4. 运行环境:确保脚本在拥有蓝牙硬件的 Android 设备上运行,且 Hamibot 客户端具有相应的系统权限。

如果你需要扫描未配对的设备,建议使用 Android 原生 startDiscovery() 方法配合广播接收器,但这在脚本中实现复杂度较高。对于大多数自动化场景,使用已配对设备列表更为稳定。


补充回答 1

这个错误是因为 Android 12(API 级别 31)及以上版本引入了新的蓝牙权限 BLUETOOTH_CONNECTBLUETOOTH_SCAN。Hamibot 标准版的 Manifest 文件中可能未声明这些新权限,导致脚本调用蓝牙 API 时被系统拦截。

Hamibot 的 runtime.requestPermissions 函数只能申请已在 app Manifest 中声明的权限。标准版 Hamibot 默认只声明了部分常用权限。要解决此问题,你需要修改 Hamibot 应用的 Manifest 文件以增加所需权限。

解决方案

1. 修改 Hamibot APK 权限(必需步骤)

由于 Android 12+ 的限制,你必须通过 APK 编辑器将 BLUETOOTH_CONNECT 权限添加到 Hamibot 应用中:

  1. 备份并卸载当前手机上的 Hamibot 应用。
  2. 使用 APK 编辑器(如 MT 管理器、APK Editor 等)打开 Hamibot 的安装包。
  3. 找到 AndroidManifest.xml 文件。
  4. <manifest> 标签内添加以下权限声明:
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    
  5. 保存并重新签名 APK。
  6. 安装修改后的 Hamibot 应用。

2. 更新脚本代码

修改 APK 后,脚本中需要动态申请这些新权限。以下是适配 Android 12+ 的代码:

// 文档地址 https://docs.hamibot.com/

// 检查 Android 版本以决定申请哪些权限
var sdkInt = android.os.Build.VERSION.SDK_INT;
var permissions = [];

// 基础蓝牙权限
permissions.push('android.permission.BLUETOOTH');
permissions.push('android.permission.BLUETOOTH_ADMIN');

// Android 6.0+ 需要位置权限用于蓝牙扫描
if (sdkInt >= 23) {
    permissions.push('android.permission.ACCESS_FINE_LOCATION');
}

// Android 12+ 需要新的蓝牙连接和扫描权限
if (sdkInt >= 31) {
    permissions.push('android.permission.BLUETOOTH_CONNECT');
    permissions.push('android.permission.BLUETOOTH_SCAN');
}

// 动态申请权限
runtime.requestPermissions(permissions);

// 获取蓝牙适配器
var BluetoothAdapter = android.bluetooth.BluetoothAdapter;
var adapter = BluetoothAdapter.getDefaultAdapter();

if (adapter == null) {
    log('此设备不支持蓝牙');
    return;
}

// 检查蓝牙是否开启
if (!adapter.isEnabled()) {
    log('蓝牙未开启,请手动开启蓝牙后重试');
    // 尝试开启蓝牙,部分系统可能需要用户确认
    // adapter.enable(); 
    return;
}

// 获取已配对的设备列表
var bondedDevices = adapter.getBondedDevices();
var targetName = '目标蓝牙名称'; // 替换为你要查找的蓝牙设备名称
var targetMac = null;

// 遍历已配对设备
if (bondedDevices != null && bondedDevices.size() > 0) {
    for (var i = 0; i < bondedDevices.size(); i++) {
        var device = bondedDevices[i];
        // 注意:getName() 和 getAddress() 在 Android 12+ 也需要 BLUETOOTH_CONNECT 权限
        var name = device.getName();
        if (name != null && name === targetName) {
            targetMac = device.getAddress();
            log('找到设备:' + name + ', MAC 地址:' + targetMac);
            break;
        }
    }
}

if (targetMac) {
    toast('获取成功:' + targetMac);
} else {
    toast('未找到名为 ' + targetName + ' 的已配对设备');
}

注意事项

  1. 权限生效:修改 APK 并重新安装后,首次运行脚本时系统会弹出权限申请对话框,务必点击“允许”。
  2. MAC 地址限制:即使获取成功,Android 10+ 系统为了隐私保护,可能会返回随机 MAC 地址而非硬件真实 MAC 地址,这是系统级限制,脚本无法绕过。
  3. 稳定性:修改 APK 可能导致应用签名验证失败,无法覆盖安装或无法使用云脚本功能,建议仅在本地调试使用。
  4. 已配对设备:代码仅能获取已配对的设备。如果需要扫描未配对设备,逻辑会更复杂且耗电,建议优先使用已配对列表。

如果你无法修改 APK,则在 Android 12 及以上设备上,标准版 Hamibot 可能无法直接通过脚本获取蓝牙 MAC 地址。


补充回答 2

不修改 Hamibot APK 权限,在 Android 12 及以上版本无法通过脚本获取蓝牙 MAC 地址。这是 Android 系统底层的安全限制,无法通过纯脚本代码绕过。

原因分析

  1. 系统权限拦截:Android 12(API 级别 31)引入了新的蓝牙权限模型。访问蓝牙设备信息(包括 MAC 地址、名称、配对列表)必须持有 BLUETOOTH_CONNECT 权限。
  2. Manifest 声明限制:权限必须在应用的 AndroidManifest.xml 中预先声明,才能在运行时申请或使用。Hamibot 标准版安装包未声明该权限,因此即使脚本调用 runtime.requestPermissions,系统也不会授予,且调用相关 API 时会直接抛出 SecurityException
  3. 沙盒机制:脚本运行在 Hamibot 应用的沙盒环境中,权限等级等同于 Hamibot 应用本身。应用没有的权限,脚本无法凭空获得。

替代方案与建议

既然无法直接获取 MAC 地址,建议采用以下替代方案实现你的自动化需求:

1. 使用蓝牙设备名称匹配

大多数自动化场景下,设备名称具有唯一性,足以作为识别标识。

// 文档地址 https://docs.hamibot.com/

var BluetoothAdapter = android.bluetooth.BluetoothAdapter;
var adapter = BluetoothAdapter.getDefaultAdapter();

if (adapter != null && adapter.isEnabled()) {
    var bondedDevices = adapter.getBondedDevices();
    var targetName = '你的蓝牙耳机'; // 替换为目标设备名称
    
    if (bondedDevices != null && bondedDevices.size() > 0) {
        for (var i = 0; i < bondedDevices.size(); i++) {
            var device = bondedDevices[i];
            var name = device.getName();
            if (name != null && name.contains(targetName)) {
                log('找到设备:' + name);
                // 在此处执行后续操作,无需 MAC 地址
                break;
            }
        }
    }
}

2. 确认是否必须使用 MAC 地址

请重新评估业务需求。如果是为了区分设备,设备名称通常足够。如果是为了网络连接,蓝牙连接本身会处理地址映射,脚本通常只需要获取 BluetoothDevice 对象即可进行连接操作,无需显式获取 MAC 字符串。

3. 关于 Root 权限(仅限高级用户)

如果手机已获取 Root 权限,理论上可以通过 shell 命令尝试读取系统底层文件获取蓝牙信息,但这不属于 Hamibot 标准支持范围,且不同手机厂商的系统文件路径不同,稳定性极差。

// 仅作为示例,未 Root 设备无法执行,且路径因厂商而异
// var result = shell("su -c 'ls /sys/class/bluetooth/'", true);

注意:即使有 Root 权限,Android 10+ 系统也对 MAC 地址进行了随机化处理,获取到的可能仍是随机地址而非硬件真实地址。

4. 区分 Wi-Fi MAC 与蓝牙 MAC

Hamibot 提供的 device.getMacAddress() 函数获取的是 WLAN (Wi-Fi) 的 MAC 地址,不是蓝牙 MAC 地址。且该函数需要在有 WLAN 连接的情况下才能返回有效值,无法用于获取蓝牙信息。

总结

在不修改 APK 的前提下,Android 12+ 系统禁止应用获取蓝牙 MAC 地址。建议修改脚本逻辑,使用蓝牙设备名称作为识别依据,这是最稳定且兼容所有 Android 版本的方案。

ℹ️ 本回答由 AI 生成,内容仅供参考