Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConnectID Foundation #2847

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
24 changes: 24 additions & 0 deletions app/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,27 @@
<string name="your_comment">Your comment</string>
<string name="support_email_address_default">[email protected]</string>

<string name="ConnectTokenURL">https://connectid.dimagi.com/o/token/</string>
<string name="ConnectHeartbeatURL">https://connectid.dimagi.com/users/heartbeat</string>
<string name="ConnectFetchDbKeyURL">https://connectid.dimagi.com/users/fetch_db_key</string>
<string name="ConnectChangePasswordURL">https://connectid.dimagi.com/users/change_password</string>
<string name="ConnectResetPasswordURL">https://connectid.dimagi.com/users/recover/reset_password</string>
<string name="ConnectConfirmPasswordURL">https://connectid.dimagi.com/users/recover/confirm_password</string>
<string name="ConnectSetPinURL">https://connectid.dimagi.com/users/set_recovery_pin</string>
<string name="ConnectConfirmPinURL">https://connectid.dimagi.com/users/recover/confirm_pin</string>
<string name="ConnectUpdateProfileURL">https://connectid.dimagi.com/users/update_profile</string>
<string name="ConnectChangePhoneURL">https://connectid.dimagi.com/users/change_phone</string>
<string name="ConnectPhoneAvailableURL">https://connectid.dimagi.com/users/phone_available</string>
<string name="ConnectRecoverURL">https://connectid.dimagi.com/users/recover</string>
<string name="ConnectRecoverSecondaryURL">https://connectid.dimagi.com/users/recover/secondary</string>
<string name="ConnectVerifySecondaryURL">https://connectid.dimagi.com/users/validate_secondary_phone</string>
<string name="ConnectValidatePhoneURL">https://connectid.dimagi.com/users/validate_phone</string>
<string name="ConnectRecoverConfirmOTPURL">https://connectid.dimagi.com/users/recover/confirm_otp</string>
<string name="ConnectRecoverConfirmSecondaryOTPURL">https://connectid.dimagi.com/users/recover/confirm_secondary_otp</string>
<string name="ConnectVerifyConfirmSecondaryOTPURL">https://connectid.dimagi.com/users/confirm_secondary_otp</string>
<string name="ConnectConfirmOTPURL">https://connectid.dimagi.com/users/confirm_otp</string>
<string name="ConnectRegisterURL">https://connectid.dimagi.com/users/register</string>

<!-- region: All strings for multiple apps and app-agnostic properties -->

<string name="manager_activity_name">App Manager</string>
Expand Down Expand Up @@ -384,6 +405,7 @@
<string name="recovery_forms_send_error" cc:translatable="true">Error while sending forms</string>
<string name="recovery_forms_state_unavailable" cc:translatable="true">Forms are not available. Make sure your phone storage is available</string>
<string name="recovery_network_unavailable" cc:translatable="true">No network connection. Please check your internet and try again.</string>
<string name="recovery_network_outdated" cc:translatable="true">The app is outdated and can no longer communicate with the server. Please update the app on the Google Play Store.</string>
<string name="recovery_app_manager" cc:translatable="true">Go to App Manager</string>
<string name="recovery_retry" cc:translatable="true">Retry Recovery</string>

Expand Down Expand Up @@ -456,4 +478,6 @@
<string name="fcm_default_notification_channel">notification-channel-push-notifications</string>
<string name="app_with_id_not_found">Required CommCare App is not installed on device</string>
<string name="audio_recording_notification">Audio Recording Notification</string>

<string name="connect_db_corrupt">A problem occurred with the database, please recover your account.</string>
</resources>
63 changes: 37 additions & 26 deletions app/src/org/commcare/CommCareApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,6 @@
import android.text.format.DateUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.multidex.MultiDexApplication;
import androidx.preference.PreferenceManager;
import androidx.work.BackoffPolicy;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;

import com.google.common.collect.Multimap;
import com.google.firebase.analytics.FirebaseAnalytics;

Expand Down Expand Up @@ -105,6 +93,7 @@
import org.commcare.utils.CommCareUtil;
import org.commcare.utils.CrashUtil;
import org.commcare.utils.DeviceIdentifier;
import org.commcare.utils.EncryptionKeyProvider;
import org.commcare.utils.FileUtil;
import org.commcare.utils.FirebaseMessagingUtil;
import org.commcare.utils.GlobalConstants;
Expand Down Expand Up @@ -135,6 +124,17 @@
import javax.annotation.Nullable;
import javax.crypto.SecretKey;

