Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
898d2e0
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
1d3867a
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
9ba972a
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
73503bd
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
da47af5
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
403e908
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
507f6d7
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
821ad82
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts May 29, 2026
66dda6c
Merge remote-tracking branch 'origin/CCCT-2437-headless-login-engine'…
conroy-ricketts Jun 4, 2026
d165331
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts Jun 4, 2026
94d61c1
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts Jun 4, 2026
3f678f7
Merge branch 'CCCT-2437-headless-login-engine' of github.com:dimagi/c…
conroy-ricketts Jun 8, 2026
d8c695b
CCCT-2437 Headless Login Engine
conroy-ricketts Jun 8, 2026
10285b8
Merge branch 'master' of github.com:dimagi/commcare-android into CCCT…
conroy-ricketts Jun 8, 2026
48e226b
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts Jun 8, 2026
3f67b5a
Merge branch 'master' of github.com:dimagi/commcare-android into CCCT…
conroy-ricketts Jun 10, 2026
6fd3a51
Merge branch 'master' of github.com:dimagi/commcare-android into CCCT…
conroy-ricketts Jun 11, 2026
128a2c9
Merge branch 'master' of github.com:dimagi/commcare-android into CCCT…
conroy-ricketts Jun 11, 2026
d6eed61
CCCT-2438 Login Routing Extraction And Inline App Seating
conroy-ricketts Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 90 additions & 51 deletions app/src/org/commcare/activities/DispatchActivity.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
package org.commcare.activities;

import static org.commcare.activities.LoginActivity.EXTRA_APP_ID;
import static org.commcare.activities.LoginActivity.EXTRA_FORCE_SINGLE_APP_MODE;
import static org.commcare.commcaresupportlibrary.CommCareLauncher.SESSION_ENDPOINT_APP_ID;
import static org.commcare.connect.ConnectAppUtils.IS_LAUNCH_FROM_CONNECT;
import static org.commcare.connect.ConnectConstants.CONNECT_MANAGED_LOGIN;
import static org.commcare.connect.ConnectConstants.NOTIFICATION_ID;
import static org.commcare.connect.ConnectConstants.PERSONALID_MANAGED_LOGIN;
import static org.commcare.utils.FirebaseMessagingUtil.getNotificationActionFromIntent;

import android.content.Intent;
import android.os.Bundle;

import android.util.Log;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import org.commcare.AppUtils;
import org.commcare.CommCareApp;
import org.commcare.CommCareApplication;
import org.commcare.android.database.connect.models.ConnectJobRecord;
import org.commcare.android.database.global.models.ApplicationRecord;
import org.commcare.android.database.user.models.SessionStateDescriptor;
import org.commcare.connect.ConnectJobHelper;
import org.commcare.connect.utils.DeepLinkHelper;
import org.commcare.connect.ConnectNavHelper;
import org.commcare.connect.utils.DeepLinkHelper;
import org.commcare.dalvik.R;
import org.commcare.google.services.analytics.AnalyticsParamValue;
import org.commcare.google.services.analytics.FirebaseAnalyticsUtil;
Expand All @@ -39,10 +31,17 @@

import java.util.ArrayList;

import androidx.appcompat.app.AppCompatActivity;

import javax.annotation.Nullable;

import static org.commcare.activities.LoginActivity.EXTRA_APP_ID;
import static org.commcare.activities.LoginActivity.EXTRA_FORCE_SINGLE_APP_MODE;
import static org.commcare.commcaresupportlibrary.CommCareLauncher.SESSION_ENDPOINT_APP_ID;
import static org.commcare.connect.ConnectAppUtils.IS_LAUNCH_FROM_CONNECT;
import static org.commcare.connect.ConnectConstants.CONNECT_MANAGED_LOGIN;
import static org.commcare.connect.ConnectConstants.NOTIFICATION_ID;
import static org.commcare.connect.ConnectConstants.PERSONALID_MANAGED_LOGIN;
import static org.commcare.utils.FirebaseMessagingUtil.getNotificationActionFromIntent;

