diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 03608533..d9c6694f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -135,6 +135,7 @@ import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.DataStoreHelper +import com.lagradost.cloudstream3.utils.DataStoreHelper.accounts import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching import com.lagradost.cloudstream3.utils.Event import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate @@ -1155,13 +1156,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { changeStatusBarState(isEmulatorSettings()) - /** Biometric Stuff **/ - val authEnabled = settingsManager.getBoolean( - getString(R.string.biometric_enabled_key), false) + /** Biometric stuff for users without accounts **/ + val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_enabled_key), false) + val noAccounts = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false) || accounts.count() <= 1 - if (isTruePhone() && authEnabled) { + if (isTruePhone() && authEnabled && noAccounts ) { BiometricAuthenticator.initializeBiometrics(this@MainActivity) - BiometricAuthenticator.checkBiometricAvailability(this@MainActivity) + BiometricAuthenticator.checkBiometricAvailability() BiometricAuthenticator.biometricPrompt.authenticate(promptInfo) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt index 23071f59..693f0c56 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt @@ -18,6 +18,7 @@ import com.lagradost.cloudstream3.ui.AutofitRecyclerView import com.lagradost.cloudstream3.ui.account.AccountAdapter.Companion.VIEW_TYPE_EDIT_ACCOUNT import com.lagradost.cloudstream3.ui.account.AccountAdapter.Companion.VIEW_TYPE_SELECT_ACCOUNT import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings +import com.lagradost.cloudstream3.utils.BiometricAuthenticator import com.lagradost.cloudstream3.utils.DataStoreHelper.accounts import com.lagradost.cloudstream3.utils.DataStoreHelper.selectedKeyIndex import com.lagradost.cloudstream3.utils.DataStoreHelper.setAccount @@ -41,6 +42,8 @@ class AccountSelectActivity : AppCompatActivity() { ) val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_enabled_key), false) + val skipStartup = settingsManager.getBoolean( getString(R.string.skip_startup_account_select_key), false @@ -48,6 +51,15 @@ class AccountSelectActivity : AppCompatActivity() { viewModel = ViewModelProvider(this)[AccountViewModel::class.java] + fun askBiometricAuth() { + + if (BiometricAuthenticator.isTruePhone() && authEnabled) { + BiometricAuthenticator.initializeBiometrics(this) + BiometricAuthenticator.checkBiometricAvailability() + BiometricAuthenticator.biometricPrompt.authenticate(BiometricAuthenticator.promptInfo) + } + } + // Don't show account selection if there is only // one account that exists if (!isEditingFromMainActivity && skipStartup) { @@ -158,6 +170,8 @@ class AccountSelectActivity : AppCompatActivity() { } else 6 } } + + askBiometricAuth() } private fun navigateToMainActivity() { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/BiometricAuthenticator.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/BiometricAuthenticator.kt index fd7aa525..6c1f068d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/BiometricAuthenticator.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/BiometricAuthenticator.kt @@ -1,9 +1,10 @@ package com.lagradost.cloudstream3.utils -import android.content.Context +import android.app.Activity import android.os.Build import android.util.Log import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity import androidx.biometric.BiometricManager import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK @@ -11,7 +12,8 @@ import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL import androidx.biometric.BiometricPrompt import androidx.core.content.ContextCompat import com.lagradost.cloudstream3.AcraApplication.Companion.context -import com.lagradost.cloudstream3.MainActivity +import com.lagradost.cloudstream3.CommonActivity.showToast +import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings @@ -21,80 +23,67 @@ object BiometricAuthenticator { private lateinit var biometricManager: BiometricManager lateinit var biometricPrompt: BiometricPrompt lateinit var promptInfo: BiometricPrompt.PromptInfo + const val TAG = "cs3Auth" - fun initializeBiometrics(activity: MainActivity) { + fun initializeBiometrics(activity: Activity) { val executor = ContextCompat.getMainExecutor(activity) biometricManager = BiometricManager.from(activity) - biometricPrompt = BiometricPrompt(activity, executor, object : BiometricPrompt.AuthenticationCallback() { + biometricPrompt = BiometricPrompt(activity as AppCompatActivity, executor, object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) - Toast.makeText(context?.applicationContext, "Authentication error: $errString", Toast.LENGTH_SHORT).show() + Log.d(TAG, "Authentication error: $errString") activity.finish() } override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) - Log.d("Cs3Auth", "Biometric succeeded.") + Log.d(TAG, "Biometric succeeded.") } override fun onAuthenticationFailed() { super.onAuthenticationFailed() - Toast.makeText(context?.applicationContext, "Authentication failed", Toast.LENGTH_SHORT).show() + Log.d(TAG, "Authentication error") + showToast(R.string.biometric_failed, Toast.LENGTH_SHORT) activity.finish() } }) promptInfo = BiometricPrompt.PromptInfo.Builder() - .setTitle("CloudStream") - .setSubtitle("Log in using your biometric credential") + .setTitle("Unlock CloudStream") + //.setSubtitle("Log in using your biometric credential") //.setNegativeButtonText("Use account password") .setAllowedAuthenticators(BIOMETRIC_WEAK or BIOMETRIC_STRONG or DEVICE_CREDENTIAL) .build() } - fun checkBiometricAvailability(context: Context) { + fun checkBiometricAvailability() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - // Strong and credential bundle cannot be checked at same time in API < 11 + // Strong and credential bundle cannot be checked at same time in API < A11 (R) when (biometricManager.canAuthenticate(BIOMETRIC_WEAK or BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) { BiometricManager.BIOMETRIC_SUCCESS -> - Log.d("Cs3Auth", "App can authenticate.") + Log.d(TAG, "App can authenticate.") BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> - Log.d("Cs3Auth", "No biometric sensor found.") + Log.d(TAG, "No biometric sensor found.") BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> - Log.d("Cs3Auth", "Biometric authentication is currently unavailable.") + Log.d(TAG, "Biometric authentication is currently unavailable.") BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> - Toast.makeText( - context, - "No biometric credentials are enrolled", - Toast.LENGTH_SHORT - ).show() + showToast(R.string.biometric_not_enrolled, Toast.LENGTH_SHORT) - BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> { - Toast.makeText( - context, - "Please update your software and security patches.", - Toast.LENGTH_SHORT - ).show() - } + BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> + showToast(R.string.biometric_update_required, Toast.LENGTH_SHORT) - BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> { - Toast.makeText( - context, - "Please update your software and security patches.", - Toast.LENGTH_SHORT - ).show() - } + BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> + showToast(R.string.biometric_unsupported, Toast.LENGTH_SHORT) - BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> { - Log.d("Cs3Auth", "Unknown error encountered(Biometric data failed).") - } + BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> + Log.e(TAG, "Unknown error encountered while authenticating fingerprint.") } } @@ -103,33 +92,26 @@ object BiometricAuthenticator { when (biometricManager.canAuthenticate(BIOMETRIC_WEAK or BIOMETRIC_STRONG)) { BiometricManager.BIOMETRIC_SUCCESS -> - Log.d("Cs3Auth", "App can authenticate using biometrics.") + Log.d(TAG, "App can authenticate using biometrics.") + BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> - Log.e("Cs3Auth", "No biometric features available on this device.") + Log.d(TAG, "No biometric features available on this device.") + BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> - Log.e("Cs3Auth", "Biometric features are currently unavailable.") + Log.e(TAG, "Biometric features are currently unavailable.") + BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> - Log.e("Cs3Auth", "Biometric features are currently unavailable.") + Log.e(TAG, "Biometric features are currently unavailable.") - BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> { - Toast.makeText( - context, - "Please update your software and security patches.", - Toast.LENGTH_SHORT - ).show() - } + BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> + showToast(R.string.biometric_update_required, Toast.LENGTH_SHORT) - BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> { - Toast.makeText( - context, - "Please update your software and security patches.", - Toast.LENGTH_SHORT - ).show() - } + BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> + showToast(R.string.biometric_unsupported, Toast.LENGTH_SHORT) + + BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> + Log.d(TAG, "Unknown error encountered while authenticating fingerprint.") - BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> { - Log.d("Cs3Auth", "Unknown error encountered(Biometric data failed).") - } } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 062a7285..dc981408 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,7 +67,7 @@ enable_nsfw_on_providers_key skip_startup_account_select_key enable_skip_op_from_database - biometric_key + %d %s | %s %s • %s @@ -741,5 +741,14 @@ auto_rotate_video_key Enable automatic switching of screen orientation based on video orientation Auto rotate - Use Fingerprint authentication + + Use Fingerprint sensor authentication + Fingerprint authentication succeeded + Fingerprint authentication failed + Unlock CloudStream + No biometric credentials are enrolled + Please update software and security patches. + Biometric authentication is not supported on this device + biometric_key +