diff --git a/README.md b/README.md index b9803e41f..bf9d13fb2 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ are interested in our custom apps, they have their own repo - [JUnit5](https://github.com/junit-team/junit5/) - The next generation of JUnit - [AssertJ](https://github.com/joel-costigliola/assertj-core) - Fluent assertions for test code - [Fetch](https://github.com/tonyofrancis/Fetch) - A customizable file download manager library for Android +- [ZXing](https://github.com/zxing/zxing) - Barcode scanning library for Java, Android ## Contributing diff --git a/app/src/main/java/org/kiwix/kiwixmobile/qr/ShareByQRCodeDialog.kt b/app/src/main/java/org/kiwix/kiwixmobile/qr/ShareByQRCodeDialog.kt index 1240fadc3..b9b7402a4 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/qr/ShareByQRCodeDialog.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/qr/ShareByQRCodeDialog.kt @@ -20,15 +20,32 @@ package org.kiwix.kiwixmobile.qr import android.app.AlertDialog import android.app.Dialog +import android.net.Uri import android.os.Bundle +import androidx.core.net.toUri import androidx.fragment.app.DialogFragment +import androidx.navigation.fragment.navArgs import org.kiwix.kiwixmobile.core.databinding.DialogShareByQrCodeBinding +import org.kiwix.kiwixmobile.core.qr.GenerateQR class ShareByQRCodeDialog : DialogFragment() { + + private val args: ShareByQRCodeDialogArgs by navArgs() + + private lateinit var binding: DialogShareByQrCodeBinding + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val binding = DialogShareByQrCodeBinding.inflate(layoutInflater) + binding = DialogShareByQrCodeBinding.inflate(layoutInflater) + + loadQrCode(args.uri.toUri()) + return AlertDialog.Builder(requireContext()) .setView(binding.root) .create() } + + private fun loadQrCode(uri: Uri) { + val qrCode = GenerateQR().createQR(uri) + binding.qrCode.setImageBitmap(qrCode) + } } diff --git a/app/src/main/res/navigation/kiwix_nav_graph.xml b/app/src/main/res/navigation/kiwix_nav_graph.xml index 166a02b85..0f3b5e294 100644 --- a/app/src/main/res/navigation/kiwix_nav_graph.xml +++ b/app/src/main/res/navigation/kiwix_nav_graph.xml @@ -160,7 +160,7 @@ android:name="org.kiwix.kiwixmobile.qr.ShareByQRCodeDialog" android:label="ShareByQRCodeFragment" tools:layout="@layout/dialog_share_by_qr_code"> - + + diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt index a245ad655..e25fd2a7b 100644 --- a/buildSrc/src/main/kotlin/Libs.kt +++ b/buildSrc/src/main/kotlin/Libs.kt @@ -359,4 +359,9 @@ object Libs { const val roomRuntime = "androidx.room:room-runtime:" + Versions.roomVersion const val roomRxjava2 = "androidx.room:room-rxjava2:" + Versions.roomVersion + + /** + * https://github.com/zxing/zxing + */ + const val zxing = "com.google.zxing:core:" + Versions.zxing } diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index d22a681a6..03ebd9fba 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -105,6 +105,8 @@ object Versions { const val material_show_case_view: String = "1.3.7" const val roomVersion = "2.5.0" + + const val zxing = "3.5.3" } /** diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 61fa4bef8..09a52179d 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -84,4 +84,7 @@ dependencies { implementation(Libs.webkit) testImplementation(Libs.kotlinx_coroutines_test) implementation(Libs.kotlinx_coroutines_android) + + // ZXing + implementation(Libs.zxing) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/qr/GenerateQR.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/qr/GenerateQR.kt new file mode 100644 index 000000000..c7f4b62d3 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/qr/GenerateQR.kt @@ -0,0 +1,48 @@ +/* + * Kiwix Android + * Copyright (c) 2024 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.qr + +import android.graphics.Bitmap +import android.graphics.Color +import android.net.Uri +import com.google.zxing.BarcodeFormat +import com.google.zxing.EncodeHintType +import com.google.zxing.qrcode.QRCodeWriter + +/** + * Utility class to generate QR codes. + */ +class GenerateQR { + /** + * Create a QR code for the given [uri]. + */ + fun createQR(uri: Uri, size: Int = 512): Bitmap { + val hints = hashMapOf().also { + it[EncodeHintType.MARGIN] = 1 + } + val bits = QRCodeWriter().encode("$uri", BarcodeFormat.QR_CODE, size, size, hints) + return Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565).also { + for (x in 0 until size) { + for (y in 0 until size) { + it.setPixel(x, y, if (bits[x, y]) Color.BLACK else Color.WHITE) + } + } + } + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt index 7b2e8306c..4f34ff48b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt @@ -392,8 +392,9 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { visibility = View.VISIBLE setOnClickListener { // Navigate cross-module via deeplink + val authority = ip?.toUri()?.encodedAuthority // Need to exclude the scheme val request = NavDeepLinkRequest.Builder - .fromUri("kiwix://shareByQr".toUri()) + .fromUri("kiwix://shareByQr/$authority".toUri()) .build() findNavController().navigate(request) }