hide background while authenticating & other improvements

This commit is contained in:
IndusAryan 2024-01-08 15:53:50 +05:30
parent 15d75e5194
commit 5bc9b413d5
4 changed files with 63 additions and 24 deletions

View file

@ -28,6 +28,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.children import androidx.core.view.children
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.marginStart import androidx.core.view.marginStart
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
@ -128,6 +129,7 @@ import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus
import com.lagradost.cloudstream3.utils.BackupUtils.backup import com.lagradost.cloudstream3.utils.BackupUtils.backup
import com.lagradost.cloudstream3.utils.BackupUtils.setUpBackup import com.lagradost.cloudstream3.utils.BackupUtils.setUpBackup
import com.lagradost.cloudstream3.utils.BiometricAuthenticator import com.lagradost.cloudstream3.utils.BiometricAuthenticator
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.TAG
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.isTruePhone import com.lagradost.cloudstream3.utils.BiometricAuthenticator.isTruePhone
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.promptInfo import com.lagradost.cloudstream3.utils.BiometricAuthenticator.promptInfo
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
@ -166,7 +168,6 @@ import kotlin.math.absoluteValue
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.system.exitProcess import kotlin.system.exitProcess
//https://github.com/videolan/vlc-android/blob/3706c4be2da6800b3d26344fc04fab03ffa4b860/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt#L1898 //https://github.com/videolan/vlc-android/blob/3706c4be2da6800b3d26344fc04fab03ffa4b860/application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt#L1898
//https://wiki.videolan.org/Android_Player_Intents/ //https://wiki.videolan.org/Android_Player_Intents/
@ -285,7 +286,7 @@ var app = Requests(responseParser = object : ResponseParser {
defaultHeaders = mapOf("user-agent" to USER_AGENT) defaultHeaders = mapOf("user-agent" to USER_AGENT)
} }
class MainActivity : AppCompatActivity(), ColorPickerDialogListener { class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricAuthenticator.BiometricAuthCallback {
companion object { companion object {
const val TAG = "MAINACT" const val TAG = "MAINACT"
const val ANIMATED_OUTLINE : Boolean = false const val ANIMATED_OUTLINE : Boolean = false
@ -1161,9 +1162,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
val noAccounts = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false) || accounts.count() <= 1 val noAccounts = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false) || accounts.count() <= 1
if (isTruePhone() && authEnabled && noAccounts ) { if (isTruePhone() && authEnabled && noAccounts ) {
BiometricAuthenticator.initializeBiometrics(this@MainActivity)
BiometricAuthenticator.initializeBiometrics(this@MainActivity, this)
BiometricAuthenticator.checkBiometricAvailability() BiometricAuthenticator.checkBiometricAvailability()
BiometricAuthenticator.biometricPrompt.authenticate(promptInfo) BiometricAuthenticator.biometricPrompt.authenticate(promptInfo)
binding?.navHostFragment?.isInvisible = true // hide background while authenticating
} }
// Automatically enable jsdelivr if cant connect to raw.githubusercontent.com // Automatically enable jsdelivr if cant connect to raw.githubusercontent.com
@ -1621,6 +1624,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
) )
} }
override fun onAuthenticationSuccess() { /** Biometric stuff **/
// make background (nav host fragment) visible again
binding?.navHostFragment?.isInvisible = false
}
private var backPressedCallback: OnBackPressedCallback? = null private var backPressedCallback: OnBackPressedCallback? = null
private fun attachBackPressedCallback() { private fun attachBackPressedCallback() {

View file

@ -24,7 +24,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.selectedKeyIndex
import com.lagradost.cloudstream3.utils.DataStoreHelper.setAccount import com.lagradost.cloudstream3.utils.DataStoreHelper.setAccount
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
class AccountSelectActivity : AppCompatActivity() { class AccountSelectActivity : AppCompatActivity(), BiometricAuthenticator.BiometricAuthCallback {
lateinit var viewModel: AccountViewModel lateinit var viewModel: AccountViewModel
@ -43,7 +43,6 @@ class AccountSelectActivity : AppCompatActivity() {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_enabled_key), false) val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_enabled_key), false)
val skipStartup = settingsManager.getBoolean( val skipStartup = settingsManager.getBoolean(
getString(R.string.skip_startup_account_select_key), getString(R.string.skip_startup_account_select_key),
false false
@ -54,7 +53,7 @@ class AccountSelectActivity : AppCompatActivity() {
fun askBiometricAuth() { fun askBiometricAuth() {
if (BiometricAuthenticator.isTruePhone() && authEnabled) { if (BiometricAuthenticator.isTruePhone() && authEnabled) {
BiometricAuthenticator.initializeBiometrics(this) BiometricAuthenticator.initializeBiometrics(this@AccountSelectActivity, this)
BiometricAuthenticator.checkBiometricAvailability() BiometricAuthenticator.checkBiometricAvailability()
BiometricAuthenticator.biometricPrompt.authenticate(BiometricAuthenticator.promptInfo) BiometricAuthenticator.biometricPrompt.authenticate(BiometricAuthenticator.promptInfo)
} }
@ -179,4 +178,7 @@ class AccountSelectActivity : AppCompatActivity() {
startActivity(mainIntent) startActivity(mainIntent)
finish() // Finish the account selection activity finish() // Finish the account selection activity
} }
override fun onAuthenticationSuccess() {
//ask github.com/IndusAryan if confusion occurs
}
} }

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.utils package com.lagradost.cloudstream3.utils
import android.app.Activity import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
@ -25,8 +27,11 @@ object BiometricAuthenticator {
lateinit var promptInfo: BiometricPrompt.PromptInfo lateinit var promptInfo: BiometricPrompt.PromptInfo
const val TAG = "cs3Auth" const val TAG = "cs3Auth"
fun initializeBiometrics(activity: Activity) { private var authCallback: BiometricAuthCallback? = null
fun initializeBiometrics(activity: Activity, callback: BiometricAuthCallback) {
val executor = ContextCompat.getMainExecutor(activity) val executor = ContextCompat.getMainExecutor(activity)
authCallback = callback // to listen success authentication
biometricManager = BiometricManager.from(activity) biometricManager = BiometricManager.from(activity)
biometricPrompt = BiometricPrompt(activity as AppCompatActivity, executor, object : BiometricPrompt.AuthenticationCallback() { biometricPrompt = BiometricPrompt(activity as AppCompatActivity, executor, object : BiometricPrompt.AuthenticationCallback() {
@ -40,6 +45,7 @@ object BiometricAuthenticator {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result) super.onAuthenticationSucceeded(result)
Log.d(TAG, "Biometric succeeded.") Log.d(TAG, "Biometric succeeded.")
unblockMain() //to make background visible after authenticating
} }
override fun onAuthenticationFailed() { override fun onAuthenticationFailed() {
@ -50,19 +56,29 @@ object BiometricAuthenticator {
} }
}) })
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
promptInfo = BiometricPrompt.PromptInfo.Builder() promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Unlock CloudStream") .setTitle("Unlock CloudStream")
//.setSubtitle("Log in using your biometric credential") //.setSubtitle("Log in using your biometric credential")
//.setNegativeButtonText("Use account password") //.setNegativeButtonText("Use account password")
.setAllowedAuthenticators(BIOMETRIC_WEAK or BIOMETRIC_STRONG or DEVICE_CREDENTIAL) .setAllowedAuthenticators(BIOMETRIC_WEAK or BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
.build() .build()
} else if (context?.let { deviceHasPasswordPinLock(it) } == true) {
@Suppress("DEPRECATION")
promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Unlock CloudStream")
.setDeviceCredentialAllowed(true)
.build()
}
} }
fun checkBiometricAvailability() { fun checkBiometricAvailability() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Strong and credential bundle cannot be checked at same time in API < A11 (R) // Strong and device credential bundle cannot be checked at same time in API < A11 (R)
when (biometricManager.canAuthenticate(BIOMETRIC_WEAK or BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) { when (biometricManager.canAuthenticate(BIOMETRIC_WEAK or BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) {
BiometricManager.BIOMETRIC_SUCCESS -> BiometricManager.BIOMETRIC_SUCCESS ->
Log.d(TAG, "App can authenticate.") Log.d(TAG, "App can authenticate.")
@ -74,10 +90,10 @@ object BiometricAuthenticator {
Log.d(TAG, "Biometric authentication is currently unavailable.") Log.d(TAG, "Biometric authentication is currently unavailable.")
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED ->
showToast(R.string.biometric_not_enrolled, Toast.LENGTH_SHORT) showToast(R.string.biometric_not_enrolled, Toast.LENGTH_LONG)
BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED ->
showToast(R.string.biometric_update_required, Toast.LENGTH_SHORT) showToast(R.string.biometric_update_required, Toast.LENGTH_LONG)
BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED ->
showToast(R.string.biometric_unsupported, Toast.LENGTH_SHORT) showToast(R.string.biometric_unsupported, Toast.LENGTH_SHORT)
@ -92,25 +108,25 @@ object BiometricAuthenticator {
when (biometricManager.canAuthenticate(BIOMETRIC_WEAK or BIOMETRIC_STRONG)) { when (biometricManager.canAuthenticate(BIOMETRIC_WEAK or BIOMETRIC_STRONG)) {
BiometricManager.BIOMETRIC_SUCCESS -> BiometricManager.BIOMETRIC_SUCCESS ->
Log.d(TAG, "App can authenticate using biometrics.") Log.d(TAG, "App can authenticate using biometrics.")
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
Log.d(TAG, "No biometric features available on this device.") Log.d(TAG, "No biometric features available on this device.")
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
Log.e(TAG, "Biometric features are currently unavailable.") Log.e(TAG, "Biometric features are currently unavailable.")
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED ->
Log.e(TAG, "Biometric features are currently unavailable.") showToast(R.string.biometric_not_enrolled, Toast.LENGTH_LONG)
BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED ->
showToast(R.string.biometric_update_required, Toast.LENGTH_SHORT) showToast(R.string.biometric_update_required, Toast.LENGTH_LONG)
BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED ->
showToast(R.string.biometric_unsupported, Toast.LENGTH_SHORT) showToast(R.string.biometric_unsupported, Toast.LENGTH_SHORT)
BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> BiometricManager.BIOMETRIC_STATUS_UNKNOWN ->
Log.d(TAG, "Unknown error encountered while authenticating fingerprint.") Log.d(TAG, "Unknown error encountered while authenticating fingerprint.")
} }
} }
@ -120,4 +136,17 @@ object BiometricAuthenticator {
fun isTruePhone(): Boolean { fun isTruePhone(): Boolean {
return !isTrueTvSettings() && !isTvSettings() && context?.isEmulatorSettings() != true return !isTrueTvSettings() && !isTvSettings() && context?.isEmulatorSettings() != true
} }
fun unblockMain() {
authCallback?.onAuthenticationSuccess()
}
private fun deviceHasPasswordPinLock(con: Context): Boolean {
val keyManager = con.getSystemService(AppCompatActivity.KEYGUARD_SERVICE) as KeyguardManager
return keyManager.isKeyguardSecure
}
interface BiometricAuthCallback {
fun onAuthenticationSuccess()
}
} }

View file

@ -742,11 +742,11 @@
<string name="auto_rotate_video_desc">Enable automatic switching of screen orientation based on video orientation</string> <string name="auto_rotate_video_desc">Enable automatic switching of screen orientation based on video orientation</string>
<string name="auto_rotate_video">Auto rotate</string> <string name="auto_rotate_video">Auto rotate</string>
<string name="biometric_setting">Use Fingerprint sensor authentication</string> <string name="biometric_setting">Fingerprint sensor authentication</string>
<string name="biometric_success">Fingerprint authentication succeeded</string> <string name="biometric_success">Fingerprint authentication succeeded</string>
<string name="biometric_failed">Fingerprint authentication failed</string> <string name="biometric_failed">Fingerprint authentication failed</string>
<string name="biometric_prompt_title">Unlock CloudStream</string> <string name="biometric_prompt_title">Unlock CloudStream</string>
<string name="biometric_not_enrolled">No biometric credentials are enrolled</string> <string name="biometric_not_enrolled">Please add fingerprint or screen lock or disable setting</string>
<string name="biometric_update_required">Please update software and security patches.</string> <string name="biometric_update_required">Please update software and security patches.</string>
<string name="biometric_unsupported">Biometric authentication is not supported on this device</string> <string name="biometric_unsupported">Biometric authentication is not supported on this device</string>
<string name="biometric_enabled_key" translatable="false">biometric_key</string> <string name="biometric_enabled_key" translatable="false">biometric_key</string>