I am trying to retrieve form data without using briefcase/aggregate since I will be strictly in an offline environment. I want to extract the data after a user has filled out a form and parse it for my own purposes in a separate application. Is this possible through some sort of Intent?
I have a working concept but wondering if there is a better/officially supported workflow. I could be off on how to go about this as I am just getting familiar with ODK and its capabilities.
Problem:
Extract data from ODK Collect form after user has filled out the data. This must occur in an offline environment.
Workflow:
User opens external app and through workflow is directed to ODK Collect through Intents. User collects data using ODK Collect. User finishes collecting data and is returned to external app. The external app then consumes the data the user just filled out.
Questions
Is extracting/removing data from a filled out ODK collect form via an Intent a supported workflow? If not is there any reason why the below working concept would not work.
The result from:
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(formUri);
startActivityForResult(intent,EDIT_FORM_REQUEST);
returns something like this: content://org.odk.collect.android.provider.odk.instances/instances/6
However there does not seem to be documentation on what to do with this. Is there another intent we can serve this to, like perhaps to get the data from it?
Working concept:
-
Launch ODK form list activity from app
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("vnd.android.cursor.dir/vnd.odk.form");
startActivityForResult(intent, PICK_FORM_REQUEST);
-
Recieve restult from app and direct to the form
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_FORM_REQUEST) {
if (resultCode == RESULT_OK) {
Uri formUri = data.getData();
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(formUri);
startActivityForResult(intent,EDIT_FORM_REQUEST);
}
}
}
-
Consume data after form is filled out. Solution below sort of works but feels very hackish. Basically I get the .xml form stored in the instances path. My plan is to then manually parse the .xml data
public static final String ODK_ROOT = Environment.getExternalStorageDirectory()
+ File.separator + "odk";
public static final String INSTANCES_PATH = ODK_ROOT + File.separator + "instances";@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == EDIT_FORM_REQUEST) {
// Consume data here.
// This is where it gets messy and doesn't seem like a workflow if supported
// Current solution below
String string = data.getDataString();
// ex: string = content://org.odk.collect.android.provider.odk.instances/instances/6
try {
File instancesDirectory = new File(INSTANCES_PATH);
if (instancesDirectory.exists()) {
File formsFilledOutDirectories = instancesDirectory.listFiles();
File lastFormfilledOutDirectory = formsFilledOutDirectories[formsFilledOutDirectories.length - 1];
File formOfInterestDir = lastFormfilledOutDirectory.listFiles();
File ActualFormFile = formOfInterestDir[formOfInterestDir.length-1];
if (ActualFormFile.exists()) {
InputStream in = new FileInputStream(new File(ActualFormFile.toURI()));
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
Element root = doc.getDocumentElement(); // perform DOM operations starting here.
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
Thanks for any input,