Merge pull request #2598 from nextcloud/bugfix/openNotification

Bugfix/open notification
This commit is contained in:
Marcel Hibbe 2022-11-30 14:01:35 +01:00 committed by GitHub
commit b3ba468bb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 70 deletions

View File

@ -37,6 +37,7 @@ import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
import com.google.android.material.snackbar.Snackbar
import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
@ -144,14 +145,13 @@ class MainActivity : BaseActivity(), ActionBarProvider {
}
override fun onStart() {
Log.d(TAG, "onStart: Activity: " + System.identityHashCode(this).toString())
super.onStart()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkIfWeAreSecure()
}
Log.d(TAG, "onStart: Activity: " + System.identityHashCode(this).toString())
logRouterBackStack(router!!)
handleActionFromContact(intent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
lockScreenIfConditionsApply()
}
}
override fun onResume() {
@ -324,7 +324,7 @@ class MainActivity : BaseActivity(), ActionBarProvider {
}
@RequiresApi(api = Build.VERSION_CODES.M)
fun checkIfWeAreSecure() {
fun lockScreenIfConditionsApply() {
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
if (keyguardManager.isKeyguardSecure && appPreferences.isScreenLocked) {
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)) {
@ -335,14 +335,15 @@ class MainActivity : BaseActivity(), ActionBarProvider {
.popChangeHandler(VerticalChangeHandler())
.tag(LockedController.TAG)
)
logRouterBackStack(router!!)
}
}
}
}
override fun onNewIntent(intent: Intent) {
Log.d(TAG, "onNewIntent Activity: " + System.identityHashCode(this).toString())
super.onNewIntent(intent)
Log.d(TAG, "onNewIntent Activity: " + System.identityHashCode(this).toString())
handleActionFromContact(intent)
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
@ -353,10 +354,16 @@ class MainActivity : BaseActivity(), ActionBarProvider {
intent.extras?.let { callNotificationIntent.putExtras(it) }
startActivity(callNotificationIntent)
} else {
logRouterBackStack(router!!)
remapChatController(
router!!, intent.getParcelableExtra<User>(KEY_USER_ENTITY)!!.id!!,
intent.getStringExtra(KEY_ROOM_TOKEN)!!, intent.extras!!, false, true
router!!,
intent.getParcelableExtra<User>(KEY_USER_ENTITY)!!.id!!,
intent.getStringExtra(KEY_ROOM_TOKEN)!!,
intent.extras!!,
false,
true
)
logRouterBackStack(router!!)
}
}
}
@ -371,6 +378,18 @@ class MainActivity : BaseActivity(), ActionBarProvider {
}
}
private fun logRouterBackStack(router: Router) {
if (BuildConfig.DEBUG) {
val backstack = router.backstack
var routerTransaction: RouterTransaction?
Log.d(TAG, " backstack size: " + router.backstackSize)
for (i in 0 until router.backstackSize) {
routerTransaction = backstack[i]
Log.d(TAG, " controller: " + routerTransaction.controller)
}
}
}
companion object {
private const val TAG = "MainActivity"
}

View File