/**
* Dispatches install, login, and home screen activities.
*
Expand Down Expand Up @@ -70,7 +69,6 @@ public class DispatchActivity extends AppCompatActivity {
public static final int INIT_APP = 2;
public static final int RECOVERY_MEASURES = 3;


/**
* Request code for automatically validating media.
* Should signal a return from CommCareVerificationActivity.
Expand Down Expand Up @@ -109,14 +107,17 @@ protected void onCreate(Bundle savedInstanceState) {

if (savedInstanceState != null) {
shortcutExtraWasConsumed = savedInstanceState.getBoolean(EXTRA_CONSUMED_KEY);
alreadyCheckedForAppFilesChange = savedInstanceState.getBoolean(KEY_APP_FILES_CHECK_OCCURRED);
waitingForActivityResultFromLogin = savedInstanceState.getBoolean(KEY_WAITING_FOR_ACTIVITY_RESULT);
alreadyCheckedForAppFilesChange = savedInstanceState.getBoolean(
KEY_APP_FILES_CHECK_OCCURRED
);
waitingForActivityResultFromLogin = savedInstanceState.getBoolean(
KEY_WAITING_FOR_ACTIVITY_RESULT
);
}
}


private Intent checkIfAnyPNIntentPresent(){
return FirebaseMessagingUtil.getIntentForPNIfAny(this,getIntent());
private Intent checkIfAnyPNIntentPresent() {
return FirebaseMessagingUtil.getIntentForPNIfAny(this, getIntent());
}

/**
Expand All @@ -130,7 +131,8 @@ private boolean finishIfNotRoot() {
if (!isTaskRoot()) {
Intent intent = getIntent();
String action = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER)
&& action != null && action.equals(Intent.ACTION_MAIN)) {
finish();
return true;
}
Expand Down Expand Up @@ -182,9 +184,9 @@ private void dispatch() {
return;
}

Intent connectOppInviteIntent = DeepLinkHelper.INSTANCE.retrieveConnectOppInviteIntentIfPresent(
this, getIntent());
if(connectOppInviteIntent != null) {
Intent connectOppInviteIntent = DeepLinkHelper.INSTANCE
.retrieveConnectOppInviteIntentIfPresent(this, getIntent());
if (connectOppInviteIntent != null) {
startActivity(connectOppInviteIntent);
return;
}
Expand All @@ -209,7 +211,6 @@ private void dispatch() {
// Result will be stored for later use
RecoveryMeasuresHelper.requestRecoveryMeasures();


// Note that the order in which these conditions are checked matters!!
if (CommCareApplication.instance().isConsumerApp() && !alreadyCheckedForAppFilesChange) {
checkForChangedCCZ();
Expand Down Expand Up @@ -241,11 +242,11 @@ private void dispatch() {
!shortcutExtraWasConsumed) {
// CommCare was launched from a shortcut
handleShortcutLaunch();
} else if(redirectToConnectHome) {
} else if (redirectToConnectHome) {
redirectToConnectHome = false;
CommCareApplication.instance().closeUserSession();
ConnectNavHelper.INSTANCE.goToConnectJobsList(this);
} else if(redirectToConnectOpportunityInfo) {
} else if (redirectToConnectOpportunityInfo) {
redirectToConnectOpportunityInfo = false;
ConnectJobRecord job = ConnectJobHelper.INSTANCE.getJobForSeatedApp(this);
ConnectNavHelper.INSTANCE.goToActiveInfoForJob(this, job, true);
Expand Down Expand Up @@ -278,19 +279,31 @@ private boolean isDbInBadState() {
int dbState = CommCareApplication.instance().getDatabaseState();
if (dbState == CommCareApplication.STATE_LEGACY_DETECTED) {
// Starting from CommCare 2.44, we don't supoort upgrading from Legacy DB
CommCareLifecycleUtils.triggerHandledAppExit(this,
CommCareLifecycleUtils.triggerHandledAppExit(
this,
getString(R.string.legacy_failure),
getString(R.string.legacy_failure_title), false, false);
getString(R.string.legacy_failure_title),
false,
false
);
return true;
} else if (dbState == CommCareApplication.STATE_MIGRATION_FAILED) {
CommCareLifecycleUtils.triggerHandledAppExit(this,
CommCareLifecycleUtils.triggerHandledAppExit(
this,
getString(R.string.migration_definite_failure),
getString(R.string.migration_failure_title), false, false);
getString(R.string.migration_failure_title),
false,
false
);
return true;
} else if (dbState == CommCareApplication.STATE_MIGRATION_QUESTIONABLE) {
CommCareLifecycleUtils.triggerHandledAppExit(this,
CommCareLifecycleUtils.triggerHandledAppExit(
this,
getString(R.string.migration_possible_failure),
getString(R.string.migration_failure_title), false, true);
getString(R.string.migration_failure_title),
false,
true
);
return true;
} else if (dbState == CommCareApplication.STATE_CORRUPTED) {
handleDamagedApp();
Expand Down Expand Up @@ -319,13 +332,16 @@ private void handleDamagedApp() {
private void startRecoveryExecutionActivity() {
startActivityForResult(
new Intent(this, ExecuteRecoveryMeasuresActivity.class),
RECOVERY_MEASURES);
RECOVERY_MEASURES
);
}

private void createNoStorageDialog() {
CommCareLifecycleUtils.triggerHandledAppExit(this,
CommCareLifecycleUtils.triggerHandledAppExit(
this,
Localization.get("app.storage.missing.message"),
Localization.get("app.storage.missing.title"));
Localization.get("app.storage.missing.title")
);
}

private void launchLoginScreen() {
Expand All @@ -336,7 +352,7 @@ private void launchLoginScreen() {
i.putExtra(IS_LAUNCH_FROM_CONNECT, getLaunchedFromConnect());

String sessionEndpointAppID = getSessionEndpointAppId();
if(sessionEndpointAppID == null && redirectToLoginAppId != null) {
if (sessionEndpointAppID == null && redirectToLoginAppId != null) {
sessionEndpointAppID = redirectToLoginAppId;
redirectToLoginAppId = null;
}
Expand All @@ -348,10 +364,12 @@ private void launchLoginScreen() {
startActivityForResult(i, LOGIN_USER);
waitingForActivityResultFromLogin = true;
} else {
Log.w(TAG,
Log.w(
TAG,
"Login redirection bug occurred; DispatchActivity is attempting to launch " +
"a new LoginActivity while it is still waiting for a result from " +
"another one.");
"another one."
);
}
}

Expand All @@ -371,8 +389,10 @@ private void launchHomeScreen() {
if (useRootMenuHomeActivity()) {
i = new Intent(this, RootMenuHomeActivity.class);
// Since we are entering a menu list, the session state will expect this later
HomeScreenBaseActivity.addPendingDataExtra(i,
CommCareApplication.instance().getCurrentSessionWrapper().getSession());
HomeScreenBaseActivity.addPendingDataExtra(
i,
CommCareApplication.instance().getCurrentSessionWrapper().getSession()
);
} else {
i = new Intent(this, StandardHomeActivity.class);
}
Expand Down Expand Up @@ -431,9 +451,11 @@ private void handleUnvalidatedApp() {
} else {
// Means that there are no usable apps, but there are multiple apps who all don't have
// MM verified -- show an error message and shut down
CommCareLifecycleUtils.triggerHandledAppExit(this,
CommCareLifecycleUtils.triggerHandledAppExit(
this,
Localization.get("multiple.apps.unverified.message"),
Localization.get("multiple.apps.unverified.title"));
Localization.get("multiple.apps.unverified.title")
);
}
}

Expand All @@ -445,24 +467,35 @@ private void handleExternalLaunch() {
String sessionRequest = this.getIntent().getStringExtra(SESSION_REQUEST);
SessionStateDescriptor ssd = new SessionStateDescriptor();
ssd.fromBundle(sessionRequest);
CommCareApplication.instance().getCurrentSessionWrapper().loadFromStateDescription(ssd);
CommCareApplication.instance()
.getCurrentSessionWrapper()
.loadFromStateDescription(ssd);
i = new Intent(this, StandardHomeActivity.class);
} else if (getIntent().hasExtra(SESSION_ENDPOINT_ID)) {
String sessionEndpointId = this.getIntent().getStringExtra(SESSION_ENDPOINT_ID);
Bundle args = this.getIntent().getBundleExtra(SESSION_ENDPOINT_ARGUMENTS_BUNDLE);
ArrayList<String> argsList = this.getIntent().getStringArrayListExtra(SESSION_ENDPOINT_ARGUMENTS_LIST);
ArrayList<String> argsList = this.getIntent().getStringArrayListExtra(
SESSION_ENDPOINT_ARGUMENTS_LIST
);
i = new Intent(this, StandardHomeActivity.class);
i.putExtra(SESSION_ENDPOINT_ID, sessionEndpointId);
i.putExtra(SESSION_ENDPOINT_ARGUMENTS_BUNDLE, args);
i.putStringArrayListExtra(SESSION_ENDPOINT_ARGUMENTS_LIST, argsList);
i.putExtra(CC_LAUNCH_REQUIRE_SYNC,
getIntent().getBooleanExtra(CC_LAUNCH_REQUIRE_SYNC, false));
i.putExtra(
CC_LAUNCH_REQUIRE_SYNC,
getIntent().getBooleanExtra(CC_LAUNCH_REQUIRE_SYNC, false)
);
}
clearSessionEndpointIntentExtras();
if (i != null) {
i.putExtra(WAS_EXTERNAL, true);
i.putExtra(EXIT_AFTER_FORM_SUBMISSION,
getIntent().getBooleanExtra(EXIT_AFTER_FORM_SUBMISSION, EXIT_AFTER_FORM_SUBMISSION_DEFAULT));
i.putExtra(
EXIT_AFTER_FORM_SUBMISSION,
getIntent().getBooleanExtra(
EXIT_AFTER_FORM_SUBMISSION,
EXIT_AFTER_FORM_SUBMISSION_DEFAULT
)
);
startActivityForResult(i, HOME_SCREEN);
}
}
Expand Down Expand Up @@ -499,8 +532,14 @@ private boolean triggerLoginIfNeeded() {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (intent != null) {
needToExecuteRecoveryMeasures = intent.getBooleanExtra(EXECUTE_RECOVERY_MEASURES, false);
redirectToConnectOpportunityInfo = intent.getBooleanExtra(REDIRECT_TO_CONNECT_OPPORTUNITY_INFO, false);
needToExecuteRecoveryMeasures = intent.getBooleanExtra(
EXECUTE_RECOVERY_MEASURES,
false
);
redirectToConnectOpportunityInfo = intent.getBooleanExtra(
REDIRECT_TO_CONNECT_OPPORTUNITY_INFO,
false
);
redirectToLoginAppId = intent.getStringExtra(EXTRA_APP_ID);
forceSingleAppMode = intent.getBooleanExtra(EXTRA_FORCE_SINGLE_APP_MODE, true);
}
Expand Down Expand Up @@ -538,7 +577,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent)
case HOME_SCREEN:
if (resultCode == RESULT_CANCELED) {
shouldFinish = !connectManagedLogin;
if(connectManagedLogin) {
if (connectManagedLogin) {
redirectToConnectHome = true;
}
return;
Expand Down
Loading
Loading