package org.commcare.dalvik.activities;
import org.commcare.android.database.global.models.ApplicationRecord;
import org.commcare.android.framework.CommCareActivity;
import org.commcare.android.framework.ManagedUi;
import org.commcare.android.framework.UiElement;
import org.commcare.android.framework.WrappingSpinnerAdapter;
import org.commcare.android.javarosa.AndroidLogger;
import org.commcare.android.models.notifications.NotificationMessage;
import org.commcare.android.models.notifications.NotificationMessageFactory;
import org.commcare.android.tasks.ResourceEngineListener;
import org.commcare.android.tasks.ResourceEngineTask;
import org.commcare.android.tasks.ResourceEngineTask.ResourceEngineOutcomes;
import org.commcare.dalvik.R;
import org.commcare.dalvik.application.CommCareApp;
import org.commcare.dalvik.application.CommCareApplication;
import org.commcare.dalvik.dialogs.CustomProgressDialog;
import org.commcare.resources.model.ResourceTable;
import org.commcare.resources.model.UnresolvedResourceException;
import org.javarosa.core.reference.InvalidReferenceException;
import org.javarosa.core.reference.ReferenceManager;
import org.javarosa.core.services.Logger;
import org.javarosa.core.services.locale.Localization;
import org.javarosa.core.util.PropertyUtils;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.PowerManager;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
/**
* The CommCareStartupActivity is purely responsible for identifying
* the state of the application (uninstalled, installed) and performing
* any necessary setup to get to a place where CommCare can load normally.
*
* If the startup activity identifies that the app is installed properly
* it should not ever require interaction or be visible to the user.
*
* @author ctsims
*
*/
@ManagedUi(R.layout.first_start_screen)
public class CommCareSetupActivity extends CommCareActivity<CommCareSetupActivity> implements ResourceEngineListener{
// public static final String DATABASE_STATE = "database_state";
public static final String RESOURCE_STATE = "resource_state";
public static final String KEY_PROFILE_REF = "app_profile_ref";
public static final String KEY_UPGRADE_MODE = "app_upgrade_mode";
public static final String KEY_ERROR_MODE = "app_error_mode";
public static final String KEY_REQUIRE_REFRESH = "require_referesh";
public static final String KEY_AUTO = "is_auto_update";
public static final String KEY_START_OVER = "start_over_uprgrade";
public static final String KEY_LAST_INSTALL = "last_install_time";
/*
* enum indicating which UI mconfiguration should be shown.
* basic: First install, user can scan barcode and move to ready mode or select advanced mode
* advanced: First install, user can enter bit.ly or URL directly, or return to basic mode
* ready: First install, barcode has been scanned. Can move to advanced mode to inspect URL, or proceed to install
* upgrade: App installed already. Buttons aren't shown, trying to update app with no user input
* error: Installation or Upgrade has failed, offer to retry or restart. upgrade/install differentiated with inUpgradeMode boolean
*/
public enum UiState { advanced, basic, ready, error, upgrade};
public UiState uiState = UiState.basic;
public static final int MODE_BASIC = Menu.FIRST;
public static final int MODE_ADVANCED = Menu.FIRST + 1;
public static final int MODE_ARCHIVE = Menu.FIRST + 2;
public static final int BARCODE_CAPTURE = 1;
public static final int MISSING_MEDIA_ACTIVITY=2;
public static final int ARCHIVE_INSTALL = 3;
public static final int DIALOG_INSTALL_PROGRESS = 4;
public static final int RETRY_LIMIT = 20;
boolean startAllowed = true;
boolean inUpgradeMode = false;
int dbState;
int resourceState;
int retryCount=0;
public String incomingRef;
public boolean canRetry;
public String displayMessage;
@UiElement(R.id.advanced_panel)
View advancedView;
@UiElement(R.id.screen_first_start_bottom)
View buttonView;
@UiElement(R.id.edit_profile_location)
EditText editProfileRef;
@UiElement(R.id.str_setup_message)
TextView mainMessage;
@UiElement(R.id.url_spinner)
Spinner urlSpinner;
@UiElement(R.id.start_install)
Button installButton;
@UiElement(R.id.btn_fetch_uri)
Button mScanBarcodeButton;
@UiElement(R.id.enter_app_location)
Button addressEntryButton;
@UiElement(R.id.start_over)
Button startOverButton;
@UiElement(R.id.view_notification)
Button viewNotificationButton;
@UiElement(R.id.retry_install)
Button retryButton;
@UiElement(R.id.screen_first_start_banner)
View banner;
String [] urlVals;
int previousUrlPosition=0;
boolean partialMode = false;
CommCareApp ccApp;
//Whether this needs to be interactive (if it's automatic, we want to skip a lot of the UI stuff
boolean isAuto = false;
/* used to keep track of whether or not the previous resource table was in a
* 'fresh' (empty or installed) state before the last install ran
*/
boolean resourceTableWasFresh;
static final long START_OVER_THRESHOLD = 604800000; //1 week in milliseconds
private BroadcastReceiver purgeNotificationReceiver = null;
/*
* (non-Javadoc)
* @see org.commcare.android.framework.CommCareActivity#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CommCareSetupActivity oldActivity = (CommCareSetupActivity)this.getDestroyedActivityState();
//Retrieve instance state
if(savedInstanceState == null) {
if(Intent.ACTION_VIEW.equals(this.getIntent().getAction())) {
//We got called from an outside application, it's gonna be a wild ride!
incomingRef = this.getIntent().getData().toString();
if(incomingRef.contains(".ccz")){
// make sure this is in the file system
boolean isFile = incomingRef.contains("file://");
if(isFile){
// remove file:// prepend
incomingRef = incomingRef.substring(incomingRef.indexOf("//")+2);
Intent i = new Intent(this, InstallArchiveActivity.class);
i.putExtra(InstallArchiveActivity.ARCHIVE_REFERENCE, incomingRef);
startActivityForResult(i, ARCHIVE_INSTALL);
}
else{
// currently down allow other locations like http://
fail(NotificationMessageFactory.message(NotificationMessageFactory.StockMessages.Bad_Archive_File), true, false);
}
}
else{
this.uiState=uiState.ready;
//Now just start up normally.
}
} else{
incomingRef = this.getIntent().getStringExtra(KEY_PROFILE_REF);
}
inUpgradeMode = this.getIntent().getBooleanExtra(KEY_UPGRADE_MODE, false);
isAuto = this.getIntent().getBooleanExtra(KEY_AUTO, false);
} else {
String uiStateEncoded = savedInstanceState.getString("advanced");
this.uiState = uiStateEncoded == null ? UiState.basic : UiState.valueOf(UiState.class, uiStateEncoded);
incomingRef = savedInstanceState.getString("profileref");
inUpgradeMode = savedInstanceState.getBoolean(KEY_UPGRADE_MODE);
isAuto = savedInstanceState.getBoolean(KEY_AUTO);
//Uggggh, this might not be 100% legit depending on timing, what if we've already reconnected and shut down the dialog?
startAllowed = savedInstanceState.getBoolean("startAllowed");
}
// if we are in upgrade mode we want the UiState to reflect that, unless we are showing an error
if(inUpgradeMode && this.uiState != UiState.error){
this.uiState = UiState.upgrade;
}
editProfileRef.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
urlSpinner.setAdapter(new WrappingSpinnerAdapter(urlSpinner.getAdapter(), getResources().getStringArray(R.array.url_list_selected_display)));
urlVals = getResources().getStringArray(R.array.url_vals);
urlSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){
/*
* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long)
*/
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
if((previousUrlPosition == 0 || previousUrlPosition == 1) && arg2 == 2){
editProfileRef.setText(R.string.default_app_server);
}
else if(previousUrlPosition == 2 && (arg2 == 0 || arg2 == 1)){
editProfileRef.setText("");
}
previousUrlPosition = arg2;
}
/*
* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView)
*/
@Override
public void onNothingSelected(AdapterView<?> arg0) {}
});
//First, identify the binary state
dbState = CommCareApplication._().getDatabaseState();
resourceState = CommCareApplication._().getAppResourceState();
if(!Intent.ACTION_VIEW.equals(this.getIntent().getAction())) {
//Otherwise we're starting up being called from inside the app. Check to see if everything is set
//and we can just skip this unless it's upgradeMode
if(dbState == CommCareApplication.STATE_READY && resourceState == CommCareApplication.STATE_READY && !inUpgradeMode) {
Intent i = new Intent(getIntent());
setResult(RESULT_OK, i);
finish();
return;
}
}
mScanBarcodeButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
Intent i = new Intent("com.google.zxing.client.android.SCAN");
//Barcode only
i.putExtra("SCAN_FORMATS","QR_CODE");
CommCareSetupActivity.this.startActivityForResult(i, BARCODE_CAPTURE);
} catch (ActivityNotFoundException e) {
Toast.makeText(CommCareSetupActivity.this,"No barcode scanner installed on phone!", Toast.LENGTH_SHORT).show();
mScanBarcodeButton.setVisibility(View.GONE);
}
}
});
addressEntryButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
setUiState(UiState.advanced);
refreshView();
}
});
addressEntryButton.setText(Localization.get("install.button.enter"));
startOverButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(inUpgradeMode) {
startResourceInstall(true);
} else {
retryCount = 0;
partialMode = false;
setUiState(UiState.basic);
refreshView();
}
}
});
// Hide "See More" button when notification is cleared
// (by any method: button press, viewing from drawer, or clearing from drawer)
purgeNotificationReceiver = new BroadcastReceiver() {
/*
* (non-Javadoc)
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
@Override
public void onReceive(Context context, Intent intent) {
viewNotificationButton.setVisibility(View.GONE);
}
};
registerReceiver(purgeNotificationReceiver, new IntentFilter(CommCareApplication.ACTION_PURGE_NOTIFICATIONS));
// "See More" launches standard notification-viewing activity
viewNotificationButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent i = new Intent(CommCareSetupActivity.this, MessageActivity.class);
CommCareSetupActivity.this.startActivity(i);
}
});
retryButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
viewNotificationButton.setVisibility(View.GONE);
partialMode = true;
startResourceInstall(false);
}
});
installButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//Now check on the resources
if(resourceState == CommCareApplication.STATE_READY) {
if(!inUpgradeMode || uiState != UiState.error) {
fail(NotificationMessageFactory.message(ResourceEngineOutcomes.StatusFailState), true);
}
} else if(resourceState == CommCareApplication.STATE_UNINSTALLED ||
(resourceState == CommCareApplication.STATE_UPGRADE && inUpgradeMode)) {
startResourceInstall();
}
}
});
final View activityRootView = findViewById(R.id.screen_first_start_main);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
/*
* (non-Javadoc)
* @see android.view.ViewTreeObserver.OnGlobalLayoutListener#onGlobalLayout()
*/
@Override
public void onGlobalLayout() {
int hideAll = CommCareSetupActivity.this.getResources().getInteger(R.integer.login_screen_hide_all_cuttoff);
int hideBanner = CommCareSetupActivity.this.getResources().getInteger(R.integer.login_screen_hide_banner_cuttoff);
int height = activityRootView.getHeight();
if(height < hideAll) {
banner.setVisibility(View.GONE);
} else if(height < hideBanner) {
banner.setVisibility(View.GONE);
} else {
banner.setVisibility(View.VISIBLE);
}
}
});
// reclaim ccApp for resuming installation
if(oldActivity != null) {
this.ccApp = oldActivity.ccApp;
}
refreshView();
//prevent the keyboard from popping up on entry by refocusing on the main layout
findViewById(R.id.mainLayout).requestFocus();
}
/*
* (non-Javadoc)
* @see org.commcare.android.framework.CommCareActivity#onDestroy()
*/
@Override
public void onDestroy() {
super.onDestroy();
if (purgeNotificationReceiver != null) {
unregisterReceiver(purgeNotificationReceiver);
}
}
public void refreshView(){
switch(uiState){
case basic:
this.setModeToBasic();
break;
case advanced:
this.setModeToAdvanced();
break;
case error:
this.setModeToError(true);
break;
case upgrade:
this.setModeToAutoUpgrade();
break;
case ready:
this.setModeToReady(incomingRef);
break;
}
}
/*
* (non-Javadoc)
* @see android.support.v4.app.FragmentActivity#onStart()
*/
@Override
protected void onStart() {
super.onStart();
//Moved here to properly attach fragments and such.
//NOTE: May need to do so elsewhere as well
if(uiState == UiState.upgrade) {
refreshView();
mainMessage.setText(Localization.get("updates.check"));
startResourceInstall();
}
}
/* (non-Javadoc)
* @see org.commcare.android.framework.CommCareActivity#getWakeLockingLevel()
*/
@Override
protected int getWakeLockingLevel() {
return PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE;
}
/*
* (non-Javadoc)
* @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("advanced", uiState.toString());
outState.putString("profileref", incomingRef);
outState.putBoolean(KEY_AUTO, isAuto);
outState.putBoolean("startAllowed", startAllowed);
outState.putBoolean(KEY_UPGRADE_MODE, inUpgradeMode);
}
/* (non-Javadoc)
* @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == BARCODE_CAPTURE) {
if(resultCode == Activity.RESULT_CANCELED) {
//Basically nothing
} else if(resultCode == Activity.RESULT_OK) {
String result = data.getStringExtra("SCAN_RESULT");
incomingRef = result;
//Definitely have a URI now.
try{
ReferenceManager._().DeriveReference(incomingRef);
}
catch(InvalidReferenceException ire){
this.setModeToBasic(Localization.get("install.bad.ref"));
return;
}
setUiState(UiState.ready);
this.refreshView();
}
}
if(requestCode == ARCHIVE_INSTALL){
if(resultCode == Activity.RESULT_CANCELED) {
//Basically nothing
} else if(resultCode == Activity.RESULT_OK) {
String result = data.getStringExtra(InstallArchiveActivity.ARCHIVE_REFERENCE);
incomingRef = result;
//Definitely have a URI now.
try{
ReferenceManager._().DeriveReference(incomingRef);
}
catch(InvalidReferenceException ire){
this.setModeToBasic(Localization.get("install.bad.ref"));
return;
}
setUiState(UiState.ready);
this.refreshView();
}
}
}
private String getRef(){
String ref;
if(this.uiState == UiState.advanced) {
int selectedIndex = urlSpinner.getSelectedItemPosition();
String selectedString = urlVals[selectedIndex];
if(previousUrlPosition != 2){
ref = selectedString + editProfileRef.getText().toString();
}
else{
ref = editProfileRef.getText().toString();
}
}
else{
ref = incomingRef;
}
return ref;
}
private CommCareApp getCommCareApp(){
CommCareApp app = null;
// we are in upgrade mode, just send back current app
if(inUpgradeMode){
app = CommCareApplication._().getCurrentApp();
return app;
}
//we have a clean slate, create a new app
if(partialMode){
return ccApp;
}
else{
ApplicationRecord newRecord = new ApplicationRecord(PropertyUtils.genUUID().replace("-",""), ApplicationRecord.STATUS_UNINITIALIZED);
app = new CommCareApp(newRecord);
return app;
}
}
private void startResourceInstall() {
CommCareApp ccApp = getCommCareApp();
long lastInstallTime = ccApp.getAppPreferences().getLong(KEY_LAST_INSTALL, -1);
if (System.currentTimeMillis() - lastInstallTime > START_OVER_THRESHOLD) {
/*If we are triggering a start over install due to the time threshold
* when there is a partial resource table that we could be using, send
* a message to log this.
*/
ResourceTable temporary = ccApp.getCommCarePlatform().getUpgradeResourceTable();
if (temporary.getTableReadiness() == ResourceTable.RESOURCE_TABLE_PARTIAL) {
Logger.log(AndroidLogger.TYPE_RESOURCES, "A start-over on installation has been "
+ "triggered by the time threshold when there is an existing partial "
+ "resource table that could be used.");
}
startResourceInstall(true);
}
else {
startResourceInstall(ccApp.getAppPreferences().getBoolean(KEY_START_OVER, true));
}
}
/* (non-Javadoc)
* @see org.commcare.android.tasks.templates.CommCareTaskConnector#startBlockingForTask()
*/
@Override
public void startBlockingForTask(int id) {
super.startBlockingForTask(id);
this.startAllowed = false;
}
/* (non-Javadoc)
* @see org.commcare.android.tasks.templates.CommCareTaskConnector#stopBlockingForTask()
*/
@Override
public void stopBlockingForTask(int id) {
super.stopBlockingForTask(id);
this.startAllowed = true;
}
/**
* @param startOverUpgrade - what determines whether CommCarePlatform.stageUpgradeTable()
* reuses the last version of the upgrade table, or starts over
*/
private void startResourceInstall(boolean startOverUpgrade) {
if(startAllowed) {
String ref = getRef();
CommCareApp app = getCommCareApp();
ccApp = app;
/* store what the state of the resource table was before this install,
* so we can compare it to the state after and decide if this should
* count as a 'last install time'
*/
int tableStateBeforeInstall = ccApp.getCommCarePlatform().getUpgradeResourceTable().
getTableReadiness();
this.resourceTableWasFresh = tableStateBeforeInstall == ResourceTable.RESOURCE_TABLE_EMPTY ||
tableStateBeforeInstall == ResourceTable.RESOURCE_TABLE_INSTALLED;
CustomProgressDialog lastDialog = getCurrentDialog();
/* used to tell the ResourceEngineTask whether or not it should sleep before
* it starts, set based on whether we are currently in keep trying mode */
boolean shouldSleep = (lastDialog == null) ? false : lastDialog.isChecked();
ResourceEngineTask<CommCareSetupActivity> task = new ResourceEngineTask<CommCareSetupActivity>(this,
inUpgradeMode, partialMode, app, startOverUpgrade, DIALOG_INSTALL_PROGRESS, shouldSleep) {
/*
* (non-Javadoc)
* @see org.commcare.android.tasks.templates.CommCareTask#deliverResult(java.lang.Object, java.lang.Object)
*/
@Override
protected void deliverResult(CommCareSetupActivity receiver, org.commcare.android.tasks.ResourceEngineTask.ResourceEngineOutcomes result) {
boolean startOverInstall;
if(result == ResourceEngineOutcomes.StatusInstalled){
startOverInstall = false;
receiver.reportSuccess(true);
} else if(result == ResourceEngineOutcomes.StatusUpToDate){
startOverInstall = false;
receiver.reportSuccess(false);
} else if (result == ResourceEngineOutcomes.StatusMissing || result == ResourceEngineOutcomes.StatusMissingDetails){
startOverInstall = false;
CustomProgressDialog lastDialog = receiver.getCurrentDialog();
boolean inKeepTryingMode = (lastDialog == null) ? false : lastDialog.isChecked();
if (inKeepTryingMode) {
receiver.startResourceInstall(false);
} else {
receiver.failMissingResource(this.missingResourceException, result);
}
} else if (result == ResourceEngineOutcomes.StatusBadReqs){
startOverInstall = false;
receiver.failBadReqs(badReqCode, vRequired, vAvailable, majorIsProblem);
} else if (result == ResourceEngineOutcomes.StatusFailState){
startOverInstall = true;
receiver.failWithNotification(ResourceEngineOutcomes.StatusFailState);
} else if (result == ResourceEngineOutcomes.StatusNoLocalStorage) {
startOverInstall = true;
receiver.failWithNotification(ResourceEngineOutcomes.StatusNoLocalStorage);
} else if(result == ResourceEngineOutcomes.StatusBadCertificate){
startOverInstall = false;
receiver.failWithNotification(ResourceEngineOutcomes.StatusBadCertificate);
} else {
startOverInstall = true;
receiver.failUnknown(ResourceEngineOutcomes.StatusFailUnknown);
}
/*
* startOverInstall will be used on next install to indicate whether
* we want to start from the existing resource table or a new one,
* based on the outcome of this install
*/
receiver.ccApp.getAppPreferences().edit().putBoolean(KEY_START_OVER, startOverInstall).commit();
/*
* Check if we want to record this as a 'last install time', based on the
* state of the resource table before and after this install took place
*/
ResourceTable temporary = receiver.ccApp.getCommCarePlatform().getUpgradeResourceTable();
if (temporary.getTableReadiness() == ResourceTable.RESOURCE_TABLE_PARTIAL &&
receiver.resourceTableWasFresh) {
receiver.ccApp.getAppPreferences().edit().putLong(KEY_LAST_INSTALL, System.currentTimeMillis()).commit();
}
}
/*
* (non-Javadoc)
* @see org.commcare.android.tasks.templates.CommCareTask#deliverUpdate(java.lang.Object, java.lang.Object[])
*/
@Override
protected void deliverUpdate(CommCareSetupActivity receiver, int[]... update) {
receiver.updateProgress(update[0][0], update[0][1], update[0][2]);
}
/*
* (non-Javadoc)
* @see org.commcare.android.tasks.templates.CommCareTask#deliverError(java.lang.Object, java.lang.Exception)
*/
@Override
protected void deliverError(CommCareSetupActivity receiver, Exception e) {
receiver.failUnknown(ResourceEngineOutcomes.StatusFailUnknown);
}
};
task.connect(this);
task.execute(ref);
} else {
Log.i("commcare-install", "Blocked a resource install press since a task was already running");
}
}
/*
* (non-Javadoc)
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, MODE_BASIC, 0, Localization.get("menu.basic")).setIcon(android.R.drawable.ic_menu_help);
menu.add(0, MODE_ADVANCED, 0, Localization.get("menu.advanced")).setIcon(android.R.drawable.ic_menu_edit);
menu.add(0, MODE_ARCHIVE, 0, Localization.get("menu.archive")).setIcon(android.R.drawable.ic_menu_upload);
return true;
}
/*
* (non-Javadoc)
* @see android.app.Activity#onPrepareOptionsMenu(android.view.Menu)
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem basic = menu.findItem(MODE_BASIC);
MenuItem advanced = menu.findItem(MODE_ADVANCED);
if(uiState == UiState.advanced) {
basic.setVisible(true);
advanced.setVisible(false);
} else if(uiState == UiState.ready){
basic.setVisible(false);
advanced.setVisible(true);
} else if(uiState == UiState.basic){
basic.setVisible(false);
advanced.setVisible(true);
} else{
basic.setVisible(false);
advanced.setVisible(false);
}
return true;
}
public void setModeToAutoUpgrade(){
retryButton.setText(Localization.get("upgrade.button.retry"));
startOverButton.setText(Localization.get("upgrade.button.startover"));
buttonView.setVisibility(View.INVISIBLE);
}
public void setModeToReady(String incomingRef) {
buttonView.setVisibility(View.VISIBLE);
mainMessage.setText(Localization.get("install.ready"));
editProfileRef.setText(incomingRef);
advancedView.setVisibility(View.GONE);
mScanBarcodeButton.setVisibility(View.GONE);
installButton.setVisibility(View.VISIBLE);
startOverButton.setText(Localization.get("install.button.startover"));
startOverButton.setVisibility(View.VISIBLE);
addressEntryButton.setVisibility(View.GONE);
retryButton.setVisibility(View.GONE);
viewNotificationButton.setVisibility(View.GONE);
}
public void setModeToError(boolean canRetry){
buttonView.setVisibility(View.VISIBLE);
advancedView.setVisibility(View.GONE);
mScanBarcodeButton.setVisibility(View.GONE);
installButton.setVisibility(View.GONE);
startOverButton.setVisibility(View.VISIBLE);
addressEntryButton.setVisibility(View.GONE);
if(canRetry){
retryButton.setVisibility(View.VISIBLE);
}
else{
retryButton.setVisibility(View.GONE);
}
}
public void setModeToBasic(){
this.setModeToBasic(Localization.get("install.barcode"));
}
public void setModeToBasic(String message){
buttonView.setVisibility(View.VISIBLE);
editProfileRef.setText("");
this.incomingRef = null;
mainMessage.setText(message);
addressEntryButton.setVisibility(View.VISIBLE);
advancedView.setVisibility(View.GONE);
mScanBarcodeButton.setVisibility(View.VISIBLE);
viewNotificationButton.setVisibility(View.GONE);
startOverButton.setVisibility(View.GONE);
installButton.setVisibility(View.GONE);
retryButton.setVisibility(View.GONE);
retryButton.setText(Localization.get("install.button.retry"));
startOverButton.setText(Localization.get("install.button.startover"));
}
public void setModeToAdvanced(){
buttonView.setVisibility(View.VISIBLE);
mainMessage.setText(Localization.get("install.manual"));
advancedView.setVisibility(View.VISIBLE);
mScanBarcodeButton.setVisibility(View.GONE);
addressEntryButton.setVisibility(View.GONE);
installButton.setVisibility(View.VISIBLE);
startOverButton.setText(Localization.get("install.button.startover"));
startOverButton.setVisibility(View.VISIBLE);
installButton.setEnabled(true);
viewNotificationButton.setVisibility(View.GONE);
retryButton.setVisibility(View.GONE);
retryButton.setText(Localization.get("install.button.retry"));
startOverButton.setText(Localization.get("install.button.startover"));
}
/*
* (non-Javadoc)
* @see org.commcare.android.framework.CommCareActivity#onOptionsItemSelected(android.view.MenuItem)
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MODE_BASIC:
setUiState(UiState.basic);
break;
case MODE_ADVANCED:
setUiState(UiState.advanced);
break;
case MODE_ARCHIVE:
Intent i = new Intent(getApplicationContext(), InstallArchiveActivity.class);
startActivityForResult(i, ARCHIVE_INSTALL);
break;
}
refreshView();
return true;
}
public void done(boolean requireRefresh) {
//TODO: We might have gotten here due to being called from the outside, in which
//case we should manually start up the home activity
if(Intent.ACTION_VIEW.equals(CommCareSetupActivity.this.getIntent().getAction())) {
//Call out to CommCare Home
Intent i = new Intent(getApplicationContext(), CommCareHomeActivity.class);
i.putExtra(KEY_REQUIRE_REFRESH, requireRefresh);
startActivity(i);
finish();
return;
} else {
//Good to go
Intent i = new Intent(getIntent());
i.putExtra(KEY_REQUIRE_REFRESH, requireRefresh);
setResult(RESULT_OK, i);
finish();
return;
}
}
public void fail(NotificationMessage message) {
fail(message, false);
}
public void fail(NotificationMessage message, boolean alwaysNotify) {
fail(message, alwaysNotify, true);
}
public void fail(NotificationMessage message, boolean alwaysNotify, boolean canRetry){
Toast.makeText(this, message.getTitle(), Toast.LENGTH_LONG).show();
setUiState(UiState.error);
retryCount++;
if(retryCount > RETRY_LIMIT){
canRetry = false;
}
if(isAuto || alwaysNotify) {
CommCareApplication._().reportNotificationMessage(message);
viewNotificationButton.setVisibility(View.VISIBLE);
}
if(isAuto) {
done(false);
} else {
if(alwaysNotify) {
this.displayMessage= Localization.get("notification.for.details.setup.wrapper", new String[] {message.getDetails()});
this.canRetry = canRetry;
mainMessage.setText(displayMessage);
} else {
this.displayMessage= message.getDetails();
this.canRetry = canRetry;
String fullErrorMessage = message.getDetails();
if(alwaysNotify){
fullErrorMessage = fullErrorMessage + message.getAction();
}
mainMessage.setText(fullErrorMessage);
}
}
refreshView();
}
/**
* Sets the state of the Ui and handles one-off changes that might need
* to happen between certain states.
* @param newUiState
*/
public void setUiState(UiState newUiState){
//We might want to do some one-off configuration
//stuff if we're undergoing certain transitions
//Ready -> Advanced: Set up the URL Spinner appropriately.
if(this.uiState == UiState.ready && newUiState == UiState.advanced){
previousUrlPosition = -1;
urlSpinner.setSelection(2);
}
this.uiState = newUiState;
}
/*
* (non-Javadoc)
* @see android.support.v4.app.FragmentActivity#onBackPressed()
*/
@Override
public void onBackPressed(){
if(uiState == UiState.advanced || uiState == UiState.ready) {
setUiState(UiState.basic);
setModeToBasic();
} else {
super.onBackPressed();
}
}
// All final paths from the Update are handled here (Important! Some interaction modes should always auto-exit this activity)
// Everything here should call one of: fail() or done()
/** All methods for implementation of ResourceEngineListener **/
public void reportSuccess(boolean appChanged) {
//If things worked, go ahead and clear out any warnings to the contrary
CommCareApplication._().clearNotifications("install_update");
if(!appChanged) {
Toast.makeText(this, Localization.get("updates.success"), Toast.LENGTH_LONG).show();
}
done(appChanged);
}
public void failMissingResource(UnresolvedResourceException ure, ResourceEngineOutcomes statusMissing) {
fail(NotificationMessageFactory.message(statusMissing, new String[] {null, ure.getResource().getDescriptor(), ure.getMessage()}), ure.isMessageUseful());
}
public void failBadReqs(int code, String vRequired, String vAvailable, boolean majorIsProblem) {
String versionMismatch = Localization.get("install.version.mismatch", new String[] {vRequired,vAvailable});
String error = "";
if(majorIsProblem){
error=Localization.get("install.major.mismatch");
}
else{
error=Localization.get("install.minor.mismatch");
}
fail(NotificationMessageFactory.message(ResourceEngineOutcomes.StatusBadReqs, new String[] {null, versionMismatch, error}), true);
}
public void failUnknown(ResourceEngineOutcomes unknown) {
fail(NotificationMessageFactory.message(unknown));
}
public void updateProgress(int done, int total, int phase) {
if(inUpgradeMode) {
if (phase == ResourceEngineTask.PHASE_DOWNLOAD) {
updateProgress(Localization.get("updates.found", new String[] {""+done,""+total}), DIALOG_INSTALL_PROGRESS);
} else if (phase == ResourceEngineTask.PHASE_COMMIT) {
updateProgress(Localization.get("updates.downloaded"), DIALOG_INSTALL_PROGRESS);
}
}
else {
updateProgress(Localization.get("profile.found", new String[]{""+done,""+total}), DIALOG_INSTALL_PROGRESS);
}
}
public void failWithNotification(ResourceEngineOutcomes statusfailstate) {
fail(NotificationMessageFactory.message(statusfailstate), true);
}
/*
* (non-Javadoc)
* @see org.commcare.android.framework.CommCareActivity#generateProgressDialog(int)
*
* implementation of generateProgressDialog() for DialogController --
* all other methods handled entirely in CommCareActivity
*/
@Override
public CustomProgressDialog generateProgressDialog(int taskId) {
if (taskId != DIALOG_INSTALL_PROGRESS) {
System.out.println("WARNING: taskId passed to generateProgressDialog does not match "
+ "any valid possibilities in CommCareSetupActivity");
return null;
}
String title, message;
if (uiState == UiState.upgrade) {
title = Localization.get("updates.title");
message = Localization.get("updates.checking");
} else {
title = Localization.get("updates.resources.initialization");
message = Localization.get("updates.resources.profile");
}
CustomProgressDialog dialog = CustomProgressDialog.newInstance(title, message, taskId);
String checkboxText = "Keep trying if network is interrupted";
CustomProgressDialog lastDialog = getCurrentDialog();
boolean isChecked = (lastDialog == null) ? false : lastDialog.isChecked();
dialog.addCheckbox(checkboxText, isChecked);
return dialog;
}
}