diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt index 794109c..6d86f6c 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardMethodSelectFragment.kt @@ -2,9 +2,7 @@ package im.angry.openeuicc.ui.wizard import android.app.AlertDialog import android.content.ClipboardManager -import android.graphics.Bitmap import android.graphics.BitmapFactory -import android.net.Uri import android.os.Bundle import android.util.Log import android.view.LayoutInflater @@ -22,9 +20,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanOptions import im.angry.openeuicc.common.R -import im.angry.openeuicc.util.ActivationCode -import im.angry.openeuicc.util.decodeQrFromBitmap -import im.angry.openeuicc.util.preferenceRepository +import im.angry.openeuicc.util.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch @@ -32,10 +28,6 @@ import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext class DownloadWizardMethodSelectFragment : DownloadWizardActivity.DownloadWizardStepFragment() { - companion object { - const val TAG = "DownloadWizardMethodSelectFragment" - } - data class DownloadMethod( val iconRes: Int, val titleRes: Int, @@ -43,28 +35,34 @@ class DownloadWizardMethodSelectFragment : DownloadWizardActivity.DownloadWizard ) // TODO: Maybe we should find a better barcode scanner (or an external one?) - private val barcodeScannerLauncher = - registerForActivityResult(ScanContract()) { - processLpaString(it.contents ?: return@registerForActivityResult) + private val barcodeScannerLauncher = registerForActivityResult(ScanContract()) { result -> + result.contents?.let { content -> + processLpaString(content) } + } private val gallerySelectorLauncher = - registerForActivityResult(ActivityResultContracts.GetContent()) { + registerForActivityResult(ActivityResultContracts.GetContent()) { result -> + if (result == null) return@registerForActivityResult + lifecycleScope.launch(Dispatchers.IO) { - val decoded = onGalleryResult(it ?: return@launch) ?: return@launch - withContext(Dispatchers.Main) { processLpaString(decoded) } + runCatching { + requireContext().contentResolver.openInputStream(result)?.let { input -> + val bmp = BitmapFactory.decodeStream(input) + input.close() + + decodeQrFromBitmap(bmp)?.let { + withContext(Dispatchers.Main) { + processLpaString(it) + } + } + + bmp.recycle() + } + } } } - private fun onGalleryResult(result: Uri) = try { - requireContext().contentResolver.openInputStream(result) - .use(BitmapFactory::decodeStream) - .use(::decodeQrFromBitmap) - } catch (e: Exception) { - Log.e(TAG, "Failed to decode QR code from gallery", e) - null - } - val downloadMethods = arrayOf( DownloadMethod(R.drawable.ic_scan_black, R.string.download_wizard_method_qr_code) { barcodeScannerLauncher.launch(ScanOptions().apply { @@ -190,10 +188,4 @@ class DownloadWizardMethodSelectFragment : DownloadWizardActivity.DownloadWizard } } -} - -private fun Bitmap.use(block: Bitmap.() -> T): T = try { - block() -} finally { - recycle() } \ No newline at end of file diff --git a/app-common/src/main/java/im/angry/openeuicc/util/Utils.kt b/app-common/src/main/java/im/angry/openeuicc/util/Utils.kt index fd32eac..444c176 100644 --- a/app-common/src/main/java/im/angry/openeuicc/util/Utils.kt +++ b/app-common/src/main/java/im/angry/openeuicc/util/Utils.kt @@ -86,12 +86,13 @@ suspend fun connectSEService(context: Context): SEService = suspendCoroutine { c } } -fun decodeQrFromBitmap(bmp: Bitmap): String { - val pixels = IntArray(bmp.width * bmp.height) - bmp.getPixels(pixels, 0, bmp.width, 0, 0, bmp.width, bmp.height) +fun decodeQrFromBitmap(bmp: Bitmap): String? = + runCatching { + val pixels = IntArray(bmp.width * bmp.height) + bmp.getPixels(pixels, 0, bmp.width, 0, 0, bmp.width, bmp.height) - val luminanceSource = RGBLuminanceSource(bmp.width, bmp.height, pixels) - val binaryBmp = BinaryBitmap(HybridBinarizer(luminanceSource)) + val luminanceSource = RGBLuminanceSource(bmp.width, bmp.height, pixels) + val binaryBmp = BinaryBitmap(HybridBinarizer(luminanceSource)) - return QRCodeReader().decode(binaryBmp).text -} + QRCodeReader().decode(binaryBmp).text + }.getOrNull()