package org.commcare; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import org.commcare.android.database.app.models.UserKeyRecord; import org.commcare.android.database.global.models.ApplicationRecord; import org.commcare.dalvik.BuildConfig; import org.commcare.dalvik.R; import org.commcare.logging.AndroidLogger; import org.commcare.models.database.user.DatabaseUserOpenHelper; import org.commcare.preferences.CommCarePreferences; import org.commcare.suite.model.Profile; import org.commcare.utils.MultipleAppsUtil; import org.javarosa.core.model.instance.FormInstance; import org.javarosa.core.services.Logger; import org.javarosa.core.services.locale.Localization; import org.javarosa.core.services.storage.EntityFilter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Set; /** * Utils for getting info about installed apps, initializing them, and uninstalling them. */ public class AppUtils { /** * @return all ApplicationRecords in storage, regardless of their status, in alphabetical order */ public static ArrayList<ApplicationRecord> getInstalledAppRecords() { ArrayList<ApplicationRecord> records = new ArrayList<>(); for (ApplicationRecord r : CommCareApplication.instance().getGlobalStorage(ApplicationRecord.class)) { records.add(r); } Collections.sort(records, new Comparator<ApplicationRecord>() { @Override public int compare(ApplicationRecord lhs, ApplicationRecord rhs) { return lhs.getDisplayName().compareTo(rhs.getDisplayName()); } }); return records; } /** * @param uniqueId - the uniqueId of the ApplicationRecord being sought * @return the ApplicationRecord corresponding to the given id, if it exists. Otherwise, * return null */ public static ApplicationRecord getAppById(String uniqueId) { for (ApplicationRecord r : getInstalledAppRecords()) { if (r.getUniqueId().equals(uniqueId)) { return r; } } return null; } /** * Initializes the first "usable" application from the list of globally installed app records, * if there is one */ public static void initFirstUsableAppRecord() { for (ApplicationRecord record : MultipleAppsUtil.getUsableAppRecords()) { CommCareApplication.instance().initializeAppResources(new CommCareApp(record)); break; } } /** * Check if any existing apps were left in a partially deleted state, and finish * uninstalling them if so. */ static void checkForIncompletelyUninstalledApps() { for (ApplicationRecord record : CommCareApplication.instance().getGlobalStorage(ApplicationRecord.class)) { if (record.getStatus() == ApplicationRecord.STATUS_DELETE_REQUESTED) { try { CommCareApplication.instance().uninstall(record); } catch (RuntimeException e) { Logger.log(AndroidLogger.TYPE_ERROR_STORAGE, "Unable to uninstall an app " + "during startup that was previously left partially-deleted"); } } } } /** * Assumes that there is an active session when it is called, and wipes out all local user * data (users, referrals, etc) for the user with an active session, but leaves application * resources in place. * * It makes no attempt to make sure this is a safe operation when called, so * it shouldn't be used lightly. */ public static void clearUserData() { wipeSandboxForUser(CommCareApplication.instance().getSession().getLoggedInUser().getUsername()); CommCareApplication.instance().getCurrentApp().getAppPreferences().edit() .putString(CommCarePreferences.LAST_LOGGED_IN_USER, null).commit(); CommCareApplication.instance().closeUserSession(); } public static void wipeSandboxForUser(final String username) { // manually clear file-backed fixture storage to ensure files are removed CommCareApplication.instance().getFileBackedUserStorage("fixture", FormInstance.class).removeAll(); // wipe the user's db final Set<String> dbIdsToRemove = new HashSet<>(); CommCareApplication.instance().getAppStorage(UserKeyRecord.class).removeAll(new EntityFilter<UserKeyRecord>() { @Override public boolean matches(UserKeyRecord ukr) { if (ukr.getUsername().equalsIgnoreCase(username.toLowerCase())) { dbIdsToRemove.add(ukr.getUuid()); return true; } return false; } }); for (String id : dbIdsToRemove) { CommCareApplication.instance().getDatabasePath(DatabaseUserOpenHelper.getDbName(id)).delete(); } } public static String getCurrentVersionString() { CommCareApplication application = CommCareApplication.instance(); PackageManager pm = application.getPackageManager(); PackageInfo pi; try { pi = pm.getPackageInfo(application.getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return "ERROR! Incorrect package version requested"; } int[] versions = application.getCommCareVersion(); String ccv = ""; for (int vn : versions) { if (!"".equals(ccv)) { ccv += "."; } ccv += vn; } Profile p = CommCareApplication.instance().getCurrentApp() == null ? null : CommCareApplication.instance().getCommCarePlatform().getCurrentProfile(); String profileVersion = ""; if (p != null) { profileVersion = String.valueOf(p.getVersion()); } String buildDate = BuildConfig.BUILD_DATE; String buildNumber = BuildConfig.BUILD_NUMBER; return Localization.get(application.getString(R.string.app_version_string), new String[]{pi.versionName, String.valueOf(pi.versionCode), ccv, buildNumber, buildDate, profileVersion}); } }