use of org.odk.collect.android.tasks.FormLoaderTask in project collect by opendatakit.
the class FormEntryActivity method onDestroy.
@Override
protected void onDestroy() {
if (formLoaderTask != null) {
formLoaderTask.setFormLoaderListener(null);
// but only if it's done, otherwise the thread never returns
if (formLoaderTask.getStatus() == AsyncTask.Status.FINISHED) {
FormLoaderTask t = formLoaderTask;
formLoaderTask = null;
t.cancel(true);
t.destroy();
}
}
if (saveToDiskTask != null) {
saveToDiskTask.setFormSavedListener(null);
// lives on and retains the FEC in memory.
if (saveToDiskTask.getStatus() == AsyncTask.Status.FINISHED) {
saveToDiskTask.cancel(true);
saveToDiskTask = null;
}
}
releaseOdkView();
formDefCacheCompositeDisposable.dispose();
super.onDestroy();
}
use of org.odk.collect.android.tasks.FormLoaderTask in project collect by opendatakit.
the class FormEntryActivity method loadingComplete.
/**
* loadingComplete() is called by FormLoaderTask once it has finished
* loading a form.
*/
@Override
public void loadingComplete(FormLoaderTask task, FormDef formDef) {
dismissDialog(PROGRESS_DIALOG);
final FormController formController = task.getFormController();
// these are bogus if
int requestCode = task.getRequestCode();
// pendingActivityResult is
// false
int resultCode = task.getResultCode();
Intent intent = task.getIntent();
formLoaderTask.setFormLoaderListener(null);
FormLoaderTask t = formLoaderTask;
formLoaderTask = null;
t.cancel(true);
t.destroy();
Collect.getInstance().setFormController(formController);
supportInvalidateOptionsMenu();
Collect.getInstance().setExternalDataManager(task.getExternalDataManager());
// Set the language if one has already been set in the past
String[] languageTest = formController.getLanguages();
if (languageTest != null) {
String defaultLanguage = formController.getLanguage();
String newLanguage = FormsDaoHelper.getFormLanguage(formPath);
long start = System.currentTimeMillis();
Timber.i("calling formController.setLanguage");
try {
formController.setLanguage(newLanguage);
} catch (Exception e) {
// if somehow we end up with a bad language, set it to the default
Timber.e("Ended up with a bad language. %s", newLanguage);
formController.setLanguage(defaultLanguage);
}
Timber.i("Done in %.3f seconds.", (System.currentTimeMillis() - start) / 1000F);
}
boolean pendingActivityResult = task.hasPendingActivityResult();
if (pendingActivityResult) {
// set the current view to whatever group we were at...
refreshCurrentView();
// process the pending activity request...
onActivityResult(requestCode, resultCode, intent);
return;
}
// it can be a normal flow for a pending activity result to restore from
// a savepoint
// (the call flow handled by the above if statement). For all other use
// cases, the
// user should be notified, as it means they wandered off doing other
// things then
// returned to ODK Collect and chose Edit Saved Form, but that the
// savepoint for that
// form is newer than the last saved version of their form data.
boolean hasUsedSavepoint = task.hasUsedSavepoint();
if (hasUsedSavepoint) {
runOnUiThread(() -> ToastUtils.showLongToast(R.string.savepoint_used));
}
// Set saved answer path
if (formController.getInstanceFile() == null) {
// Create new answer folder.
String time = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.ENGLISH).format(Calendar.getInstance().getTime());
String file = formPath.substring(formPath.lastIndexOf('/') + 1, formPath.lastIndexOf('.'));
String path = Collect.INSTANCES_PATH + File.separator + file + "_" + time;
if (FileUtils.createFolder(path)) {
File instanceFile = new File(path + File.separator + file + "_" + time + ".xml");
formController.setInstanceFile(instanceFile);
}
formController.getTimerLogger().logTimerEvent(TimerLogger.EventTypes.FORM_START, 0, null, false, true);
} else {
Intent reqIntent = getIntent();
boolean showFirst = reqIntent.getBooleanExtra("start", false);
formController.getTimerLogger().logTimerEvent(TimerLogger.EventTypes.FORM_RESUME, 0, null, false, true);
if (!showFirst) {
if (!allowMovingBackwards) {
FormIndex formIndex = SaveFormIndexTask.loadFormIndexFromFile();
if (formIndex != null) {
formController.jumpToIndex(formIndex);
refreshCurrentView();
return;
}
}
String formMode = reqIntent.getStringExtra(ApplicationConstants.BundleKeys.FORM_MODE);
if (formMode == null || ApplicationConstants.FormModes.EDIT_SAVED.equalsIgnoreCase(formMode)) {
startActivity(new Intent(this, EditFormHierarchyActivity.class));
// so we don't show the intro screen before jumping to the hierarchy
return;
} else {
if (ApplicationConstants.FormModes.VIEW_SENT.equalsIgnoreCase(formMode)) {
startActivity(new Intent(this, ViewFormHierarchyActivity.class));
}
finish();
}
}
}
refreshCurrentView();
if (formDef != null) {
final File cachedFormDefFile = FormDefCache.getCacheFile(new File(formPath));
if (cachedFormDefFile.exists()) {
Timber.i("FormDef %s is already in the cache", cachedFormDefFile.toString());
} else {
Disposable formDefCacheDisposable = writeCacheAsync(formDef, cachedFormDefFile).subscribe(() -> {
}, Timber::e);
formDefCacheCompositeDisposable.add(formDefCacheDisposable);
}
}
}
use of org.odk.collect.android.tasks.FormLoaderTask in project collect by opendatakit.
the class FormEntryActivity method onCreate.
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// external intent
try {
Collect.createODKDirs();
} catch (RuntimeException e) {
createErrorDialog(e.getMessage(), EXIT);
return;
}
setContentView(R.layout.form_entry);
errorMessage = null;
beenSwiped = false;
alertDialog = null;
currentView = null;
inAnimation = null;
outAnimation = null;
gestureDetector = new GestureDetector(this, this);
questionHolder = findViewById(R.id.questionholder);
initToolbar();
nextButton = findViewById(R.id.form_forward_button);
nextButton.setOnClickListener(v -> {
beenSwiped = true;
showNextView();
});
backButton = findViewById(R.id.form_back_button);
backButton.setOnClickListener(v -> {
beenSwiped = true;
showPreviousView();
});
String startingXPath = null;
String waitingXPath = null;
String instancePath = null;
boolean newForm = true;
autoSaved = false;
allowMovingBackwards = (boolean) AdminSharedPreferences.getInstance().get(KEY_MOVING_BACKWARDS);
if (savedInstanceState != null) {
state = savedInstanceState;
if (savedInstanceState.containsKey(KEY_FORMPATH)) {
formPath = savedInstanceState.getString(KEY_FORMPATH);
}
if (savedInstanceState.containsKey(KEY_INSTANCEPATH)) {
instancePath = savedInstanceState.getString(KEY_INSTANCEPATH);
}
if (savedInstanceState.containsKey(KEY_XPATH)) {
startingXPath = savedInstanceState.getString(KEY_XPATH);
Timber.i("startingXPath is: %s", startingXPath);
}
if (savedInstanceState.containsKey(KEY_XPATH_WAITING_FOR_DATA)) {
waitingXPath = savedInstanceState.getString(KEY_XPATH_WAITING_FOR_DATA);
Timber.i("waitingXPath is: %s", waitingXPath);
}
if (savedInstanceState.containsKey(NEWFORM)) {
newForm = savedInstanceState.getBoolean(NEWFORM, true);
}
if (savedInstanceState.containsKey(KEY_ERROR)) {
errorMessage = savedInstanceState.getString(KEY_ERROR);
}
saveName = savedInstanceState.getString(KEY_SAVE_NAME);
if (savedInstanceState.containsKey(KEY_AUTO_SAVED)) {
autoSaved = savedInstanceState.getBoolean(KEY_AUTO_SAVED);
}
}
// Dialogs mid form just disappear on rotation.
if (errorMessage != null) {
createErrorDialog(errorMessage, EXIT);
return;
}
// Check to see if this is a screen flip or a new form load.
Object data = getLastCustomNonConfigurationInstance();
if (data instanceof FormLoaderTask) {
formLoaderTask = (FormLoaderTask) data;
} else if (data instanceof SaveToDiskTask) {
saveToDiskTask = (SaveToDiskTask) data;
} else if (data == null) {
if (!newForm) {
if (getFormController() != null) {
refreshCurrentView();
} else {
Timber.w("Reloading form and restoring state.");
// we need to launch the form loader to load the form
// controller...
formLoaderTask = new FormLoaderTask(instancePath, startingXPath, waitingXPath);
Collect.getInstance().getActivityLogger().logAction(this, "formReloaded", formPath);
// TODO: this doesn' work (dialog does not get removed):
// showDialog(PROGRESS_DIALOG);
// show dialog before we execute...
formLoaderTask.execute(formPath);
}
return;
}
// Not a restart from a screen orientation change (or other).
Collect.getInstance().setFormController(null);
supportInvalidateOptionsMenu();
Intent intent = getIntent();
if (intent != null) {
Uri uri = intent.getData();
String uriMimeType = null;
if (uri != null) {
uriMimeType = getContentResolver().getType(uri);
}
if (uriMimeType == null && intent.hasExtra(EXTRA_TESTING_PATH)) {
formPath = intent.getStringExtra(EXTRA_TESTING_PATH);
} else if (uriMimeType != null && uriMimeType.equals(InstanceColumns.CONTENT_ITEM_TYPE)) {
// get the formId and version for this instance...
FormInfo formInfo = ContentResolverHelper.getFormDetails(uri);
if (formInfo == null) {
createErrorDialog(getString(R.string.bad_uri, uri), EXIT);
return;
}
instancePath = formInfo.getInstancePath();
Collect.getInstance().getActivityLogger().logAction(this, "instanceLoaded", instancePath);
String jrFormId = formInfo.getFormID();
String jrVersion = formInfo.getFormVersion();
String[] selectionArgs;
String selection;
if (jrVersion == null) {
selectionArgs = new String[] { jrFormId };
selection = FormsColumns.JR_FORM_ID + "=? AND " + FormsColumns.JR_VERSION + " IS NULL";
} else {
selectionArgs = new String[] { jrFormId, jrVersion };
selection = FormsColumns.JR_FORM_ID + "=? AND " + FormsColumns.JR_VERSION + "=?";
}
int formCount = FormsDaoHelper.getFormsCount(selection, selectionArgs);
if (formCount < 1) {
createErrorDialog(getString(R.string.parent_form_not_present, jrFormId) + ((jrVersion == null) ? "" : "\n" + getString(R.string.version) + " " + jrVersion), EXIT);
return;
} else {
formPath = FormsDaoHelper.getFormPath(selection, selectionArgs);
// database to fix it.
if (formCount > 1) {
createErrorDialog(getString(R.string.survey_multiple_forms_error), EXIT);
return;
}
}
} else if (uriMimeType != null && uriMimeType.equals(FormsColumns.CONTENT_ITEM_TYPE)) {
formPath = ContentResolverHelper.getFormPath(uri);
if (formPath == null) {
createErrorDialog(getString(R.string.bad_uri, uri), EXIT);
return;
} else {
// This is the fill-blank-form code path.
// See if there is a savepoint for this form that
// has never been
// explicitly saved
// by the user. If there is, open this savepoint
// (resume this filled-in
// form).
// Savepoints for forms that were explicitly saved
// will be recovered
// when that
// explicitly saved instance is edited via
// edit-saved-form.
final String filePrefix = formPath.substring(formPath.lastIndexOf('/') + 1, formPath.lastIndexOf('.')) + "_";
final String fileSuffix = ".xml.save";
File cacheDir = new File(Collect.CACHE_PATH);
File[] files = cacheDir.listFiles(pathname -> {
String name = pathname.getName();
return name.startsWith(filePrefix) && name.endsWith(fileSuffix);
});
// explicitly saved by the user...
for (File candidate : files) {
String instanceDirName = candidate.getName().substring(0, candidate.getName().length() - fileSuffix.length());
File instanceDir = new File(Collect.INSTANCES_PATH + File.separator + instanceDirName);
File instanceFile = new File(instanceDir, instanceDirName + ".xml");
if (instanceDir.exists() && instanceDir.isDirectory() && !instanceFile.exists()) {
// yes! -- use this savepoint file
instancePath = instanceFile.getAbsolutePath();
break;
}
}
}
} else {
Timber.e("Unrecognized URI: %s", uri);
createErrorDialog(getString(R.string.unrecognized_uri, uri), EXIT);
return;
}
formLoaderTask = new FormLoaderTask(instancePath, null, null);
Collect.getInstance().getActivityLogger().logAction(this, "formLoaded", formPath);
showDialog(PROGRESS_DIALOG);
// show dialog before we execute...
formLoaderTask.execute(formPath);
}
}
}
use of org.odk.collect.android.tasks.FormLoaderTask in project collect by opendatakit.
the class FormEntryActivity method onResume.
@Override
protected void onResume() {
super.onResume();
String navigation = (String) GeneralSharedPreferences.getInstance().get(PreferenceKeys.KEY_NAVIGATION);
showNavigationButtons = navigation.contains(PreferenceKeys.NAVIGATION_BUTTONS);
backButton.setVisibility(showNavigationButtons ? View.VISIBLE : View.GONE);
nextButton.setVisibility(showNavigationButtons ? View.VISIBLE : View.GONE);
if (errorMessage != null) {
if (alertDialog != null && !alertDialog.isShowing()) {
createErrorDialog(errorMessage, EXIT);
} else {
return;
}
}
FormController formController = getFormController();
Collect.getInstance().getActivityLogger().open();
if (formLoaderTask != null) {
formLoaderTask.setFormLoaderListener(this);
if (formController == null && formLoaderTask.getStatus() == AsyncTask.Status.FINISHED) {
FormController fec = formLoaderTask.getFormController();
if (fec != null) {
loadingComplete(formLoaderTask, formLoaderTask.getFormDef());
} else {
dismissDialog(PROGRESS_DIALOG);
FormLoaderTask t = formLoaderTask;
formLoaderTask = null;
t.cancel(true);
t.destroy();
// there is no formController -- fire MainMenu activity?
startActivity(new Intent(this, MainMenuActivity.class));
}
}
} else {
if (formController == null) {
// there is no formController -- fire MainMenu activity?
startActivity(new Intent(this, MainMenuActivity.class));
return;
} else {
refreshCurrentView();
}
}
if (saveToDiskTask != null) {
saveToDiskTask.setFormSavedListener(this);
}
}
use of org.odk.collect.android.tasks.FormLoaderTask in project collect by opendatakit.
the class FormEntryActivity method onCreateDialog.
/**
* We use Android's dialog management for loading/saving progress dialogs
*/
@Override
protected Dialog onCreateDialog(int id) {
switch(id) {
case PROGRESS_DIALOG:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onCreateDialog.PROGRESS_DIALOG", "show");
progressDialog = new ProgressDialog(this);
DialogInterface.OnClickListener loadingButtonListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onCreateDialog.PROGRESS_DIALOG", "cancel");
dialog.dismiss();
if (formLoaderTask != null) {
formLoaderTask.setFormLoaderListener(null);
FormLoaderTask t = formLoaderTask;
formLoaderTask = null;
t.cancel(true);
t.destroy();
}
finish();
}
};
progressDialog.setTitle(getString(R.string.loading_form));
progressDialog.setMessage(getString(R.string.please_wait));
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(false);
progressDialog.setButton(getString(R.string.cancel_loading_form), loadingButtonListener);
return progressDialog;
case SAVING_DIALOG:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onCreateDialog.SAVING_DIALOG", "show");
progressDialog = new ProgressDialog(this);
progressDialog.setTitle(getString(R.string.saving_form));
progressDialog.setMessage(getString(R.string.please_wait));
progressDialog.setIndeterminate(true);
progressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onCreateDialog.SAVING_DIALOG", "OnDismissListener");
cancelSaveToDiskTask();
}
});
return progressDialog;
case SAVING_IMAGE_DIALOG:
progressDialog = new ProgressDialog(this);
progressDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
progressDialog.setMessage(getString(R.string.please_wait));
progressDialog.setCancelable(false);
return progressDialog;
}
return null;
}
Aggregations