How to get form definition from ODK Collect FormsProvider

We're working on an external app that uses the android ContentProviders to pull the data directly from ODK Collect.
The above code works very nicely to get a cursor from which I can read the actual Form object's attributes.

cursor = context.getContentResolver().query(
        Uri.parse("content://org.odk.collect.android.provider.odk.forms/forms/"),
        null,
        null,
        null,
        null);
if (cursor != null) {
    while (cursor.moveToNext()) {
        ODKForm form = new ODKForm(cursor);
        forms.add(form);
    }
}

However, I also need to read the form definition. More specifically the metadata we have stored in the prefill data. What I have tried is below, but I think I may be approaching it wrong as I get the following error:

java.io.FileNotFoundException: No files supported by provider at content://org.odk.collect.android.provider.odk.forms/forms/1
Uri uri = Uri.parse("content://org.odk.collect.android.provider.odk.forms/forms/"+mItem.getId());
ContentResolver resolver = context.getContentResolver();
ContentProviderClient providerClient = resolver.acquireUnstableContentProviderClient(uri);
ParcelFileDescriptor descriptor = providerClient.openFile(uri, "r");

That can't be done. Can you describe your use case in more detail? Why can't the application e.g. also pull the form definition directly from the server?

This makes me think you want instances (filled forms), not forms definitions which is what the forms provider provides.

See related discussion here (with opposite direction of data flow).

I was worried that might be the case.

This is actually a replacement to the app @yanokwa built out from the Clinic app for the MSDS DataExchange app.

In the form definition there is prefill data we fields that contain contain an expiry date and a submissions limit.

I was initially looking at the Instance provider but we need the metadata before a submission has been created and any instances created.

Our current workaround is to use the App user token to pull the definition from the server as well. But the users are going to have intermittent connections so there's a lot could go wrong.

Also our submissions are encrypted so I'm not sure if we would even be able to read prefill data from an instance?

Would it be reasonable to suggest that the FormsProvider could also return the form definition data?
I've been digging around in the Collect source so I think I may be able to make the addition unless there is a technical limitation that I'm missing?

After digging into the Collect code. I managed to get a slight understanding of where the form definitions and prefill data is read back out.

Do you have a architecture diagram of the app so I can get a better understanding?

Also is there any specific reason form definitions aren't exposed by a ContentProvider? As if not, if someone could point me in the right direction, I'd be more than happy to fork and implement it.

No. The best general overview available really is to go through the contributing guide (especially the "state of the union").

Also is there any specific reason form definitions aren't exposed by a ContentProvider? As if not, if someone could point me in the right direction, I'd be more than happy to fork and implement it.

No specific reason I can think of. I guess before it would have been available via the file system - we now store Collect files in our app specific directory due to changes in Android Storage. I do believe you'll be able to get at them via the file system if you build in a flow that allows the user to grant permission for your app to access Collect's app files. Alternatively, you could look at submitting a pull request with an implementation that allows you to grab the form definition via the Content Provider. If you go with the latter it'd be good to discuss the exact needs and your approach in the ODK Slack.

3 posts were split to a new topic: How can I pass choice labels to an external application?