package org.commcare.activities;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import org.commcare.CommCareApplication;
import org.commcare.android.logging.ForceCloseLogger;
import org.commcare.dalvik.R;
import org.commcare.logging.AndroidLogger;
import org.commcare.models.database.SqlStorage;
import org.commcare.android.database.user.models.FormRecord;
import org.commcare.preferences.CommCareServerPreferences;
import org.commcare.tasks.ProcessAndSendTask;
import org.commcare.utils.FormUploadResult;
import org.commcare.utils.SessionUnavailableException;
import org.commcare.utils.StorageUtils;
import org.commcare.views.ManagedUi;
import org.commcare.views.UiElement;
import org.javarosa.core.services.Logger;
/**
* @author ctsims
*/
@ManagedUi(R.layout.screen_recovery)
public class RecoveryActivity extends SessionAwareCommCareActivity<RecoveryActivity> {
@UiElement(R.id.screen_recovery_unsent_message)
TextView txtUnsentForms;
@UiElement(R.id.screen_recovery_unsent_button)
Button sendForms;
@UiElement(R.id.screen_recovery_app_install_message)
TextView appState;
@UiElement(R.id.screen_recovery_app_install_button)
Button btnRecoverApp;
@UiElement(R.id.screen_recovery_progress)
TextView txtUserMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// launching activity, not just changing orientation
updateSendFormsState();
updateRecoverAppState();
}
sendForms.setOnClickListener(new OnClickListener() {
@SuppressLint("NewApi")
@Override
public void onClick(View v) {
FormRecord[] records = StorageUtils.getUnsentRecordsForCurrentApp(
CommCareApplication.instance().getUserStorage(FormRecord.class));
SharedPreferences settings = CommCareApplication.instance().getCurrentApp().getAppPreferences();
ProcessAndSendTask<RecoveryActivity> mProcess =
new ProcessAndSendTask<RecoveryActivity>(RecoveryActivity.this,
settings.getString(CommCareServerPreferences.PREFS_SUBMISSION_URL_KEY,
RecoveryActivity.this.getString(R.string.PostURL)), true) {
@Override
protected void onPreExecute() {
super.onPreExecute();
displayMessage("Submitting form(s) to the server...");
}
@Override
protected void deliverResult(RecoveryActivity receiver, FormUploadResult result) {
if (result == FormUploadResult.PROGRESS_LOGGED_OUT) {
receiver.displayMessage("Log-in expired during send. Please press back and log in again");
return;
}
int successfulSends = this.getSuccessfulSends();
if (result == FormUploadResult.FULL_SUCCESS) {
receiver.displayMessage("Send succesful. All " + successfulSends + " forms were submitted");
} else if (result == FormUploadResult.FAILURE) {
String remainder = successfulSends > 0 ? " Only " + successfulSends + " were submitted" : "";
receiver.displayMessage("There were errors submitting the forms." + remainder);
} else if (result == FormUploadResult.TRANSPORT_FAILURE) {
receiver.displayMessage("Unable to contact the remote server.");
}
}
@Override
protected void deliverUpdate(RecoveryActivity receiver, Long... update) {
//we don't need to deliver updates here, it happens on the notification bar
}
@Override
protected void deliverError(RecoveryActivity receiver, Exception e) {
Logger.log(AndroidLogger.TYPE_ERROR_ASSERTION, "Error in recovery form send: " + ForceCloseLogger.getStackTrace(e));
receiver.displayMessage("Error while sending : " + e.getMessage());
}
};
mProcess.addSubmissionListener(CommCareApplication.instance().getSession().getListenerForSubmissionNotification());
mProcess.connect(RecoveryActivity.this);
//Execute on a true multithreaded chain. We should probably replace all of our calls with this
//but this is the big one for now.
mProcess.executeParallel(records);
}
});
btnRecoverApp.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
displayMessage("App recovery is not yet enabled. Please clear user data (After sending all of your forms!) and re-install.");
}
});
}
private void displayMessage(String text) {
txtUserMessage.setText(text);
}
@Override
public void startBlockingForTask(int id) {
btnRecoverApp.setEnabled(false);
sendForms.setEnabled(false);
}
@Override
public void stopBlockingForTask(int id) {
updateSendFormsState();
updateRecoverAppState();
}
private void updateRecoverAppState() {
btnRecoverApp.setEnabled(false);
if (!CommCareApplication.instance().isStorageAvailable()) {
appState.setText("app state unavailable.");
return;
}
if (CommCareApplication.instance().getCurrentApp().getAppResourceState() == CommCareApplication.STATE_CORRUPTED) {
appState.setText("App install is corrupt. Make sure forms are sent before attempting recovery.");
btnRecoverApp.setEnabled(true);
} else {
appState.setText("App is installed and valid");
btnRecoverApp.setEnabled(false);
}
}
private void updateSendFormsState() {
sendForms.setEnabled(false);
if (!CommCareApplication.instance().isStorageAvailable()) {
txtUnsentForms.setText("unsent forms unavailable.");
return;
}
try {
CommCareApplication.instance().getSession();
} catch (SessionUnavailableException sue) {
txtUnsentForms.setText("Couldn't read unsent forms. Not Logged in");
return;
}
SqlStorage<FormRecord> recordStorage = CommCareApplication.instance().getUserStorage(FormRecord.class);
try {
FormRecord[] records = StorageUtils.getUnsentRecordsForCurrentApp(recordStorage);
if (records.length == 0) {
txtUnsentForms.setText("This device has no unsent forms");
} else {
txtUnsentForms.setText("There are " + records.length + " unsent form(s) on this device");
sendForms.setEnabled(true);
}
} catch (Exception e) {
Logger.log(AndroidLogger.TYPE_ERROR_ASSERTION, e.getMessage());
txtUnsentForms.setText("Couldn't read unsent forms. Error : " + e.getMessage());
}
}
}