use of org.odk.collect.android.utilities.InstancesRepositoryProvider in project collect by opendatakit.
the class QuitFormDialogFragment method onCreateDialog.
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
super.onCreateDialog(savedInstanceState);
String title = formSaveViewModel.getFormName() == null ? getActivity().getString(R.string.no_form_loaded) : formSaveViewModel.getFormName();
List<IconMenuItem> items;
if (settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.KEY_SAVE_MID)) {
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_save, R.string.keep_changes), new IconMenuItem(R.drawable.ic_delete, R.string.do_not_save));
} else {
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_delete, R.string.do_not_save));
}
ListView listView = DialogUtils.createActionListView(getActivity());
final IconMenuListAdapter adapter = new IconMenuListAdapter(getActivity(), items);
listView.setAdapter(adapter);
listView.setOnItemClickListener((parent, view, position, id) -> {
IconMenuItem item = (IconMenuItem) adapter.getItem(position);
if (item.getTextResId() == R.string.keep_changes) {
if (listener != null) {
listener.onSaveChangesClicked();
}
} else {
formSaveViewModel.ignoreChanges();
String action = getActivity().getIntent().getAction();
if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_EDIT.equals(action)) {
// caller is waiting on a picked form
Uri uri = null;
String path = formSaveViewModel.getAbsoluteInstancePath();
if (path != null) {
Instance instance = new InstancesRepositoryProvider(requireContext()).get().getOneByPath(path);
if (instance != null) {
uri = InstancesContract.getUri(currentProjectProvider.getCurrentProject().getUuid(), instance.getDbId());
}
}
if (uri != null) {
getActivity().setResult(RESULT_OK, new Intent().setData(uri));
}
}
getActivity().finish();
}
if (getDialog() != null) {
getDialog().dismiss();
}
});
return new MaterialAlertDialogBuilder(getActivity()).setTitle(getString(R.string.quit_application, title)).setNegativeButton(getActivity().getString(R.string.do_not_exit), (dialog, id) -> {
dialog.cancel();
dismiss();
}).setView(listView).create();
}
use of org.odk.collect.android.utilities.InstancesRepositoryProvider in project collect by opendatakit.
the class SaveFormToDisk method exportData.
/**
* Write's the data to the sdcard, and updates the instances content provider.
* In theory we don't have to write to disk, and this is where you'd add
* other methods.
*/
private void exportData(boolean markCompleted, FormSaver.ProgressListener progressListener) throws IOException, EncryptionException {
FormController formController = Collect.getInstance().getFormController();
progressListener.onProgressUpdate(getLocalizedString(Collect.getInstance(), R.string.survey_saving_collecting_message));
ByteArrayPayload payload = formController.getFilledInFormXml();
// write out xml
String instancePath = formController.getInstanceFile().getAbsolutePath();
for (String fileName : tempFiles) {
mediaUtils.deleteMediaFile(fileName);
}
progressListener.onProgressUpdate(getLocalizedString(Collect.getInstance(), R.string.survey_saving_saving_message));
writeFile(payload, instancePath);
// Write last-saved instance
String lastSavedPath = formController.getLastSavedPath();
writeFile(payload, lastSavedPath);
// update the uri. We have exported the reloadable instance, so update status...
// Since we saved a reloadable instance, it is flagged as re-openable so that if any error
// occurs during the packaging of the data for the server fails (e.g., encryption),
// we can still reopen the filled-out form and re-save it at a later time.
updateInstanceDatabase(true, true);
if (markCompleted) {
// now see if the packaging of the data for the server would make it
// non-reopenable (e.g., encryption or other fraction of the form).
boolean canEditAfterCompleted = formController.isSubmissionEntireForm();
boolean isEncrypted = false;
// build a submission.xml to hold the data being submitted
// and (if appropriate) encrypt the files on the side
// pay attention to the ref attribute of the submission profile...
File instanceXml = formController.getInstanceFile();
File submissionXml = new File(instanceXml.getParentFile(), "submission.xml");
payload = formController.getSubmissionXml();
// write out submission.xml -- the data to actually submit to aggregate
progressListener.onProgressUpdate(getLocalizedString(Collect.getInstance(), R.string.survey_saving_finalizing_message));
writeFile(payload, submissionXml.getAbsolutePath());
// see if the form is encrypted and we can encrypt it...
EncryptedFormInformation formInfo = EncryptionUtils.getEncryptedFormInformation(uri, formController.getSubmissionMetadata());
if (formInfo != null) {
// if we are encrypting, the form cannot be reopened afterward
canEditAfterCompleted = false;
// and encrypt the submission (this is a one-way operation)...
progressListener.onProgressUpdate(getLocalizedString(Collect.getInstance(), R.string.survey_saving_encrypting_message));
EncryptionUtils.generateEncryptedSubmission(instanceXml, submissionXml, formInfo);
isEncrypted = true;
analytics.logEvent(ENCRYPT_SUBMISSION, AnalyticsUtils.getFormHash(Collect.getInstance().getFormController()), "");
}
// At this point, we have:
// 1. the saved original instanceXml,
// 2. all the plaintext attachments
// 2. the submission.xml that is the completed xml (whether encrypting or not)
// 3. all the encrypted attachments if encrypting (isEncrypted = true).
//
// NEXT:
// 1. Update the instance database (with status complete).
// 2. Overwrite the instanceXml with the submission.xml
// and remove the plaintext attachments if encrypting
updateInstanceDatabase(false, canEditAfterCompleted);
if (!canEditAfterCompleted) {
manageFilesAfterSavingEncryptedForm(instanceXml, submissionXml);
} else {
// (we don't need to delete and rename anything).
if (!submissionXml.delete()) {
String msg = "Error deleting " + submissionXml.getAbsolutePath() + " (instance is re-openable)";
Timber.w(msg);
}
}
// (anything not named instanceXml or anything not ending in .enc)
if (isEncrypted) {
InstancesRepository instancesRepository = new InstancesRepositoryProvider(Collect.getInstance()).get();
Instance instance = instancesRepository.get(ContentUriHelper.getIdFromUri(uri));
// Clear the geometry. Done outside of updateInstanceDatabase to avoid multiple
// branches and because it has no knowledge of encryption status.
instancesRepository.save(new Instance.Builder(instance).geometry(null).geometryType(null).build());
ContentValues values = new ContentValues();
values.put(DatabaseInstanceColumns.GEOMETRY, (String) null);
values.put(DatabaseInstanceColumns.GEOMETRY_TYPE, (String) null);
if (!EncryptionUtils.deletePlaintextFiles(instanceXml, new File(lastSavedPath))) {
Timber.e("Error deleting plaintext files for %s", instanceXml.getAbsolutePath());
}
}
}
}
use of org.odk.collect.android.utilities.InstancesRepositoryProvider in project collect by opendatakit.
the class InstanceUploaderTask method onPostExecute.
@Override
protected void onPostExecute(Outcome outcome) {
synchronized (this) {
if (outcome != null && stateListener != null) {
if (outcome.authRequestingServer != null) {
stateListener.authRequest(outcome.authRequestingServer, outcome.messagesByInstanceId);
} else {
stateListener.uploadingComplete(outcome.messagesByInstanceId);
// Delete instances that were successfully sent and that need to be deleted
// either because app-level auto-delete is enabled or because the form
// specifies it.
Set<String> instanceIds = outcome.messagesByInstanceId.keySet();
boolean isFormAutoDeleteOptionEnabled;
// the app preferences set for delete after submission
if (deleteInstanceAfterSubmission != null) {
isFormAutoDeleteOptionEnabled = deleteInstanceAfterSubmission;
} else {
isFormAutoDeleteOptionEnabled = settingsProvider.getUnprotectedSettings().getBoolean(ProjectKeys.KEY_DELETE_AFTER_SEND);
}
Stream<Instance> instancesToDelete = instanceIds.stream().map(id -> new InstancesRepositoryProvider(Collect.getInstance()).get().get(Long.parseLong(id))).filter(instance -> instance.getStatus().equals(Instance.STATUS_SUBMITTED)).filter(instance -> shouldFormBeDeleted(formsRepository, instance.getFormId(), instance.getFormVersion(), isFormAutoDeleteOptionEnabled));
DeleteInstancesTask dit = new DeleteInstancesTask(instancesRepository, formsRepository);
dit.execute(instancesToDelete.map(Instance::getDbId).toArray(Long[]::new));
}
}
}
}
use of org.odk.collect.android.utilities.InstancesRepositoryProvider in project collect by opendatakit.
the class FormEntryActivity method finishAndReturnInstance.
/**
* Returns the instance that was just filled out to the calling activity, if
* requested.
*/
private void finishAndReturnInstance() {
String action = getIntent().getAction();
if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_EDIT.equals(action)) {
// caller is waiting on a picked form
Uri uri = null;
String path = getAbsoluteInstancePath();
if (path != null) {
Instance instance = new InstancesRepositoryProvider(this).get().getOneByPath(path);
if (instance != null) {
uri = InstancesContract.getUri(currentProjectProvider.getCurrentProject().getUuid(), instance.getDbId());
}
}
if (uri != null) {
setResult(RESULT_OK, new Intent().setData(uri));
}
}
finish();
}
use of org.odk.collect.android.utilities.InstancesRepositoryProvider in project collect by opendatakit.
the class FormEntryActivity method createViewForFormEnd.
/**
* Creates the final screen in a form-filling interaction. Allows the user to set a display
* name for the instance and to decide whether the form should be finalized or not. Presents
* a button for saving and exiting.
*/
private View createViewForFormEnd(FormController formController) {
if (formController.getSubmissionMetadata().instanceName != null) {
saveName = formController.getSubmissionMetadata().instanceName;
} else {
// no meta/instanceName field in the form -- see if we have a
// name for this instance from a previous save attempt...
String uriMimeType = null;
Uri instanceUri = getIntent().getData();
if (instanceUri != null) {
uriMimeType = getContentResolver().getType(instanceUri);
}
if (saveName == null && uriMimeType != null && uriMimeType.equals(InstancesContract.CONTENT_ITEM_TYPE)) {
Instance instance = new InstancesRepositoryProvider(Collect.getInstance()).get().get(ContentUriHelper.getIdFromUri(instanceUri));
if (instance != null) {
saveName = instance.getDisplayName();
}
}
if (saveName == null) {
saveName = formSaveViewModel.getFormName();
}
}
FormEndView endView = new FormEndView(this, formSaveViewModel.getFormName(), saveName, InstancesDaoHelper.isInstanceComplete(true, settingsProvider.getUnprotectedSettings().getBoolean(KEY_COMPLETED_DEFAULT)), new FormEndView.Listener() {
@Override
public void onSaveAsChanged(String saveAs) {
// Seems like this is needed for rotation?
saveName = saveAs;
}
@Override
public void onSaveClicked(boolean markAsFinalized) {
if (saveName.length() < 1) {
showShortToast(FormEntryActivity.this, R.string.save_as_error);
} else {
formSaveViewModel.saveForm(getIntent().getData(), markAsFinalized, saveName, true);
}
}
});
if (!settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.KEY_MARK_AS_FINALIZED)) {
endView.findViewById(R.id.mark_finished).setVisibility(View.GONE);
}
if (formController.getSubmissionMetadata().instanceName != null) {
// if instanceName is defined in form, this is the name -- no
// revisions
// display only the name, not the prompt, and disable edits
endView.findViewById(R.id.save_form_as).setVisibility(View.GONE);
endView.findViewById(R.id.save_name).setEnabled(false);
endView.findViewById(R.id.save_name).setVisibility(View.VISIBLE);
}
// override the visibility settings based upon admin preferences
if (!settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.KEY_SAVE_AS)) {
endView.findViewById(R.id.save_form_as).setVisibility(View.GONE);
endView.findViewById(R.id.save_name).setVisibility(View.GONE);
}
if (showNavigationButtons) {
updateNavigationButtonVisibility();
}
return endView;
}
Aggregations