20

dataこれは広告主です (タイプとして渡される通知AdvertiseData)

  private void advertise() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    BluetoothLeAdvertiser advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
    AdvertiseSettings settings = new AdvertiseSettings.Builder()
            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
            .setConnectable(false)
            .build();
    ParcelUuid pUuid = new ParcelUuid(UUID.fromString("cf2c82b6-6a06-403d-b7e6-13934e602664"));
    AdvertiseData data = new AdvertiseData.Builder()
            //.setIncludeDeviceName(true)
            .addServiceUuid(pUuid)
            .addServiceData(pUuid, "123456".getBytes(Charset.forName("UTF-8")))
            .build();
    AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            Log.i(tag, "Advertising onStartSuccess");
            super.onStartSuccess(settingsInEffect);
        }

        @Override
        public void onStartFailure(int errorCode) {
            Log.e(tag, "Advertising onStartFailure: " + errorCode);
            super.onStartFailure(errorCode);
        }
    };
    advertiser.startAdvertising(settings, data, advertiseCallback);
}

無事起動です。

これがスキャナー

 private void discover() {
    ScanSettings settings = new ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
            .build();
    mBluetoothLeScanner.startScan(null, settings, mScanCallback);
}

private ScanCallback mScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        Log.i(tag, "Discovery onScanResult");
        if (result == null) {
            Log.i(tag, "no result");
            return;
        }
        ScanRecord scanRecord = result.getScanRecord();
        List<ParcelUuid> list = scanRecord != null ? scanRecord.getServiceUuids() : null;
        if (list != null) {
            Log.i(tag, scanRecord.toString());
            for (ParcelUuid uuid : list) {
                byte[] data = scanRecord.getServiceData(uuid);
            }
    }

    @Override
    public void onBatchScanResults(List<ScanResult> results) {
        super.onBatchScanResults(results);
        Log.i(tag, "Discovery onBatchScanResults");
    }

    @Override
    public void onScanFailed(int errorCode) {
        super.onScanFailed(errorCode);
        Log.e(tag, "Discovery onScanFailed: " + errorCode);
    }
};

コールバックで、この出力を生成するonScarnResultスキャン レコードをログに記録しますtoString()

 ScanRecord [mAdvertiseFlags=2, 
         mServiceUuids=[cf2c82b6-6a06-403d-b7e6-13934e602664],
         mManufacturerSpecificData={}, 
         mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 51, 52, 53, 54]}, 
         mTxPowerLevel=-2147483648, mDeviceName=null]

残念ながら、uuid は一致します。

  byte[] data = scanRecord.getServiceData(uuid) 

ですnulltoString出力には、アドバタイズされたデータ文字「123456」の ASCII コード、つまり 49,50,51,52,53,54 が含まれていることに気付きました。

 mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 51, 52, 53, 54]}

正しい広告データを受け取りたいのですが、何か問題がありますか?

編集: マニフェストには、bluetooth、bt admin、および場所のアクセス許可があります。3 つ目は、Android 6 で実行時にリクエストを起動します。

編集:scanRecord全体を印刷すると、この出力が得られます

ScanRecord [mAdvertiseFlags=-1, mServiceUuids=[cf2c82b6-6a06-403d-b7e6-13934e602664], mManufacturerSpecificData={}, mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 2, 513, 5 54]}、mTxPowerLevel=-2147483648、mDeviceName=null]

mServiceUuids 配列にある広告主が決めた uuid は、mServiceData に関連付けられたキーが別なので基本的には使えません。このようにコードを変更して、データ マップをナビゲートして値を取得しました (2 つの if ブロックを参照してください)。

   public void onBatchScanResults(List<ScanResult> results) {
        super.onBatchScanResults(results);
        for (ScanResult result : results) {
            ScanRecord scanRecord = result.getScanRecord();
            List<ParcelUuid> uuids = scanRecord.getServiceUuids();
            Map<ParcelUuid, byte[]> map = scanRecord.getServiceData();
            if (uuids != null) {
                for (ParcelUuid uuid : uuids) {
                    byte[] data = scanRecord.getServiceData(uuid);
                    Log.i(tag, uuid + " -> " + data + " contain " + map.containsKey(uuid));
                }
            }

            if (map != null) {
                Set<Map.Entry<ParcelUuid, byte[]>> set = map.entrySet();
                Iterator<Map.Entry<ParcelUuid, byte[]>> iterator = set.iterator();
                while (iterator.hasNext()) {
                    Log.i(tag, new String(iterator.next().getValue()));
                }
            }
        }
    }

実際、ライン

 map.containsKey(uuid)

広告主の uuid がデータ マップで使用されていないため、false を返します。

値を見つけるためにマップをナビゲートする必要がありました (2 番目の if ブロック) が、それが興味のある値であるかどうかを知る手段がありません。いずれにせよ、システムが値を入力した場合、値を取得できませんレシーバーアプリでスキャナーのコードを実行しているときにわからない別のキー。

受信機でこの問題を処理するにはどうすればよいですか? データ フィールドを使用したいのですが、それらを取得するための文字列キーはアプリオリに知られておらず、システムによって決定されます。

4

4 に答える 4