浏览代码

Merge pull request #2598 from nextcloud/bugfix/openNotification

Bugfix/open notification
Marcel Hibbe 2 年之前
父节点
当前提交
b3ba468bb5

+ 27 - 8
app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt

@@ -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() {
+        super.onStart()
         Log.d(TAG, "onStart: Activity: " + System.identityHashCode(this).toString())
+        logRouterBackStack(router!!)
 
-        super.onStart()
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            checkIfWeAreSecure()
+            lockScreenIfConditionsApply()
         }
-
-        handleActionFromContact(intent)
     }
 
     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"
     }

+ 13 - 0
app/src/main/java/com/nextcloud/talk/controllers/LockedController.kt

@@ -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) {

+ 30 - 30
app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt

@@ -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
                     }

+ 36 - 16
app/src/main/java/com/nextcloud/talk/utils/ConductorRemapping.kt

@@ -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())
     }
 }

+ 20 - 6
app/src/main/java/com/nextcloud/talk/utils/SecurityUtils.java

@@ -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);

+ 8 - 8
app/src/main/res/layout/controller_settings.xml

@@ -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"