From 8dbdda9faf44b2289eac0bd2f791c6be7bb64f1c Mon Sep 17 00:00:00 2001 From: Pratik Velani Date: Sat, 7 Oct 2023 02:30:04 +0530 Subject: [PATCH] fix(android): When chrome is not installed/enabled or the default browser (#2261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #2225 - Set Chrome app has a hard requirement for seamless user experience with app link. - Check if Chrome is not installed/enabled, then show an error toast. - If Chrome is not set as the default browser, use the Chrome stable version package name to force open the sign-in flow in Chrome. Fixes #2184 - Closing webview moves back to sign-in page. _Applinks is supported in Firefox but is disabled by default (https://support.mozilla.org/en-US/kb/set-firefox-android-open-links-native-apps) ..why 🤦‍♂️??_ Later based on user's browser we can update the redirected page to include instructions to enable the link, something like this: ![Screenshot_1696581921](https://github.com/firezone/firezone/assets/1523745/2587b3de-7e85-4b82-aa99-61e58b8dc0b3) --------- Co-authored-by: Jamil --- .../android/features/auth/ui/AuthActivity.kt | 45 +++++++++++++++---- .../features/signin/ui/SignInFragment.kt | 1 - .../firezone/android/util/CustomTabsHelper.kt | 21 +++++++++ .../app/src/main/res/values/strings.xml | 1 + 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/kotlin/android/app/src/main/java/dev/firezone/android/features/auth/ui/AuthActivity.kt b/kotlin/android/app/src/main/java/dev/firezone/android/features/auth/ui/AuthActivity.kt index a4400e06b..d4bcaffc1 100644 --- a/kotlin/android/app/src/main/java/dev/firezone/android/features/auth/ui/AuthActivity.kt +++ b/kotlin/android/app/src/main/java/dev/firezone/android/features/auth/ui/AuthActivity.kt @@ -4,7 +4,7 @@ package dev.firezone.android.features.auth.ui import android.content.Intent import android.net.Uri import android.os.Bundle -import android.util.Log +import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity @@ -14,6 +14,7 @@ import dev.firezone.android.R import dev.firezone.android.core.presentation.MainActivity import dev.firezone.android.databinding.ActivityAuthBinding import dev.firezone.android.util.CustomTabsHelper +import java.lang.Exception @AndroidEntryPoint class AuthActivity : AppCompatActivity(R.layout.activity_auth) { @@ -38,14 +39,10 @@ class AuthActivity : AppCompatActivity(R.layout.activity_auth) { private fun setupActionObservers() { viewModel.actionLiveData.observe(this) { action -> - Log.d("AuthActivity", "setupActionObservers: $action") when (action) { is AuthViewModel.ViewAction.LaunchAuthFlow -> setupWebView(action.url) is AuthViewModel.ViewAction.NavigateToSignInFragment -> { - startActivity( - Intent(this, MainActivity::class.java), - ) - finish() + navigateToSignIn() } is AuthViewModel.ViewAction.ShowError -> showError() else -> {} @@ -54,10 +51,40 @@ class AuthActivity : AppCompatActivity(R.layout.activity_auth) { } private fun setupWebView(url: String) { - val intent = CustomTabsIntent.Builder().build() - intent.intent.setPackage(CustomTabsHelper.getPackageNameToUse(this@AuthActivity)) - intent.launchUrl(this@AuthActivity, Uri.parse(url)) + if (CustomTabsHelper.checkIfChromeIsInstalled(this)) { + val intent = CustomTabsIntent.Builder().build() + val packageName = CustomTabsHelper.getPackageNameToUse(this) + if (CustomTabsHelper.checkIfChromeAppIsDefault()) { + if (packageName != null) { + intent.intent.setPackage(packageName) + } + } else { + intent.intent.setPackage(CustomTabsHelper.STABLE_PACKAGE) + } + + try { + intent.launchUrl(this@AuthActivity, Uri.parse(url)) + finish() + } catch (e: Exception) { + showChromeAppRequiredError() + } + } else { + showChromeAppRequiredError() + } } + + private fun showChromeAppRequiredError() { + Toast.makeText(this, getString(R.string.signing_in_requires_chrome_browser), Toast.LENGTH_LONG).show() + navigateToSignIn() + } + + private fun navigateToSignIn() { + startActivity( + Intent(this, MainActivity::class.java), + ) + finish() + } + private fun showError() { AlertDialog.Builder(this) .setTitle(R.string.error_dialog_title) diff --git a/kotlin/android/app/src/main/java/dev/firezone/android/features/signin/ui/SignInFragment.kt b/kotlin/android/app/src/main/java/dev/firezone/android/features/signin/ui/SignInFragment.kt index 01e3ec7ad..2840f0fa8 100644 --- a/kotlin/android/app/src/main/java/dev/firezone/android/features/signin/ui/SignInFragment.kt +++ b/kotlin/android/app/src/main/java/dev/firezone/android/features/signin/ui/SignInFragment.kt @@ -34,7 +34,6 @@ internal class SignInFragment : Fragment(R.layout.fragment_sign_in) { AuthActivity::class.java, ), ) - requireActivity().finish() } btSettings.setOnClickListener { findNavController().navigate( diff --git a/kotlin/android/app/src/main/java/dev/firezone/android/util/CustomTabsHelper.kt b/kotlin/android/app/src/main/java/dev/firezone/android/util/CustomTabsHelper.kt index 7f6c7b01c..d2a2233ba 100644 --- a/kotlin/android/app/src/main/java/dev/firezone/android/util/CustomTabsHelper.kt +++ b/kotlin/android/app/src/main/java/dev/firezone/android/util/CustomTabsHelper.kt @@ -3,7 +3,10 @@ package dev.firezone.android.util import android.content.Context import android.content.Intent +import android.content.pm.PackageManager import android.net.Uri +import android.os.Build + class CustomTabsHelper { companion object { val STABLE_PACKAGE = "com.android.chrome" @@ -46,5 +49,23 @@ class CustomTabsHelper { } return sPackageNameToUse } + + fun checkIfChromeAppIsDefault() = + sPackageNameToUse == STABLE_PACKAGE || + sPackageNameToUse == BETA_PACKAGE || + sPackageNameToUse == DEV_PACKAGE || + sPackageNameToUse == LOCAL_PACKAGE + + fun checkIfChromeIsInstalled(context: Context): Boolean = try { + val info = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + context.packageManager.getPackageInfo(STABLE_PACKAGE, PackageManager.PackageInfoFlags.of(0L)) + } else { + @Suppress("DEPRECATION") + context.packageManager.getPackageInfo(STABLE_PACKAGE, 0) + } + info.applicationInfo.enabled + } catch (e: PackageManager.NameNotFoundException) { + false + } } } diff --git a/kotlin/android/app/src/main/res/values/strings.xml b/kotlin/android/app/src/main/res/values/strings.xml index 5303d3571..d8b9a91fd 100644 --- a/kotlin/android/app/src/main/res/values/strings.xml +++ b/kotlin/android/app/src/main/res/values/strings.xml @@ -27,6 +27,7 @@ Request Permission Enter team id Sign In (Debug User) + Signing in requires chrome browser