Добавляйте пользовательские данные во время рекламы с помощью формата AltBeacon

Я изучаю разработку приложений для Android, создавая приложение, которое взаимодействует с физической сетью. Я хочу разместить рекламу на основе спецификации AltBeacon и добавить небольшую полезную нагрузку в виде строки или байтов. Я наткнулся на Beacon.Builder Javadoc, но он написан плохо. Какую функцию я должен использовать из приведенного выше javadoc или есть еще что-то доступное?

Моя цель - рекламировать с помощью моего приложения и передавать определенную строку. Если на другом устройстве установлено мое приложение, оно должно отображать уведомление с этой строкой. Весь мой код был взят из этого.


person potatoPC    schedule 10.12.2017    source источник
comment
Кто-то может найти этот setDataFields, а setExtraDataFields может показаться для размещения дополнительной полезной нагрузки, но они могут хранить только 6 байтов полезной нагрузки или размер Java.   -  person potatoPC    schedule 11.12.2017


Ответы (1)


Стандартные схемы расположения маяков Bluetooth (iBeacon, AltBeacon, Eddystone-UID) предназначены для передачи уникального числового идентификатора, а не строки. (Eddystone-URL является исключением, поскольку он предназначен для передачи закодированной строки URL-адреса.)

Однако, безусловно, можно передать строку, закодированную в передаче маяка. Просто поймите, что у этого есть несколько ограничений:

  1. Количество места ограничено. При передаче радиомаяка доступно только около 20 байтов полезного пространства, что составляет 20 символов при использовании кодировки, такой как ASCII, и, возможно, меньше в зависимости от символов при использовании UTF-8.

  2. Вам нужно определенное количество совпадающих байтов, чтобы определить (с некоторой разумной уверенностью), является ли реклама «вашей» и должна ли вообще быть декодирована как строка. Использование двухбайтового значения соответствия даст вам шанс 1 из 65536 случайно декодировать чей-то еще маяк в виде строки.

  3. Если вы хотите получать и декодировать на iOS, вы не можете использовать iBeacon, потому что для сопоставления должен использоваться 16-байтовый UUID, оставляя два нескольких байта для хранения строки.

Вот пример того, как вы могли бы сделать это, используя модифицированный макет AltBeacon, с первым двухбайтовым совпадающим идентификатором 0x8b9c, используемым, чтобы убедиться, что это ваш маяк, и вторым 18-байтовым идентификатором, используемым для хранения закодированной строки. Фрагмент кода, показывающий передачу строки ASCII длиной не более 18 символов:

public static final Identifier MY_MATCHING_IDENTIFIER = Identifier.fromInt(0x8b9c);
...
mBeaconManager.getBeaconParsers().clear();
BeaconParser customBeaconParser = new BeaconParser().setBeaconLayout("m:2-3=beac,i:4-5,i:6-23,p:24-24,d:25-25");
mBeaconManager.addBeaconParser(customBeaconParser);
String stringToTransmit = "Only 18 chars fit!";
byte[] stringToTransmitAsAsciiBytes = stringToTransmit.getBytes(StandardCharsets.US_ASCII);
Beacon beacon = new Beacon.Builder().setId1(MY_MATCHING_IDENTIFIER.toString())
            .setId2(Identifier.fromBytes(stringToTransmitAsAsciiBytes, 0, 18, false).toString())
            .setTxPower(-59).build();
mBeaconTransmitter = new BeaconTransmitter(this, customBeaconParser);
mBeaconTransmitter.startAdvertising(beacon);

А вот и получаю:

@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
    for (Beacon beacon : beacons) {
        if (beacon.getId1().equals(MY_MATCHING_IDENTIFIER)) {
            byte[] bytes = beacon.getId2().toByteArray();
            String receivedString = null;
            try {
                receivedString = new String(bytes, 0, bytes.length, "ASCII");
            } catch (UnsupportedEncodingException e) {
                Log.d(TAG, "Cannot decode ASII");
            }
            Log.d(TAG, "I just received: "+receivedString);
        }
    }
}

РЕДАКТИРОВАТЬ: Убедитесь, что вы очистили парсеры маяков, как показано выше, иначе ваш код попытается использовать синтаксический анализатор маяков по умолчанию. См. Изменения кода выше.

person davidgyoung    schedule 10.12.2017
comment
Таким образом, если я использую хеш MD5 и вместо 32 символов я управляю 16 символами, я могу добиться этого с большей точностью, давая мне еще два байта в качестве уникальных начальных байтов. Еще больше затрудняет получение повторяющегося совпадения. Тогда вероятность будет 1 из 256 ^ 4. Это правильно - person potatoPC; 10.12.2017
comment
@davidyoung нет метода clearBeaconParsers в BeaconManager. Пожалуйста, проверьте документы altbeacon.github.io/android-beacon-library/ javadoc / index.html - person potatoPC; 12.12.2017
comment
Извините, используйте: mBeaconManager.getBeaconParsers().clear(); Я использовал экспериментальный API V3, который использует новый синтаксис, показанный ранее. Я обновил свой ответ. - person davidgyoung; 12.12.2017