@ -73,6 +73,7 @@ class LockedController : BaseController(R.layout.controller_locked) {
@RequiresApi(api = Build.VERSION_CODES.M)
override fun onAttach(view: View) {
super.onAttach(view)
Log.d(TAG, "onAttach")
if (activity != null && resources != null) {
DisplayUtils.applyColorToStatusBar(
activity,
@ -86,6 +87,11 @@ class LockedController : BaseController(R.layout.controller_locked) {
checkIfWeAreSecure()
}
override fun onDetach(view: View) {
super.onDetach(view)
Log.d(TAG, "onDetach")
}
@RequiresApi(api = Build.VERSION_CODES.M)
fun unlock() {
checkIfWeAreSecure()
@ -139,14 +145,21 @@ class LockedController : BaseController(R.layout.controller_locked) {
val keyguardManager = activity?.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager?
if (keyguardManager?.isKeyguardSecure == true && appPreferences!!.isScreenLocked) {
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences!!.screenLockTimeout)) {
Log.d(TAG, "showBiometricDialog because 'we are NOT authenticated'...")
showBiometricDialog()
} else {
Log.d(
TAG,
"popCurrentController because 'we are authenticated'. backstacksize= " +
router.backstack.size
)
router.popCurrentController()
}
}
}
private fun showAuthenticationScreen() {
Log.d(TAG, "showAuthenticationScreen")
val keyguardManager = activity?.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager?
val intent = keyguardManager?.createConfirmDeviceCredentialIntent(null, null)
if (intent != null) {

View File

@ -333,30 +333,30 @@ class SettingsController : BaseController(R.layout.controller_settings) {
}
private fun registerChangeListeners() {
appPreferences!!.registerProxyTypeListener(ProxyTypeChangeListener().also { proxyTypeChangeListener = it })
appPreferences!!.registerProxyCredentialsListener(
appPreferences.registerProxyTypeListener(ProxyTypeChangeListener().also { proxyTypeChangeListener = it })
appPreferences.registerProxyCredentialsListener(
ProxyCredentialsChangeListener().also {
proxyCredentialsChangeListener = it
}
)
appPreferences!!.registerScreenSecurityListener(
appPreferences.registerScreenSecurityListener(
ScreenSecurityChangeListener().also {
screenSecurityChangeListener = it
}
)
appPreferences!!.registerScreenLockListener(ScreenLockListener().also { screenLockChangeListener = it })
appPreferences!!.registerScreenLockTimeoutListener(
appPreferences.registerScreenLockListener(ScreenLockListener().also { screenLockChangeListener = it })
appPreferences.registerScreenLockTimeoutListener(
ScreenLockTimeoutListener().also {
screenLockTimeoutChangeListener = it
}
)
appPreferences!!.registerThemeChangeListener(ThemeChangeListener().also { themeChangeListener = it })
appPreferences!!.registerPhoneBookIntegrationChangeListener(
appPreferences.registerThemeChangeListener(ThemeChangeListener().also { themeChangeListener = it })
appPreferences.registerPhoneBookIntegrationChangeListener(
PhoneBookIntegrationChangeListener(this).also {
phoneBookIntegrationChangeListener = it
}
)
appPreferences!!.registerReadPrivacyChangeListener(
appPreferences.registerReadPrivacyChangeListener(
ReadPrivacyChangeListener().also {
readPrivacyChangeListener = it
}
@ -525,7 +525,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
}
private fun setupProxyTypeSettings() {
if (("No proxy" == appPreferences!!.proxyType) || appPreferences!!.proxyType == null) {
if (("No proxy" == appPreferences.proxyType) || appPreferences.proxyType == null) {
hideProxySettings()
} else {
showProxySettings()
@ -533,7 +533,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
}
private fun setupProxyCredentialSettings() {
if (appPreferences!!.proxyCredentials) {
if (appPreferences.proxyCredentials) {
showProxyCredentials()
} else {
hideProxyCredentials()
@ -655,16 +655,16 @@ class SettingsController : BaseController(R.layout.controller_settings) {
private fun setupCheckables() {
(binding.settingsScreenSecurity.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked =
appPreferences!!.isScreenSecured
appPreferences.isScreenSecured
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
(binding.settingsIncognitoKeyboard.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked =
appPreferences!!.isKeyboardIncognito
appPreferences.isKeyboardIncognito
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(binding.settingsIncognitoKeyboard.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked =
appPreferences!!.isKeyboardIncognito
appPreferences.isKeyboardIncognito
}
if (CapabilitiesUtilNew.isReadStatusAvailable(userManager.currentUser.blockingGet())) {
@ -675,19 +675,19 @@ class SettingsController : BaseController(R.layout.controller_settings) {
}
(binding.settingsPhoneBookIntegration.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked =
appPreferences!!.isPhoneBookIntegrationEnabled
appPreferences.isPhoneBookIntegrationEnabled
}
private fun setupScreenLockSetting() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val keyguardManager = context!!.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
if (keyguardManager.isKeyguardSecure) {
binding.settingsScreenLock.isEnabled = true
binding.settingsScreenLockTimeout.isEnabled = true
(binding.settingsScreenLock.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked =
appPreferences!!.isScreenLocked
binding.settingsScreenLockTimeout.isEnabled = appPreferences!!.isScreenLocked
if (appPreferences!!.isScreenLocked) {
appPreferences.isScreenLocked
binding.settingsScreenLockTimeout.isEnabled = appPreferences.isScreenLocked
if (appPreferences.isScreenLocked) {
binding.settingsScreenLockTimeout.alpha = ENABLED_ALPHA
} else {
binding.settingsScreenLockTimeout.alpha = DISABLED_ALPHA
@ -696,8 +696,8 @@ class SettingsController : BaseController(R.layout.controller_settings) {
} else {
binding.settingsScreenLock.isEnabled = false
binding.settingsScreenLockTimeout.isEnabled = false
appPreferences!!.removeScreenLock()
appPreferences!!.removeScreenLockTimeout()
appPreferences.removeScreenLock()
appPreferences.removeScreenLockTimeout()
(binding.settingsScreenLock.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked = false
binding.settingsScreenLock.alpha = DISABLED_ALPHA
binding.settingsScreenLockTimeout.alpha = DISABLED_ALPHA
@ -792,12 +792,12 @@ class SettingsController : BaseController(R.layout.controller_settings) {
.enqueue(OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java).build())
checkForPhoneNumber()
} else {
appPreferences!!.setPhoneBookIntegration(false)
appPreferences.setPhoneBookIntegration(false)
(binding.settingsPhoneBookIntegration.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked =
appPreferences!!.isPhoneBookIntegrationEnabled
appPreferences.isPhoneBookIntegrationEnabled
Toast.makeText(
context,
context!!.resources.getString(R.string.no_phone_book_integration_due_to_permissions),
context.resources.getString(R.string.no_phone_book_integration_due_to_permissions),
Toast.LENGTH_LONG
).show()
}
@ -806,7 +806,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
private inner class ScreenLockTimeoutListener : OnPreferenceValueChangedListener<String?> {
override fun onChanged(newValue: String?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SecurityUtils.createKey(appPreferences!!.screenLockTimeout)
SecurityUtils.createKey(appPreferences.screenLockTimeout)
}
}
}
@ -949,8 +949,8 @@ class SettingsController : BaseController(R.layout.controller_settings) {
.setTitle(R.string.nc_settings_phone_book_integration_phone_number_dialog_title)
.setMessage(R.string.nc_settings_phone_book_integration_phone_number_dialog_description)
.setView(phoneNumberLayoutWrapper)
.setPositiveButton(context!!.resources.getString(R.string.nc_common_set), null)
.setNegativeButton(context!!.resources.getString(R.string.nc_common_skip), null)
.setPositiveButton(context.resources.getString(R.string.nc_common_set), null)
.setNegativeButton(context.resources.getString(R.string.nc_common_skip), null)
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(phoneNumberInputLayout.context, dialogBuilder)
@ -994,13 +994,13 @@ class SettingsController : BaseController(R.layout.controller_settings) {
dialog.dismiss()
Toast.makeText(
context,
context!!.resources.getString(
context.resources.getString(
R.string.nc_settings_phone_book_integration_phone_number_dialog_success
),
Toast.LENGTH_LONG
).show()
} else {
textInputLayout.helperText = context!!.resources.getString(
textInputLayout.helperText = context.resources.getString(
R.string.nc_settings_phone_book_integration_phone_number_dialog_invalid
)
Log.d(TAG, "failed to set phoneNumber. statusCode=$statusCode")
@ -1008,7 +1008,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
}
override fun onError(e: Throwable) {
textInputLayout.helperText = context!!.resources.getString(
textInputLayout.helperText = context.resources.getString(
R.string.nc_settings_phone_book_integration_phone_number_dialog_invalid
)
Log.e(TAG, "setPhoneNumber error", e)
@ -1041,7 +1041,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
}
override fun onError(e: Throwable) {
appPreferences!!.setReadPrivacy(!newValue)
appPreferences.setReadPrivacy(!newValue)
(binding.settingsReadPrivacy.findViewById<View>(R.id.mp_checkable) as Checkable).isChecked =
!newValue
}

View File

@ -21,15 +21,19 @@
package com.nextcloud.talk.utils
import android.os.Bundle
import android.util.Log
import com.bluelinelabs.conductor.Router
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler
import com.nextcloud.talk.controllers.ChatController
import com.nextcloud.talk.controllers.ConversationsListController
import com.nextcloud.talk.controllers.LockedController
object ConductorRemapping {
private val TAG = ConductorRemapping::class.simpleName
fun remapChatController(
router: Router,
internalUserId: Long,
@ -48,20 +52,10 @@ object ConductorRemapping {
replaceTop: Boolean,
pushImmediately: Boolean
) {
val tag = "$internalUserId@$roomTokenOrId"
if (router.getControllerWithTag(tag) != null) {
val backstack = router.backstack
var routerTransaction: RouterTransaction? = null
for (i in 0 until router.backstackSize) {
if (tag == backstack[i].tag()) {
routerTransaction = backstack[i]
backstack.remove(routerTransaction)
break
}
}
val chatControllerTag = "$internalUserId@$roomTokenOrId"
backstack.add(routerTransaction)
router.setBackstack(backstack, HorizontalChangeHandler())
if (router.getControllerWithTag(chatControllerTag) != null) {
moveControllerToTop(router, chatControllerTag)
} else {
val pushChangeHandler = if (pushImmediately) {
SimpleSwapChangeHandler()
@ -70,29 +64,55 @@ object ConductorRemapping {
}
if (!replaceTop) {
if (!router.hasRootController()) {
Log.d(TAG, "router has no RootController. creating backstack with ConversationsListController")
val newBackstack = listOf(
RouterTransaction.with(ConversationsListController(Bundle()))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()),
RouterTransaction.with(ChatController(bundle))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()).tag(tag)
.popChangeHandler(HorizontalChangeHandler()).tag(chatControllerTag)
)
router.setBackstack(newBackstack, SimpleSwapChangeHandler())
} else {
Log.d(TAG, "router has RootController. pushing ChatController")
router.pushController(
RouterTransaction.with(ChatController(bundle))
.pushChangeHandler(pushChangeHandler)
.popChangeHandler(HorizontalChangeHandler()).tag(tag)
.popChangeHandler(HorizontalChangeHandler()).tag(chatControllerTag)
)
}
} else {
Log.d(TAG, "ChatController replace topController")
router.replaceTopController(
RouterTransaction.with(ChatController(bundle))
.pushChangeHandler(pushChangeHandler)
.popChangeHandler(HorizontalChangeHandler()).tag(tag)
.popChangeHandler(HorizontalChangeHandler()).tag(chatControllerTag)
)
}
}
if (router.getControllerWithTag(LockedController.TAG) != null) {
moveControllerToTop(router, LockedController.TAG)
}
}
private fun moveControllerToTop(router: Router, controllerTag: String) {
Log.d(TAG, "moving $controllerTag to top...")
val backstack = router.backstack
var routerTransaction: RouterTransaction? = null
for (i in 0 until router.backstackSize) {
if (controllerTag == backstack[i].tag()) {
routerTransaction = backstack[i]
backstack.remove(routerTransaction)
Log.d(TAG, "removed controller: " + routerTransaction.controller)
break
}
}
backstack.add(routerTransaction)
Log.d(TAG, "added controller to top: " + routerTransaction!!.controller)
router.setBackstack(backstack, HorizontalChangeHandler())
}
}

View File

@ -27,18 +27,32 @@ import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.UserNotAuthenticatedException;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.biometric.BiometricPrompt;
import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import javax.crypto.*;
import java.io.IOException;
import java.security.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import androidx.annotation.RequiresApi;
import androidx.biometric.BiometricPrompt;
public class SecurityUtils {
private static final String TAG = "SecurityUtils";
private static final String CREDENTIALS_KEY = "KEY_CREDENTIALS";
@ -68,8 +82,8 @@ public class SecurityUtils {
return false;
} catch (KeyPermanentlyInvalidatedException e) {
// This happens if the lock screen has been disabled or reset after the key was
// generated after the key was generated.
// Shouldnt really happen because we regenerate the key every time an activity
// generated.
// Shouldn't really happen because we regenerate the key every time an activity
// is created, but oh well
// Create key, and attempt again
createKey(screenLockTimeout);

View File

@ -197,6 +197,14 @@
apc:cardElevation="0dp"
apc:mpc_title="@string/nc_settings_privacy">
<com.yarolegovich.mp.MaterialSwitchPreference
android:id="@+id/settings_screen_lock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
apc:mp_default_value="@bool/value_false"
apc:mp_key="@string/nc_settings_screen_lock_key"
apc:mp_title="@string/nc_settings_screen_lock_title" />
<com.yarolegovich.mp.MaterialChoicePreference
android:id="@+id/settings_screen_lock_timeout"
android:layout_width="match_parent"
@ -208,14 +216,6 @@
apc:mp_show_value="onBottom"
apc:mp_title="@string/nc_settings_screen_lock_timeout_title" />
<com.yarolegovich.mp.MaterialSwitchPreference
android:id="@+id/settings_screen_lock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
apc:mp_default_value="@bool/value_false"
apc:mp_key="@string/nc_settings_screen_lock_key"
apc:mp_title="@string/nc_settings_screen_lock_title" />
<com.yarolegovich.mp.MaterialSwitchPreference
android:id="@+id/settings_screen_security"
android:layout_width="match_parent"