QR коды в Android приложении

sashatinkoff
О разработке для Android
3 min readApr 22, 2019

Самым простым способом коммуникации между двумя приложения на кратчайшей дистанции (скажем, вытянутой руки) мне казалась технология Network Service Discovery Manager. Эта технология очень часто используется при поиске принтеров в рамках wifi сети, например. Если очень кратко (ведь речь в статье о другом), то схема такая: устройство регистрирует сервис, который может быть найден на другом устройстве. В рамках соединения между устройствами может быть передана какая-то минимальная информация. В теории (и отчасти на практике) это казалось идеальным: запуск сервиса на одном устройстве и мгновенное (почти) его получение на другом.

На практике не все оказалось так гладко. Так, например, на устройствах раньше Marshmallow передача данных не поддерживалась, так что пришлось городить огород и находить костыльные решения… Которые впрочем оказались не так востребованы. Кажется, на некоторых wifi роутерах возможность поиска устройств отключена… или не работает по какой-либо другой таинственной причине.

Пришлось вернуться обратно к списку возможных ответов на вопрос “Как передать информацию с одного устройства на другое”. Так как в рамках задачи эти два устройства общаются через сервер, то варианты получились следующие:

  1. Общение по Bluetooth. Вообще, скорость соединения устройств по блутусу не так скоростна, как допустим NFC, но мне необходима поддержка довольно медленных устройств, так что я отложил этот вариант
  2. Создание PIN кода на сервере и ввод его на другом устройстве. Этот вариант мне понравился тем, что клавиатура будет работать на любом устройстве, и таких подводных камней, как например при NSD можно избежать. Но это решение потребовало бы усилий не только Android, но и бэкенд разработчика, и как бы я ни был “за” это решение, я его отложил
  3. Шифрование базовой информации в виде QR / Barcode. В связи с некоторыми задачами в будущем, я решил использовать именно этот вариант.

И снова не без проблем. Оказалось, что QR коды, их генерация и чтение в рамках Android разработки не совсем тривиальная задача. Google предоставил инструмент для чтения кодов в рамках Play Services Vision, но для этого надо иметь актуальные версии play services, установленные на устройствах. Как показал мой опыт работы над библиотекой Vision ранее, это может быть проблемой, поэтому я искал вариант без использования Play Services.

К тому же возможно использование дешевых китайских устройств, где не совсем понятно будут ли установлены гугловские сервисы, поэтому лучше максимально от них дистанцироваться.

Если начать гугление на тему QR коды в андроид приложении, то первое (и практически единственное) решение — это библиотека zxing. Там оказалось не все так просто (не в режиме установил, написал и вперед), а пришлось немного повозиться, поэтому я решил осветить рабочую интеграцию.

Итак, первое, что надо сделать, это добавить зависимость в наш build.gradle

implementation "com.google.zxing:core:${versions.zxing}"

Актуальная версия на момент написания статьи 3.3.0

Создание QR кода легко гуглится

fun create(text: String): Bitmap? {
val writer = QRCodeWriter()
return try {
val bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, 512, 512)
val width = bitMatrix.width
val height = bitMatrix.height
val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
for (x in 0 until width) {
for (y in 0 until height) {
bmp.setPixel(x, y, if (bitMatrix.get(x, y)) Color.BLACK else Color.WHITE)
}
}
bmp

} catch (e: WriterException) {
null
}
}

А вот с чтением QR кода возникли некоторые сложности. Не буду пытать, а сразу приложу рабочий код

fun read(bitmap: Bitmap): String? {
val intArray = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(intArray, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)

val source = RGBLuminanceSource(bitmap.width, bitmap.height, intArray)
val binaryBitmap = BinaryBitmap(HybridBinarizer(source))

val reader = MultiFormatReader()
return try {
val result = reader.decode(binaryBitmap)
result.text
} catch (e: Exception) {
null
}
}

Ну и рабочий код в Gist, как обычно

--

--

sashatinkoff
О разработке для Android

Пишу о разном с матом ем булку с маком никогда не бегал с автоматом