[Android] Show QrCode instead of links when no browser is installed

Nicolas Pomepuy git at videolan.org
Mon Mar 28 15:16:56 UTC 2022


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Mon Mar 28 16:01:03 2022 +0200| [95bfc26c2e40ae30c7ac0685109eaca0207a82c5] | committer: Nicolas Pomepuy

Show QrCode instead of links when no browser is installed

> https://code.videolan.org/videolan/vlc-android/commit/95bfc26c2e40ae30c7ac0685109eaca0207a82c5
---

 .../resources/src/main/res/values/strings.xml      |  2 +
 application/vlc-android/build.gradle               |  1 +
 .../org/videolan/vlc/gui/dialogs/LicenseDialog.kt  |  5 +-
 .../src/org/videolan/vlc/gui/helpers/UiTools.kt    |  7 +-
 .../src/org/videolan/vlc/util/UrlUtils.kt          | 75 ++++++++++++++++++++++
 5 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/application/resources/src/main/res/values/strings.xml b/application/resources/src/main/res/values/strings.xml
index 9afa2ff33..c49c2676d 100644
--- a/application/resources/src/main/res/values/strings.xml
+++ b/application/resources/src/main/res/values/strings.xml
@@ -924,5 +924,7 @@
     <string name="always_fast_seek_summary">Seek is faster but may be less precise</string>
     <string name="touch_only">Touch only feature</string>
     <string name="touch_only_description">Switching to the mobile interface can only be done with a tactile screen or a mouse.\nPlease slide below to verify that this feature is safe to change.</string>
+    <string name="no_web_browser">No web browser installed</string>
+    <string name="no_web_browser_message">You can scan this on your smartphone.\nThe URL is %s</string>
 
 </resources>
diff --git a/application/vlc-android/build.gradle b/application/vlc-android/build.gradle
index bfc80d8d1..4d272090e 100644
--- a/application/vlc-android/build.gradle
+++ b/application/vlc-android/build.gradle
@@ -193,6 +193,7 @@ dependencies {
     api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.ext.kotlinx_version"
 
     implementation 'nl.dionsegijn:konfetti:1.2.2'
+    implementation 'com.google.zxing:core:3.4.0'
 
     // Tests
     androidTestImplementation "androidx.test.espresso:espresso-contrib:$rootProject.espressoVersion"
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/LicenseDialog.kt b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/LicenseDialog.kt
index 3c68c7e50..c1a23b899 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/LicenseDialog.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/LicenseDialog.kt
@@ -21,18 +21,17 @@
  */
 package org.videolan.vlc.gui.dialogs
 
-import android.content.Intent
 import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import androidx.core.net.toUri
 import androidx.core.os.bundleOf
 import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.ObsoleteCoroutinesApi
 import org.videolan.vlc.databinding.DialogLicenseBinding
 import org.videolan.vlc.gui.LibraryWithLicense
+import org.videolan.vlc.util.openLinkIfPossible
 
 const val LICENSE_ITEM = "LICENSE_ITEM"
 
@@ -74,7 +73,7 @@ class LicenseDialog : VLCBottomSheetDialogFragment() {
         binding = DialogLicenseBinding.inflate(layoutInflater, container, false)
         binding.library = licenseItem
         binding.licenseButton.setOnClickListener {
-            if (licenseItem.licenseLink.isNotEmpty()) requireActivity().startActivity(Intent(Intent.ACTION_VIEW, licenseItem.licenseLink.toUri()))
+            if (licenseItem.licenseLink.isNotEmpty()) requireActivity().openLinkIfPossible(licenseItem.licenseLink)
         }
         return binding.root
     }
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
index 616dea25b..648ee3e79 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
@@ -83,6 +83,7 @@ import org.videolan.vlc.media.MediaUtils
 import org.videolan.vlc.media.getAll
 import org.videolan.vlc.providers.medialibrary.MedialibraryProvider
 import org.videolan.vlc.util.FileUtils
+import org.videolan.vlc.util.openLinkIfPossible
 
 @ObsoleteCoroutinesApi
 @ExperimentalCoroutinesApi
@@ -379,13 +380,13 @@ object UiTools {
             AboutVersionDialog.newInstance().show(activity.supportFragmentManager, "AboutVersionDialog")
         }
         v.findViewById<View>(R.id.about_website_container).setOnClickListener {
-            activity.startActivity(Intent(Intent.ACTION_VIEW, "https://www.videolan.org/vlc/".toUri()))
+            activity.openLinkIfPossible("https://www.videolan.org/vlc/")
         }
         v.findViewById<View>(R.id.about_forum_container).setOnClickListener {
-            activity.startActivity(Intent(Intent.ACTION_VIEW, "https://forum.videolan.org/viewforum.php?f=35".toUri()))
+            activity.openLinkIfPossible("https://forum.videolan.org/viewforum.php?f=35")
         }
         v.findViewById<View>(R.id.about_sources_container).setOnClickListener {
-            activity.startActivity(Intent(Intent.ACTION_VIEW, "https://code.videolan.org/videolan/vlc-android".toUri()))
+            activity.openLinkIfPossible("https://code.videolan.org/videolan/vlc-android")
         }
 
         v.findViewById<View>(R.id.about_authors_container).setOnClickListener {
diff --git a/application/vlc-android/src/org/videolan/vlc/util/UrlUtils.kt b/application/vlc-android/src/org/videolan/vlc/util/UrlUtils.kt
new file mode 100644
index 000000000..c494a2631
--- /dev/null
+++ b/application/vlc-android/src/org/videolan/vlc/util/UrlUtils.kt
@@ -0,0 +1,75 @@
+/*
+ * ************************************************************************
+ *  UrlUtils.kt
+ * *************************************************************************
+ * Copyright © 2022 VLC authors and VideoLAN
+ * Author: Nicolas POMEPUY
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * **************************************************************************
+ *
+ *
+ */
+
+package org.videolan.vlc.util
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ResolveInfo
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.widget.ImageView
+import androidx.appcompat.app.AlertDialog
+import androidx.core.net.toUri
+import com.google.zxing.BarcodeFormat
+import com.google.zxing.qrcode.QRCodeWriter
+import org.videolan.vlc.R
+
+
+fun Context.openLinkIfPossible(url: String, size: Int = 512) {
+
+
+    try {
+
+
+            val intent = Intent(Intent.ACTION_VIEW, url.toUri())
+        val match: List<ResolveInfo> = packageManager.queryIntentActivities(intent, 0)
+
+        if (match.size == 1) {
+            val resolveActivity = intent.resolveActivity(packageManager)
+            if (resolveActivity == null || resolveActivity.packageName.startsWith("com.google.android.tv.frameworkpackagestubs")) throw IllegalStateException("No web browser found")
+        }
+        startActivity(intent)
+    } catch (e: Exception) {
+        val image = ImageView(this)
+
+        val bits = QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, size, size)
+        val bitmap = 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)
+                }
+            }
+        }
+        image.setImageBitmap(bitmap)
+        AlertDialog.Builder(this)
+                .setTitle(getString(R.string.no_web_browser))
+                .setMessage(getString(R.string.no_web_browser_message, url))
+                .setView(image)
+                .setPositiveButton(R.string.ok) { _, _ ->
+
+                }
+                .show()
+    }
+}
\ No newline at end of file



More information about the Android mailing list