import androidx.annotation.NonNull;
import androidx.multidex.MultiDexApplication;
import androidx.preference.PreferenceManager;
import androidx.work.BackoffPolicy;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import io.noties.markwon.Markwon;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
Expand Down Expand Up @@ -198,6 +198,7 @@ public class CommCareApplication extends MultiDexApplication {

private boolean invalidateCacheOnRestore;
private CommCareNoficationManager noficationManager;
private EncryptionKeyProvider encryptionKeyProvider;

private boolean backgroundSyncSafe;

Expand Down Expand Up @@ -253,6 +254,9 @@ public void onCreate() {

FirebaseMessagingUtil.verifyToken();

//Create standard provider
setEncryptionKeyProvider(new EncryptionKeyProvider());

customiseOkHttp();

setRxJavaGlobalHandler();
Expand All @@ -273,9 +277,8 @@ protected void turnOnStrictMode() {
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
LocalePreferences.saveDeviceLocale(newConfig.locale);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this removed ?

}

private void initNotifications() {
Expand All @@ -294,11 +297,11 @@ private void logFirstCommCareRun() {
}
}

public void setBackgroundSyncSafe(boolean backgroundSyncSafe){
public void setBackgroundSyncSafe(boolean backgroundSyncSafe) {
this.backgroundSyncSafe = backgroundSyncSafe;
}

public boolean isBackgroundSyncSafe(){
public boolean isBackgroundSyncSafe() {
return this.backgroundSyncSafe;
}

Expand Down Expand Up @@ -339,11 +342,11 @@ private void configureCommCareEngineConstantsAndStaticRegistrations() {
// md5 hasher. Major speed improvements.
AndroidClassHasher.registerAndroidClassHashStrategy();

ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();

PerformanceTuningUtil.updateMaxPrefetchCaseBlock(
PerformanceTuningUtil.guessLargestSupportedBulkCaseFetchSizeFromHeap(memoryClass * 1024 * 1024));
PerformanceTuningUtil.guessLargestSupportedBulkCaseFetchSizeFromHeap((long) memoryClass * 1024 * 1024));
}

public void startUserSession(byte[] symmetricKey, UserKeyRecord record, boolean restoreSession) {
Expand Down Expand Up @@ -419,12 +422,13 @@ synchronized public FirebaseAnalytics getAnalyticsInstance() {
analyticsInstance = FirebaseAnalytics.getInstance(this);
}
analyticsInstance.setUserId(getUserIdOrNull());

return analyticsInstance;
}

public int[] getCommCareVersion() {
String[] components = BuildConfig.VERSION_NAME.split("\\.");
int[] versions = new int[] {0, 0, 0};
int[] versions = new int[]{0, 0, 0};
for (int i = 0; i < components.length; i++) {
versions[i] = Integer.parseInt(components[i]);
}
Expand Down Expand Up @@ -469,7 +473,7 @@ public void initializeGlobalResources(CommCareApp app) {

@NonNull
public String getPhoneId() {
/**
/*
* https://source.android.com/devices/tech/config/device-identifiers
* https://issuetracker.google.com/issues/129583175#comment10
* Starting from Android 10, apps cannot access non-resettable device ids unless they have special career permission.
Expand Down Expand Up @@ -513,7 +517,7 @@ private void setRoots() {
private void initializeAnAppOnStartup() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String lastAppId = prefs.getString(LoginActivity.KEY_LAST_APP, "");
if (!"".equals(lastAppId)) {
if (!lastAppId.isEmpty()) {
ApplicationRecord lastApp = MultipleAppsUtil.getAppById(lastAppId);
if (lastApp == null || !lastApp.isUsable()) {
AppUtils.initFirstUsableAppRecord();
Expand Down Expand Up @@ -544,7 +548,7 @@ public void initializeAppResources(CommCareApp app) {
} catch (Exception e) {
Log.i("FAILURE", "Problem with loading");
Log.i("FAILURE", "E: " + e.getMessage());
e.printStackTrace();
// e.printStackTrace();
OrangeAndGreen marked this conversation as resolved.
Show resolved Hide resolved
ForceCloseLogger.reportExceptionInBg(e);
CrashUtil.reportException(e);
resourceState = STATE_CORRUPTED;
Expand Down Expand Up @@ -730,7 +734,7 @@ public void onServiceConnected(ComponentName className, IBinder service) {
synchronized (serviceLock) {
mCurrentServiceBindTimeout = MAX_BIND_TIMEOUT;

mBoundService = ((CommCareSessionService.LocalBinder)service).getService();
mBoundService = ((CommCareSessionService.LocalBinder) service).getService();
mBoundService.showLoggedInNotification(null);

// Don't let anyone touch this until it's logged in
Expand Down Expand Up @@ -916,7 +920,7 @@ public static boolean areAutomatedActionsInvalid() {

/**
* Whether the current login is a "demo" mode login.
*
* <p>
OrangeAndGreen marked this conversation as resolved.
Show resolved Hide resolved
* Returns a provided default value if there is no active user login
*/
public static boolean isInDemoMode(boolean defaultValue) {
Expand Down Expand Up @@ -971,8 +975,7 @@ public CommCareSessionService getSession() {
public static boolean isSessionActive() {
try {
return CommCareApplication.instance().getSession() != null;
}
catch (SessionUnavailableException e){
} catch (SessionUnavailableException e) {
return false;
}
}
Expand Down Expand Up @@ -1152,6 +1155,14 @@ public void setInvalidateCacheFlag(boolean b) {
invalidateCacheOnRestore = b;
}

public void setEncryptionKeyProvider(EncryptionKeyProvider provider) {
encryptionKeyProvider = provider;
}

public EncryptionKeyProvider getEncryptionKeyProvider() {
return encryptionKeyProvider;
}

public PrototypeFactory getPrototypeFactory(Context c) {
return AndroidPrototypeFactorySetup.getPrototypeFactory(c);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.commcare.android.database.connect.models;

import org.commcare.android.storage.framework.Persisted;
import org.commcare.models.framework.Persisting;
import org.commcare.modern.database.Table;
import org.commcare.modern.models.MetaField;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Table(ConnectAppRecord.STORAGE_KEY)
public class ConnectAppRecord extends Persisted implements Serializable {
/**
* Name of database that stores app info for Connect jobs
OrangeAndGreen marked this conversation as resolved.
Show resolved Hide resolved
*/
public static final String STORAGE_KEY = "connect_apps";

public static final String META_JOB_ID = "job_id";
public static final String META_DOMAIN = "cc_domain";
public static final String META_APP_ID = "cc_app_id";
public static final String META_NAME = "name";
public static final String META_DESCRIPTION = "description";
public static final String META_ORGANIZATION = "organization";
public static final String META_PASSING_SCORE = "passing_score";
public static final String META_INSTALL_URL = "install_url";
public static final String META_MODULES = "learn_modules";

@Persisting(1)
@MetaField(META_JOB_ID)
private int jobId;
@Persisting(2)
private boolean isLearning;
@Persisting(3)
@MetaField(META_DOMAIN)
private String domain;
@Persisting(4)
@MetaField(META_APP_ID)
private String appId;
@Persisting(5)
@MetaField(META_NAME)
private String name;
@Persisting(6)
@MetaField(META_DESCRIPTION)
private String description;
@Persisting(7)
@MetaField(META_ORGANIZATION)
private String organization;

@Persisting(8)
@MetaField(META_PASSING_SCORE)
private int passingScore;
@Persisting(9)
@MetaField(META_INSTALL_URL)
private String installUrl;
@Persisting(10)
private Date lastUpdate;

private List<ConnectLearnModuleSummaryRecord> learnModules;

public ConnectAppRecord() {

}

public static ConnectAppRecord fromJson(JSONObject json, int jobId, boolean isLearning) throws JSONException {
ConnectAppRecord app = new ConnectAppRecord();

app.jobId = jobId;
app.isLearning = isLearning;

app.domain = json.has(META_DOMAIN) ? json.getString(META_DOMAIN) : "";
app.appId = json.has(META_APP_ID) ? json.getString(META_APP_ID) : "";
app.name = json.has(META_NAME) ? json.getString(META_NAME) : "";
app.description = json.has(META_DESCRIPTION) ? json.getString(META_DESCRIPTION) : "";
app.organization = json.has(META_ORGANIZATION) ? json.getString(META_ORGANIZATION) : "";
app.passingScore = json.has(META_PASSING_SCORE) && !json.isNull(META_PASSING_SCORE) ? json.getInt(META_PASSING_SCORE) : -1;
app.installUrl = json.has(META_INSTALL_URL) ? json.getString(META_INSTALL_URL) : "";

JSONArray array = json.getJSONArray(META_MODULES);
app.learnModules = new ArrayList<>();
for(int i=0; i<array.length(); i++) {
JSONObject obj = (JSONObject)array.get(i);
app.learnModules.add(ConnectLearnModuleSummaryRecord.fromJson(obj, i));
}

return app;
}

public boolean getIsLearning() { return isLearning; }
public int getJobId() { return jobId; }
public void setJobId(int jobId) { this.jobId = jobId; }

public String getAppId() { return appId; }
public String getDomain() { return domain; }
public int getPassingScore() { return passingScore; }

public List<ConnectLearnModuleSummaryRecord> getLearnModules() { return learnModules; }
public String getInstallUrl() { return installUrl; }
public void setLearnModules(List<ConnectLearnModuleSummaryRecord> modules) { learnModules = modules; }
public void setLastUpdate(Date lastUpdate) { this.lastUpdate = lastUpdate; }
}
Loading
Loading