Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Commit

Permalink
QR code Generation Component (EXPOSUREAPP-5961) (#2689)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
axelherbstreith and harambasicluka authored Mar 26, 2021
1 parent 5cc2126 commit 2532abf
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -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")
}
}

/**
Expand Down Expand Up @@ -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>
}
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit 2532abf

Please sign in to comment.