Хочу вам рассказать нашу историю из серии «ожидание и реальность» или о том, как слова товарища М.Ф. Квинтилиана: «Вредить легко, помогать трудно» приобрели для нас новый смысл.
Covid-19. Наверное, каждый слышал об этом вирусе. Я сейчас не берусь описывать свое личное отношение или обсуждать теории заговоров вокруг этого. Лично для меня это реальный кейс с близкими, которые заболели.
Столкнувшись с ковид лицом к лицу, наша команда решила внести свой вклад в борьбу с этим злом.
Мы разработали мобильное приложение, которое позволяет отслеживать местоположение опасных районов с ковид, с использованием данных о локации и по Bluetooth.
В отличие от аналогов, мы хотели сделать всё анонимно и добровольно. Без использования регистрации, привязки номера телефона и email.
Без отправки данных во все возможные инстанции.
Идея была проста – чтобы каждый мог отправить свой статус здоровья и поделиться им с другими участниками добровольно. Чтобы пользователи могли видеть на карте зараженные маршруты и получать уведомления после пересечения с заболевшими. Интегрировали туда индекс заражения района и множество других, на наш взгляд, полезных идей.
Технических сложностей было много, начиная от работы локации в фоновом режиме и заканчивая обменом данных по Bluetooth без подключения.
Так как Bluetooth может вызвать много вопросов и, на наш взгляд, наиболее интересен, поделюсь хитрым решением с вами. Может кому-то пригодится в проектах.
Мы использовали Bluetooth одновременно как Beacon-маячок и как сканер маячков.
Наша задача находить контакты с заболевшими людьми рядом. Так как у нас анонимное приложение и у каждого пользователя есть только обезличенный ID, его мы и решили вещать по Bluetooth.
В Android для этого мы создали foreground службу BluetoothMonitorService. Эта служба должна вещать наш ID по Bluetooth и сканировать местность рядом на наличие других ID. В обычной службе операционная система не даст работать вашему приложению и, к сожалению, должно быть постоянное уведомление в трее.
Вторым важным моментом на этом этапе требуется наличие разрешения:
Так что локацию запрашивать придется. Без этого разрешения вам будет приходить пустой список.
Ну и конечно:
И так, начнем.
Для начала запустим вещание:
Как можно заметить ID пользователя мы разместили в addManufacturerData.
Будьте внимательны, размер пакета ограничен 31 байтом. Отключите отображение имени и информацию об уровень мощности, чтобы хватило на ваш Payload.
addServiceUuid – это 128-битный уникальный идентификатор атрибута. Уникальный UUID для нашего приложения, по которому можно будет отфильтровать девайс при сканировании.
После этого слушаем ответ:
Параллельно запускаем наш сканер:
ServiceUUID должен быть такой же, как при вещании, иначе вы не будете получать вообще никакой информации. Он уникален для вашего приложения. Сгенерировать можно вот тут https://www.uuidgenerator.net.
В самой службе следует установить удобные интервалы опроса, у нас это раз в 30 секунд. Это позволяет нам беречь заряд батареи.
Приложение получилось не прожорливым. Даже с учетом работы локации, находится в конце списка по потреблению.
После нескольких месяцев разработки появились iOS и Android версии приложения. Мы отправили их на проверку в Google и Apple.
И вот тут началось самое интересное, оказывается разработать решение – это самое лёгкое. Сложности начались с размещением в сторах.
В Google у нас получилось пройти, предоставив бумагу официальных гос. органов, что они не против приложения. Получить её в России само по себе подвиг, но это уже другая история.
С Apple была тишина долгое время. Мы писали повторно, оправляли им разрешение гос. органов, но ответа не было.
И вот, в один прекрасный день, звонок. Мне позвонили из Apple! Я так переволновался, что забыл английский язык. В Apple были крайне вежливы и после пяти минут общения сказали, что найдут переводчика.
Через некоторое время, мне позвонили опять и уже на русском с акцентом стали спрашивать о приложении.
Сказали, что их медицинский департамент заинтересовался нашим приложением, что без их одобрения мы не пройдем проверку. Что если мы ответим на их вопросы, они готовы даже посотрудничать. После этого мы какое-то время покорно отвечали на все их вопросы и ждали решения и долгожданного сотрудничества.
Но чтобы не терять времени, мы решили рассказать о приложении нашим властям, чтобы показать альтернативу и возможность не принуждать людей как стадо, а дать им выбор и добровольный инструмент.
Отправляя письма во все инстанции, мы получали один ответ – полное отсутствие ответа.
Минздрав России мы решили атаковать активнее как Энди Дюфрейн. Но Минздрав был непробиваем, нам даже Госдепартамент США ответил на обращение, а вот Минздрав…
Нашему удивлению не было предела, когда Apple выпустила своё API ExposureNotification с формулировками точь-в-точь, повторяющими наши! Может быть это совпадение, но это настораживает и заставляет задуматься.
Хочу обратиться к вам за помощью в оценке приложения, в его распространении и донесении до наших властей, что можно и по-другому. Давайте попробуем вместе что-то поменять!
https://mysafe.ai
Google Play
Covid-19. Наверное, каждый слышал об этом вирусе. Я сейчас не берусь описывать свое личное отношение или обсуждать теории заговоров вокруг этого. Лично для меня это реальный кейс с близкими, которые заболели.
Столкнувшись с ковид лицом к лицу, наша команда решила внести свой вклад в борьбу с этим злом.
Мы разработали мобильное приложение, которое позволяет отслеживать местоположение опасных районов с ковид, с использованием данных о локации и по Bluetooth.
В отличие от аналогов, мы хотели сделать всё анонимно и добровольно. Без использования регистрации, привязки номера телефона и email.
Без отправки данных во все возможные инстанции.
Идея была проста – чтобы каждый мог отправить свой статус здоровья и поделиться им с другими участниками добровольно. Чтобы пользователи могли видеть на карте зараженные маршруты и получать уведомления после пересечения с заболевшими. Интегрировали туда индекс заражения района и множество других, на наш взгляд, полезных идей.
Технических сложностей было много, начиная от работы локации в фоновом режиме и заканчивая обменом данных по Bluetooth без подключения.
Так как Bluetooth может вызвать много вопросов и, на наш взгляд, наиболее интересен, поделюсь хитрым решением с вами. Может кому-то пригодится в проектах.
Мы использовали Bluetooth одновременно как Beacon-маячок и как сканер маячков.
Наша задача находить контакты с заболевшими людьми рядом. Так как у нас анонимное приложение и у каждого пользователя есть только обезличенный ID, его мы и решили вещать по Bluetooth.
В Android для этого мы создали foreground службу BluetoothMonitorService. Эта служба должна вещать наш ID по Bluetooth и сканировать местность рядом на наличие других ID. В обычной службе операционная система не даст работать вашему приложению и, к сожалению, должно быть постоянное уведомление в трее.
Вторым важным моментом на этом этапе требуется наличие разрешения:
Manifest.permission.ACCESS_COARSE_LOCATION.
Так что локацию запрашивать придется. Без этого разрешения вам будет приходить пустой список.
Ну и конечно:
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
И так, начнем.
Для начала запустим вещание:
private void StartAdvertisingLegacy(long timeoutInMillis, int id) {
byte[] bytesPID = ByteBuffer.allocate(charLength).putInt(id).array();
data = new AdvertiseData.Builder()
.setIncludeDeviceName(false)
.setIncludeTxPowerLevel(false)
.addServiceUuid(pUuid)
.addManufacturerData(9, bytesPID)
.build();
try {
Log.d(TAG, "Start advertising");
advertiser = (advertiser != null) ? advertiser : BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
advertiser.startAdvertising(settings, data, advertisingCallback);
} catch (Exception e) {
Log.d(TAG, "Failed to start advertising legacy: ${e.message}");
}
}
Как можно заметить ID пользователя мы разместили в addManufacturerData.
Будьте внимательны, размер пакета ограничен 31 байтом. Отключите отображение имени и информацию об уровень мощности, чтобы хватило на ваш Payload.
addServiceUuid – это 128-битный уникальный идентификатор атрибута. Уникальный UUID для нашего приложения, по которому можно будет отфильтровать девайс при сканировании.
После этого слушаем ответ:
AdvertiseCallback advertisingCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
Log.i(TAG, "Advertising onStartSuccess");
Log.i(TAG, settingsInEffect.toString());
isAdvertising = true;
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
String reason;
switch (errorCode) {
case ADVERTISE_FAILED_ALREADY_STARTED:
reason = "ADVERTISE_FAILED_ALREADY_STARTED";
isAdvertising = true;
break;
case ADVERTISE_FAILED_FEATURE_UNSUPPORTED:
reason = "ADVERTISE_FAILED_FEATURE_UNSUPPORTED";
isAdvertising = false;
break;
case ADVERTISE_FAILED_INTERNAL_ERROR:
reason = "ADVERTISE_FAILED_INTERNAL_ERROR";
isAdvertising = false;
break;
case ADVERTISE_FAILED_TOO_MANY_ADVERTISERS:
reason = "ADVERTISE_FAILED_TOO_MANY_ADVERTISERS";
isAdvertising = false;
break;
case ADVERTISE_FAILED_DATA_TOO_LARGE:
reason = "ADVERTISE_FAILED_DATA_TOO_LARGE";
isAdvertising = false;
charLength--;
break;
default:
reason = "UNDOCUMENTED";
}
Log.e(TAG, "Advertising onStartFailure: " + errorCode + " " + reason);
}
};
Параллельно запускаем наш сканер:
public void StartScan(ScanCallback scanCallback) {
ScanFilter filter = new ScanFilter.Builder()
.setServiceUuid(new ParcelUuid(UUID.fromString(serviceUUID)))
.build();
List<ScanFilter> filters = new ArrayList<>();
filters.add(filter);
ScanSettings settings = new ScanSettings.Builder()
.setReportDelay(reportDelay)
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
this.scanCallback = scanCallback;
//try to get a scanner if there isn't anything
scanner = (scanner != null) ? scanner : BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
scanner.startScan(filters, settings, scanCallback);
Log.d(TAG, "scanning started");
}
ServiceUUID должен быть такой же, как при вещании, иначе вы не будете получать вообще никакой информации. Он уникален для вашего приложения. Сгенерировать можно вот тут https://www.uuidgenerator.net.
В самой службе следует установить удобные интервалы опроса, у нас это раз в 30 секунд. Это позволяет нам беречь заряд батареи.
Приложение получилось не прожорливым. Даже с учетом работы локации, находится в конце списка по потреблению.
После нескольких месяцев разработки появились iOS и Android версии приложения. Мы отправили их на проверку в Google и Apple.
И вот тут началось самое интересное, оказывается разработать решение – это самое лёгкое. Сложности начались с размещением в сторах.
В Google у нас получилось пройти, предоставив бумагу официальных гос. органов, что они не против приложения. Получить её в России само по себе подвиг, но это уже другая история.
С Apple была тишина долгое время. Мы писали повторно, оправляли им разрешение гос. органов, но ответа не было.
И вот, в один прекрасный день, звонок. Мне позвонили из Apple! Я так переволновался, что забыл английский язык. В Apple были крайне вежливы и после пяти минут общения сказали, что найдут переводчика.
Через некоторое время, мне позвонили опять и уже на русском с акцентом стали спрашивать о приложении.
Сказали, что их медицинский департамент заинтересовался нашим приложением, что без их одобрения мы не пройдем проверку. Что если мы ответим на их вопросы, они готовы даже посотрудничать. После этого мы какое-то время покорно отвечали на все их вопросы и ждали решения и долгожданного сотрудничества.
Но чтобы не терять времени, мы решили рассказать о приложении нашим властям, чтобы показать альтернативу и возможность не принуждать людей как стадо, а дать им выбор и добровольный инструмент.
Отправляя письма во все инстанции, мы получали один ответ – полное отсутствие ответа.
Минздрав России мы решили атаковать активнее как Энди Дюфрейн. Но Минздрав был непробиваем, нам даже Госдепартамент США ответил на обращение, а вот Минздрав…
Нашему удивлению не было предела, когда Apple выпустила своё API ExposureNotification с формулировками точь-в-точь, повторяющими наши! Может быть это совпадение, но это настораживает и заставляет задуматься.
Хочу обратиться к вам за помощью в оценке приложения, в его распространении и донесении до наших властей, что можно и по-другому. Давайте попробуем вместе что-то поменять!
https://mysafe.ai
Google Play