From 22dee14cb3f1a9750c54c2b479745b15221299f3 Mon Sep 17 00:00:00 2001 From: ibrahim-iqbal Date: Mon, 12 Oct 2026 10:57:59 +0530 Subject: [PATCH 1/4] fix: guard bottom-nav against NPE when no account is set (#4998) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the last account is removed (or no account exists yet), BaseActivity.swapToDefaultAccount() launches the account-setup flow but leaves the account null for the rest of the activity's lifecycle. A bottom-nav click in that window still called navigateToOption(), which eventually constructs FileDataStorageManager(account) and NPEs on the null account. Guard the three navigateToOption() call sites in DrawerActivity.bottomBarNavigationTo with a null-account check — the setup screen is already launching, so there's nothing to navigate to. The Uploads nav item is untouched since it never touches the storage manager. Signed-off-by: ibrahim-iqbal --- .../android/ui/activity/DrawerActivity.kt | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt index fa1dd9807eb..f39b6232d82 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt @@ -243,19 +243,36 @@ abstract class DrawerActivity : ToolbarActivity() { private fun bottomBarNavigationTo(menuItemId: Int, isCurrentOptionActive: Boolean) { when (menuItemId) { - R.id.nav_all_files -> navigateToOption(FileListOption.ALL_FILES) - R.id.nav_spaces -> navigateToOption(FileListOption.SPACES_LIST) + R.id.nav_all_files -> navigateToOptionIfAccountReady(FileListOption.ALL_FILES) + R.id.nav_spaces -> navigateToOptionIfAccountReady(FileListOption.SPACES_LIST) R.id.nav_uploads -> if (!isCurrentOptionActive) { val uploadListIntent = Intent(applicationContext, UploadListActivity::class.java) uploadListIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) startActivity(uploadListIntent) } - R.id.nav_available_offline_files -> navigateToOption(FileListOption.AV_OFFLINE) - R.id.nav_shared_by_link_files -> navigateToOption(FileListOption.SHARED_BY_LINK) + R.id.nav_available_offline_files -> navigateToOptionIfAccountReady(FileListOption.AV_OFFLINE) + R.id.nav_shared_by_link_files -> navigateToOptionIfAccountReady(FileListOption.SHARED_BY_LINK) } } + /** + * #4998: when there's no valid account (e.g. the last account was just + * removed), [BaseActivity.swapToDefaultAccount] kicks off the + * account-setup flow but leaves the account null for the rest of this + * activity's lifecycle. [navigateToOption] eventually calls + * `getStorageManager()`, which constructs a `FileDataStorageManager(account)` + * and NPEs on that null account. The setup screen is already launching, + * so there's nothing useful to navigate to here — no-op instead of + * crashing. + */ + private fun navigateToOptionIfAccountReady(fileListOption: FileListOption) { + if (account == null) { + return + } + navigateToOption(fileListOption) + } + private fun openHelp() { goToUrl(url = getString(R.string.url_help)) } From 0bbd3bf9e8002930773a08d91d13592ee5586df9 Mon Sep 17 00:00:00 2001 From: ibrahim-iqbal Date: Wed, 14 Oct 2026 17:49:07 +0530 Subject: [PATCH 2/4] chore: add calens file Signed-off-by: ibrahim-iqbal --- changelog/unreleased/5012 | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changelog/unreleased/5012 diff --git a/changelog/unreleased/5012 b/changelog/unreleased/5012 new file mode 100644 index 00000000000..f29c8b2125e --- /dev/null +++ b/changelog/unreleased/5012 @@ -0,0 +1,6 @@ +Bugfix: Guard bottom navigation against crash when no account is set + +A null-account check has been added to the bottom navigation so it skips navigation instead of crashing. + +https://github.com/owncloud/android/issues/4998 +https://github.com/owncloud/android/pull/5012 From f05c70d478babc6c1b8ca67811fa1511f085446e Mon Sep 17 00:00:00 2001 From: ibrahim-iqbal Date: Wed, 14 Oct 2026 17:49:07 +0530 Subject: [PATCH 3/4] refactor: inline the null-account guard, drop the AI-flavored comment Per review: moved the account==null check to the top of bottomBarNavigationTo itself instead of a separate navigateToOptionIfAccountReady wrapper, and replaced the long AI-generated doc comment with a one-line note matching the file's existing comment style. Signed-off-by: ibrahim-iqbal --- .../android/ui/activity/DrawerActivity.kt | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt index f39b6232d82..2be3426ef30 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt @@ -242,35 +242,24 @@ abstract class DrawerActivity : ToolbarActivity() { } private fun bottomBarNavigationTo(menuItemId: Int, isCurrentOptionActive: Boolean) { + // #4998: account can be null here if the last account was just removed and + // BaseActivity.swapToDefaultAccount() is already launching account setup; + // navigateToOption() would NPE on getStorageManager() in that case. + if (account == null) { + return + } when (menuItemId) { - R.id.nav_all_files -> navigateToOptionIfAccountReady(FileListOption.ALL_FILES) - R.id.nav_spaces -> navigateToOptionIfAccountReady(FileListOption.SPACES_LIST) + R.id.nav_all_files -> navigateToOption(FileListOption.ALL_FILES) + R.id.nav_spaces -> navigateToOption(FileListOption.SPACES_LIST) R.id.nav_uploads -> if (!isCurrentOptionActive) { val uploadListIntent = Intent(applicationContext, UploadListActivity::class.java) uploadListIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) startActivity(uploadListIntent) } - R.id.nav_available_offline_files -> navigateToOptionIfAccountReady(FileListOption.AV_OFFLINE) - R.id.nav_shared_by_link_files -> navigateToOptionIfAccountReady(FileListOption.SHARED_BY_LINK) - } - } - - /** - * #4998: when there's no valid account (e.g. the last account was just - * removed), [BaseActivity.swapToDefaultAccount] kicks off the - * account-setup flow but leaves the account null for the rest of this - * activity's lifecycle. [navigateToOption] eventually calls - * `getStorageManager()`, which constructs a `FileDataStorageManager(account)` - * and NPEs on that null account. The setup screen is already launching, - * so there's nothing useful to navigate to here — no-op instead of - * crashing. - */ - private fun navigateToOptionIfAccountReady(fileListOption: FileListOption) { - if (account == null) { - return + R.id.nav_available_offline_files -> navigateToOption(FileListOption.AV_OFFLINE) + R.id.nav_shared_by_link_files -> navigateToOption(FileListOption.SHARED_BY_LINK) } - navigateToOption(fileListOption) } private fun openHelp() { From 8f500b1828bb27d8ae7401eaceb5d5e5f0856e01 Mon Sep 17 00:00:00 2001 From: ibrahim-iqbal Date: Fri, 16 Oct 2026 10:49:27 +0530 Subject: [PATCH 4/4] refactor: drop remaining AI-flavored doc comment on bottomBarNavigationTo Same category as the earlier removed comment on navigateToOptionIfAccountReady - the guard clause is self-explanatory, the comment restated it. Signed-off-by: ibrahim-iqbal --- .../java/com/owncloud/android/ui/activity/DrawerActivity.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt index 2be3426ef30..153def4368f 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt @@ -242,9 +242,6 @@ abstract class DrawerActivity : ToolbarActivity() { } private fun bottomBarNavigationTo(menuItemId: Int, isCurrentOptionActive: Boolean) { - // #4998: account can be null here if the last account was just removed and - // BaseActivity.swapToDefaultAccount() is already launching account setup; - // navigateToOption() would NPE on getStorageManager() in that case. if (account == null) { return }