diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index fdeb3e45..6308117b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -19,6 +19,7 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import android.widget.Toast +import android.widget.Toast.LENGTH_LONG import androidx.activity.OnBackPressedCallback import androidx.activity.result.ActivityResultLauncher import androidx.annotation.IdRes @@ -1208,26 +1209,21 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricAu changeStatusBarState(isEmulatorSettings()) /** Biometric stuff for users without accounts **/ - val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_enabled_key), false) + val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_key), false) val noAccounts = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false) || accounts.count() <= 1 if (isTruePhone() && authEnabled && noAccounts) { if (deviceHasPasswordPinLock(this)) { - startBiometricAuthentication(this, - R.string.biometric_authentication_title, - false - ) + startBiometricAuthentication(this, R.string.biometric_authentication_title, false) BiometricAuthenticator.promptInfo?.let { - BiometricAuthenticator.biometricPrompt?.authenticate( - it - ) + BiometricAuthenticator.biometricPrompt?.authenticate(it) } // hide background while authenticating, Sorry moms & dads 🙏 binding?.navHostFragment?.isInvisible = true } else { - showToast(R.string.phone_not_secured, Toast.LENGTH_LONG) + showToast(R.string.phone_not_secured, LENGTH_LONG) } } 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 2bb4746b..c6e1e1fe 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 @@ -47,7 +47,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricAuthenticator.Biomet ) val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) - val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_enabled_key), false) + val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_key), false) val skipStartup = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false ) || accounts.count() <= 1 @@ -57,11 +57,8 @@ class AccountSelectActivity : AppCompatActivity(), BiometricAuthenticator.Biomet if (isTruePhone() && authEnabled) { if (deviceHasPasswordPinLock(this)) { - startBiometricAuthentication( - this, - R.string.biometric_authentication_title, - false - ) + startBiometricAuthentication(this, R.string.biometric_authentication_title, false) + BiometricAuthenticator.promptInfo?.let { BiometricAuthenticator.biometricPrompt?.authenticate(it) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt index aa5a3182..d04757da 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt @@ -13,6 +13,7 @@ import androidx.fragment.app.FragmentActivity import androidx.preference.PreferenceFragmentCompat import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser +import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.databinding.AccountManagmentBinding @@ -32,7 +33,10 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSet import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setToolBarScrollFlags import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar +import com.lagradost.cloudstream3.utils.AppUtils.html +import com.lagradost.cloudstream3.utils.BackupUtils import com.lagradost.cloudstream3.utils.Coroutines.ioSafe +import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialogText import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.setImage @@ -256,6 +260,19 @@ class SettingsAccount : PreferenceFragmentCompat() { hideKeyboard() setPreferencesFromResource(R.xml.settings_account, rootKey) + getPref(R.string.biometric_key)?.setOnPreferenceClickListener { + + BackupUtils.backup(activity) + val title = activity?.getString(R.string.biometric_setting) + val warning = activity?.getString(R.string.biometric_warning) + activity?.showBottomDialogText( + title as String, + warning.html() + ) { onDialogDismissedEvent } + + true + } + val syncApis = listOf( R.string.mal_key to malApi, diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt index e50131fe..db001ef5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt @@ -66,6 +66,7 @@ object BackupUtils { OPEN_SUBTITLES_USER_KEY, "nginx_user", // Nginx user key + "biometric_key" // can lock down users if backup is shared on a incompatible device ) /** false if blacklisted key */ 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 96e73cd3..de9b9963 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/BiometricAuthenticator.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/BiometricAuthenticator.kt @@ -5,7 +5,6 @@ import android.app.KeyguardManager import android.content.Context import android.os.Build import android.util.Log -import android.widget.Toast.LENGTH_SHORT import androidx.appcompat.app.AppCompatActivity import androidx.biometric.BiometricManager import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG @@ -41,9 +40,10 @@ object BiometricAuthenticator { override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) - showToast("$errString", LENGTH_SHORT) + showToast("$errString") Log.e(TAG, "$errorCode") failedAttempts++ + if (failedAttempts >= MAX_FAILED_ATTEMPTS) { failedAttempts = 0 activity.finish() @@ -70,6 +70,7 @@ object BiometricAuthenticator { }) } + @Suppress("DEPRECATION") // authentication dialog prompt builder private fun authenticationDialog( activity: Activity, @@ -77,6 +78,7 @@ object BiometricAuthenticator { setDeviceCred: Boolean, ) { val description = activity.getString(R.string.biometric_prompt_description) + if (setDeviceCred) { // For API level > 30, Newer API setAllowedAuthenticators is used if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { @@ -87,17 +89,18 @@ object BiometricAuthenticator { .setDescription(description) .setAllowedAuthenticators(authFlag) .build() + } else { - @Suppress("DEPRECATION") + // for apis < 30 promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle(activity.getString(title)) .setDescription(description) .setDeviceCredentialAllowed(true) .build() } + } else { // fallback for A12+ when both fingerprint & Face unlock is absent but PIN is set - @Suppress("DEPRECATION") promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle(activity.getString(title)) .setDescription(description) @@ -107,9 +110,11 @@ object BiometricAuthenticator { } private fun isBiometricHardWareAvailable(): Boolean { + // authentication occurs only when this is true and device is truly capable var result = false if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + when (biometricManager?.canAuthenticate( DEVICE_CREDENTIAL or BIOMETRIC_STRONG or BIOMETRIC_WEAK )) { @@ -121,6 +126,7 @@ object BiometricAuthenticator { BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> result = true BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> result = false } + } else { @Suppress("DEPRECATION") when (biometricManager?.canAuthenticate()) { @@ -137,7 +143,7 @@ object BiometricAuthenticator { return result } - // checks if device is secured or not + // checks if device is secured i.e has at least some type of lock fun deviceHasPasswordPinLock(context: Context?): Boolean { val keyMgr = context?.getSystemService(AppCompatActivity.KEYGUARD_SERVICE) as? KeyguardManager @@ -160,7 +166,7 @@ object BiometricAuthenticator { promptInfo?.let { biometricPrompt?.authenticate(it) } } else { - showToast(R.string.biometric_unsupported, LENGTH_SHORT) + showToast(R.string.biometric_unsupported) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 79b3c813..244095ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -747,11 +747,13 @@ Unlock CloudStream - Fingerprint sensor authentication - biometric_key + Fingerprint/Face unlock authentication + biometric_key Password/PIN Authentication Biometric authentication is not supported on this device Please disable fingerprint authentication if device has no lock. This window will close after few failed attempts. You\'ll have to restart the App. - + Your CloudStream data has been backed up now, although probability of this rare case is very low but all + devices behave differently, in case you get locked down from accessing the app in worst case scenario, + Clear the app data wholly and restore the backup. Any inconvenience if arrived is deeply regretted. diff --git a/app/src/main/res/xml/settings_account.xml b/app/src/main/res/xml/settings_account.xml index d0316f96..39e21162 100644 --- a/app/src/main/res/xml/settings_account.xml +++ b/app/src/main/res/xml/settings_account.xml @@ -24,7 +24,7 @@ android:title="@string/skip_startup_account_select_pref" />