首页 > 其他分享 >Android BLE 广播定制

Android BLE 广播定制

时间:2023-03-22 14:55:20浏览次数:43  
标签:定制 bytes key1 蓝牙 key2 BLE Android byte name

近期项目中用到蓝牙BLE,需要区分设备及显示蓝牙名。对于蓝牙BLE广播,发送字节数超过31会广播失败(原因之一是蓝牙名称太长),再者蓝牙mac地址是动态的无法区分设备。和同事交流后,采用他的项目中的方法。

名称太长问题

  1. 广播时,不添加Service UUID,采用2个字节表示服务。
  2. 蓝牙名字符长度超过10则截取前十个字符,并发送表示名称不完整的字节。

设备唯一性

随机两个数字保存在本地,广播时作为设备码(占用2个字节)发送。

代码实现

广播数据部分

    private AdvertiseData buildAdvertiseData(boolean includeDeviceName) {
        
        SharedPreferences sharedPreferences = mContext.getSharedPreferences("config_ble", Context.MODE_PRIVATE);
        int key1 = sharedPreferences.getInt("key1", 0);
        int key2 = sharedPreferences.getInt("key2", 0);
        if (key1 == 0 || key2 == 0) {
            Random random = new Random();
            key1 = 10 + random.nextInt(89);
            key2 = 10 + random.nextInt(89);
            sharedPreferences.edit().putInt("key1", key1).putInt("key2", key2).apply();
        }
        String name = mBluetoothAdapter.getName();
        boolean isFullName = true;
        int maxNameLength = 10;
        if (TextUtils.isEmpty(name)) {
            name = String.format("BLE-%s%s", key1, key2);
        } else {
            if (name.length() > maxNameLength) {
                name = name.substring(0, maxNameLength);
                isFullName = false;
            }
        }
        byte[] bytes = name.getBytes(StandardCharsets.UTF_8);
        byte[] nameBytes = new byte[bytes.length + 1];
        nameBytes[0] = (byte) (isFullName ? 1 : 0);
        System.arraycopy(bytes, 0, nameBytes, 1, bytes.length);
        String realName = isFullName ? name : (name + "...");
        return
                new AdvertiseData.Builder()
                .setIncludeDeviceName(false) //包含蓝牙名称,不能传送名字(太长超过31字节),会广播不成功
                .addManufacturerData(0, new byte[]{0x6A, 0x7E}) //标识该服务
                .addManufacturerData(1, new byte[]{(byte) key1, (byte) key2})//设备码
                .addManufacturerData(2, nameBytes)//蓝牙名
                .build();
    }

蓝牙扫描过滤

    private fun buildScanFilter(): List<ScanFilter> {
        val scanFilters = ArrayList<ScanFilter>()
        val filter = ScanFilter.Builder()
            .setManufacturerData(0, new byte[]{0x6A, 0x7E})
            .build()
        scanFilters.add(filter)
        return scanFilters
    }

蓝牙数据ScanResult解析

        val scanRecord = scanResult?.scanRecord
        val deviceCode: Int =
            scanRecord?.getManufacturerSpecificData(1)?.let { 100 * it[0] + it[1] } ?: 0
        val deviceName = scanRecord?.getManufacturerSpecificData(2)?.let { bytes ->
            val name = String(bytes.sliceArray(1 until bytes.size))
            if (bytes[0].toInt() == 0) {
                "$name..."
            } else {
                name
            }
        } ?: "null"

标签:定制,bytes,key1,蓝牙,key2,BLE,Android,byte,name
From: https://www.cnblogs.com/xunevermore/p/17243939.html

相关文章

  • IHome主页 - 定制你的浏览器主页
    IHome主页是一个功能强大的定制化浏览器主页,它提供了许多优点和功能,可以帮助用户更轻松地管理他们的网上活动。以下是一些IHome主页的主要特点:笔记功能:IHome主页让用户可以......
  • IHome主页 - 定制你的浏览器主页
    IHome主页是一个功能强大的定制化浏览器主页,它提供了许多优点和功能,可以帮助用户更轻松地管理他们的网上活动。以下是一些IHome主页的主要特点:笔记功能:IHome主页让用户可......
  • APP脱壳与反编译之Android Hook
    实验环境1.安装安卓模拟器 2,安装miniconda3,安装fridapipinstallfridapipinstallfridafrida-tools-ihttps://pypi.mirrors.ustc.edu.cn/simple/frida--ve......
  • Unable to cast object of type in System.DirectoryServices.AccountManagement.Grou
    在使用​​UserPrincipal.Current.ToString()​​获取域登录用户信息时,本地调试没有问题,上传到服务器报错Unabletocastobjectoftype'System.DirectoryServices.Accoun......
  • 一统天下 flutter - UI: android 底部导航栏
    一统天下flutterhttps://github.com/webabcd/flutter_demo作者webabcd一统天下flutter-UI:android底部导航栏示例如下:lib\ui\navigation_bar.dart/**an......
  • jquery 禁用按钮无效 disabled属性设置无效
    禁用按鈕$(this).prop("disabled",true);啟用按鈕$(this).prop("disabled",false);禁用按鈕$(this).attr("disabled","disabled");啟用按鈕$(this).removeAttr("d......
  • Android 上网流量监控方法
    一.下提供两种方法获取上网流量相关信息。利用TrafficStats(2.2版本以上)TrafficStats类存在好几个查看流量的方法,具体说明参照SDK。getMobileRxByte......
  • android Vibrator使用示例
    使用Vibrator的vibrate()可调节震动时间;cancel()取消震动。<!—震动权限--><uses-permissionandroid:name="android.permission.VIBRATE"/>//振动器实例化privateVibrato......
  • android Activity 转为 View
    Intentintent=newIntent(Activity.this,Activity.class);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//Activity转为ViewWindowactivity=getLocalActivit......
  • android Intent的FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_REORDER_TO_FRONT
    ctivity的两种启动模式:FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_REORDER_TO_FRONT1.如果已经启动了四个Activity:A,B,C和D。在DActivity里,我们要跳到B......