From f144b64365c96ac4f1f2ffd19e03b76fb4eb981b Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Wed, 13 Nov 2024 14:04:16 +0100 Subject: [PATCH] fix NPE in restoreMessageQueue currentConversation was not yet initialized in ChatActivity. In the future this may be better handled via StateFlows. For now it's solved via arguments. Without the fix, this NPE appeared: Exception java.lang.RuntimeException: at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4768) at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4801) at android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:54) at android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:45) at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:176) at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2215) at android.os.Handler.dispatchMessage (Handler.java:106) at android.os.Looper.loopOnce (Looper.java:346) at android.os.Looper.loop (Looper.java:475) at android.app.ActivityThread.main (ActivityThread.java:7889) at java.lang.reflect.Method.invoke at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1009) Caused by java.lang.NullPointerException: at com.nextcloud.talk.chat.MessageInputFragment.onResume (MessageInputFragment.kt:146) at androidx.fragment.app.Fragment.performResume (Fragment.java:3180) at androidx.fragment.app.FragmentStateManager.resume (FragmentStateManager.java:606) at androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:285) at androidx.fragment.app.FragmentStore.moveToExpectedState (FragmentStore.java:113) at androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1433) at androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:2977) at androidx.fragment.app.FragmentManager.dispatchResume (FragmentManager.java:2909) at androidx.fragment.app.FragmentController.dispatchResume (FragmentController.java:285) at androidx.fragment.app.FragmentActivity.onResumeFragments (FragmentActivity.java:334) at androidx.fragment.app.FragmentActivity.onPostResume (FragmentActivity.java:323) at androidx.appcompat.app.AppCompatActivity.onPostResume (AppCompatActivity.java:245) at android.app.Activity.performResume (Activity.java:8215) at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4758) Signed-off-by: Marcel Hibbe --- .../com/nextcloud/talk/chat/ChatActivity.kt | 17 +++++++++++++---- .../nextcloud/talk/chat/MessageInputFragment.kt | 12 ++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 9cbec6884..86f6e5cd3 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -411,12 +411,11 @@ class ChatActivity : setContentView(binding.root) setupSystemColors() - messageInputFragment = MessageInputFragment() - conversationUser = currentUserProvider.currentUser.blockingGet() - handleIntent(intent) + messageInputFragment = getMessageInputFragment() + chatViewModel = ViewModelProvider(this, viewModelFactory)[ChatViewModel::class.java] messageInputViewModel = ViewModelProvider(this, viewModelFactory)[MessageInputViewModel::class.java] @@ -457,6 +456,15 @@ class ChatActivity : } } + private fun getMessageInputFragment(): MessageInputFragment { + val internalId = conversationUser!!.id.toString() + "@" + roomToken + return MessageInputFragment().apply { + arguments = Bundle().apply { + putString(CONVERSATION_INTERNAL_ID, internalId) + } + } + } + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) val extras: Bundle? = intent.extras @@ -990,7 +998,7 @@ class ChatActivity : } else { supportFragmentManager.commit { setReorderingAllowed(true) - replace(R.id.fragment_container_activity_chat, MessageInputFragment()) + replace(R.id.fragment_container_activity_chat, getMessageInputFragment()) } } } @@ -3784,5 +3792,6 @@ class ChatActivity : private const val RESUME_AUDIO_TAG = "RESUME_AUDIO_TAG" private const val DELAY_TO_SHOW_PROGRESS_BAR = 1000L private const val FIVE_MINUTES_IN_SECONDS: Long = 300 + const val CONVERSATION_INTERNAL_ID = "CONVERSATION_INTERNAL_ID" } } diff --git a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt index 9ddcc6c56..294692788 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt @@ -111,6 +111,7 @@ class MessageInputFragment : Fragment() { lateinit var networkMonitor: NetworkMonitor lateinit var binding: FragmentMessageInputBinding + private lateinit var conversationInternalId: String private var typedWhileTypingTimerIsRunning: Boolean = false private var typingTimer: CountDownTimer? = null private lateinit var chatActivity: ChatActivity @@ -122,6 +123,10 @@ class MessageInputFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) sharedApplication!!.componentApplication.inject(this) + conversationInternalId = arguments?.getString(ChatActivity.CONVERSATION_INTERNAL_ID).orEmpty() + if (conversationInternalId.isEmpty()) { + Log.e(TAG, "internalId for conversation passed to MessageInputFragment is empty") + } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -143,7 +148,7 @@ class MessageInputFragment : Fragment() { override fun onResume() { super.onResume() - chatActivity.messageInputViewModel.restoreMessageQueue(chatActivity.currentConversation!!.internalId) + chatActivity.messageInputViewModel.restoreMessageQueue(conversationInternalId) } override fun onDestroyView() { @@ -728,9 +733,8 @@ class MessageInputFragment : Fragment() { } } - private fun isTypingStatusEnabled(): Boolean { - return !CapabilitiesUtil.isTypingStatusPrivate(chatActivity.conversationUser!!) - } + private fun isTypingStatusEnabled(): Boolean = + !CapabilitiesUtil.isTypingStatusPrivate(chatActivity.conversationUser!!) private fun uploadFile(fileUri: String, isVoiceMessage: Boolean, caption: String = "", token: String = "") { var metaData = ""