From 2532abf8bdfac2018ce92d3625153cb2610fced3 Mon Sep 17 00:00:00 2001 From: axelherbstreith <75120552+axelherbstreith@users.noreply.github.com> Date: Fri, 26 Mar 2021 10:42:56 +0100 Subject: [PATCH] QR code Generation Component (EXPOSUREAPP-5961) (#2689) * added qr code generator component * linting * updated error handling * linting * updated exception handling in view model Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com> --- .../ui/qrcode/QrCodeCreationTestViewModel.kt | 58 +++---------------- .../checkins/qrcode/QrCodeGenerator.kt | 58 +++++++++++++++++++ 2 files changed, 67 insertions(+), 49 deletions(-) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QrCodeGenerator.kt diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt index 268db7561..a1eca9f8b 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/qrcode/QrCodeCreationTestViewModel.kt @@ -2,17 +2,12 @@ package de.rki.coronawarnapp.test.eventregistration.ui.qrcode import android.content.Context import android.graphics.Bitmap -import android.graphics.Color.BLACK -import android.graphics.Color.WHITE import android.graphics.pdf.PdfDocument import android.view.View -import com.google.zxing.BarcodeFormat -import com.google.zxing.EncodeHintType -import com.google.zxing.MultiFormatWriter -import com.google.zxing.common.BitMatrix import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import de.rki.coronawarnapp.appconfig.AppConfigProvider +import de.rki.coronawarnapp.ui.eventregistration.organizer.details.QrCodeGenerator import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.files.FileSharing @@ -26,6 +21,7 @@ import java.io.FileOutputStream class QrCodeCreationTestViewModel @AssistedInject constructor( private val dispatcher: DispatcherProvider, private val fileSharing: FileSharing, + private val qrCodeGenerator: QrCodeGenerator, @AppContext private val context: Context, private val appConfigProvider: AppConfigProvider, ) : CWAViewModel(dispatcher) { @@ -38,7 +34,13 @@ class QrCodeCreationTestViewModel @AssistedInject constructor( * Creates a QR Code [Bitmap] ,result is delivered by [qrCodeBitmap] */ fun createQrCode(input: String) = launch(context = dispatcher.IO) { - qrCodeBitmap.postValue(encodeAsBitmap(input)) + + try { + qrCodeBitmap.postValue(qrCodeGenerator.createQrCode(input)) + } catch (e: Exception) { + Timber.d(e, "Qr code creation failed") + errorMessage.postValue(e.localizedMessage ?: "QR code creation failed") + } } /** @@ -83,48 +85,6 @@ class QrCodeCreationTestViewModel @AssistedInject constructor( return File(dir, "CoronaWarnApp-Event.pdf") } - private suspend fun encodeAsBitmap(input: String, size: Int = 1000): Bitmap? { - return try { - val qrCodeErrorCorrectionLevel = appConfigProvider - .getAppConfig() - .presenceTracing - .qrCodeErrorCorrectionLevel - Timber.i("QrCodeErrorCorrectionLevel: $qrCodeErrorCorrectionLevel") - val hints = mapOf( - EncodeHintType.ERROR_CORRECTION to qrCodeErrorCorrectionLevel - // This is not required in the specs and it should not be enabled - // it is causing crash on older Android versions ex:API 23 - // EncodeHintType.CHARACTER_SET to Charsets.UTF_8 - ) - MultiFormatWriter().encode( - input, - BarcodeFormat.QR_CODE, - size, - size, - hints - ).toBitmap() - } catch (e: Exception) { - Timber.d(e, "Qr code creation failed") - errorMessage.postValue(e.localizedMessage ?: "QR code creation failed") - null - } - } - - private fun BitMatrix.toBitmap() = - Bitmap.createBitmap( - context.resources.displayMetrics, - width, - height, - Bitmap.Config.ARGB_8888 - ).apply { - for (x in 0 until width) { - for (y in 0 until height) { - val color = if (get(x, y)) BLACK else WHITE - setPixel(x, y, color) - } - } - } - @AssistedFactory interface Factory : SimpleCWAViewModelFactory<QrCodeCreationTestViewModel> } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QrCodeGenerator.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QrCodeGenerator.kt new file mode 100644 index 000000000..6dac184d6 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QrCodeGenerator.kt @@ -0,0 +1,58 @@ +package de.rki.coronawarnapp.ui.eventregistration.organizer.details + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Color +import com.google.zxing.BarcodeFormat +import com.google.zxing.EncodeHintType +import com.google.zxing.MultiFormatWriter +import com.google.zxing.common.BitMatrix +import dagger.Reusable +import de.rki.coronawarnapp.appconfig.AppConfigProvider +import de.rki.coronawarnapp.util.di.AppContext +import timber.log.Timber +import javax.inject.Inject + +@Reusable +class QrCodeGenerator @Inject constructor( + private val appConfigProvider: AppConfigProvider, + @AppContext private val context: Context, +) { + + suspend fun createQrCode(input: String, size: Int = 1000): Bitmap? { + + val qrCodeErrorCorrectionLevel = appConfigProvider + .getAppConfig() + .presenceTracing + .qrCodeErrorCorrectionLevel + Timber.i("QrCodeErrorCorrectionLevel: $qrCodeErrorCorrectionLevel") + val hints = mapOf( + EncodeHintType.ERROR_CORRECTION to qrCodeErrorCorrectionLevel + ) + + return MultiFormatWriter().encode( + input, + BarcodeFormat.QR_CODE, + size, + size, + hints + ).toBitmap() + } + + private fun BitMatrix.toBitmap(): Bitmap { + val bitmap = Bitmap.createBitmap( + context.resources.displayMetrics, + width, + height, + Bitmap.Config.ARGB_8888 + ) + + for (x in 0 until width) { + for (y in 0 until height) { + val color = if (get(x, y)) Color.BLACK else Color.WHITE + bitmap.setPixel(x, y, color) + } + } + return bitmap + } +} -- GitLab