ODK Collect API

See also

External Apps

ODK Collect supports several intents which allow it to be launched by external applications. You can open a specific form or lists of empty forms, saved forms, finalized forms or sent forms. The app also shares its data (a list of forms and instances) with external apps.

This section describes how to launch ODK Collect and open its activities from an external app and how to get the shared data. The code samples go in your custom Android application.

Understanding Intents and Content providers

An Intent is a messaging object you can use to request an action from another app component.

For more details on intents, you can refer to these Android docs.

A content provider component supplies data from one application to others on request.

For more details on content providers, you can refer to these Android docs.

Launching Collect activities and getting its shared data from an external application

To start one of ODK Collect's activities:

  1. Create a new intent using an appropriate action.

  2. Set the type of the created intent.

  3. Start an activity using the intent.

Launching the form list or instance list activity

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("vnd.android.cursor.dir/vnd.odk.form");
startActivity(intent);

This displays a list of forms and allows the user to select one and fill it.

Similarly, for an instance of the form:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("vnd.android.cursor.dir/vnd.odk.instance");
startActivity(intent);

This displays a list of saved forms and allows the user to select one and edit it.

Getting the list of forms and instances:

Using Content providers ODK Collect shares the list of forms and instances with other apps.

To fetch the list of forms, call:

Uri uri = "content://org.odk.collect.android.provider.odk.forms/forms"
getContentResolver().query(uri, null, null, null, null);

If you want to fetch the list of forms but with only the newest version for each form_id, call:

Uri uri = "content://org.odk.collect.android.provider.odk.forms/newestFormsByFormId"
getContentResolver().query(uri, null, null, null, null);

Similarly, for the list of instances:

Uri uri = "content://org.odk.collect.android.provider.odk.instances/instances"
getContentResolver().query(uri, null, null, null, null);

You can also get an individual (or filtered list) form/instance by adding selection criteria. For example, if you want to get a list of instances with a given jrFormId you can use:

Uri uri = "content://org.odk.collect.android.provider.odk.instances/instances"
getContentResolver().query(uri, null, "jrFormId=?", new String[]{"all-widgets"}, null);

This will return a Cursor with the list of forms/instances. You can iterate such a cursor and read the data stored in it:

if (cursor != null) {
    try {
        while (cursor.moveToNext()) {
            int id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
            String formName = cursor.getString(cursor.getColumnIndex(DISPLAY_NAME));

            // Collect data from other columns and store it in a list for example
        }
    } finally {
        cursor.close();
    }
}

The data stored in a cursor is different for forms and instances. The list of columns used to share forms is defined in DatabaseFormColumns. For instances it is: DatabaseInstanceColumns.

Getting the URI of a form or instance chosen by the user

Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("vnd.android.cursor.dir/vnd.odk.form");
static final int PICK_FORM_REQUEST = 1;  // The request code
startActivityForResult(intent, PICK_FORM_REQUEST);

To get the result, override onActivityResultMethod in the following way:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  // Check which request we're responding to
  if (requestCode == PICK_FORM_REQUEST) {
    // Make sure the request was successful
    if (resultCode == RESULT_OK) {
      // The Intent's data URI identifies which form was selected.
      Uri formUri = data.getData();
      // Do something with the form here
    }
  }
}

For an instance, change the intent type:

intent.setType("vnd.android.cursor.dir/vnd.odk.instance");

Using a URI to edit a form or instance

If the URI of a form or instance is known, it can be viewed or edited. For example, a URI received in onActivityResult() as described above can be used.

If the URI of a form or instance is not known, it can be generated by appending the id (received in a cursor after fetching the list of forms/instances as described above) to content://org.odk.collect.android.provider.odk.forms/forms/ in the case of forms and content://org.odk.collect.android.provider.odk.instances/instances/ in the case of instances.

Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData("content://org.odk.collect.android.provider.odk.forms/forms/2");
startActivityForResult(intent);

Note

The Form EDIT action returns an instance URI, so after saving such a form it should be returned in intent data (example: content://org.odk.collect.android.provider.odk.instances/instances/1).

The same thing can be done with a specific instance.

Warning

Launching Collect activities using their names is not supported because those names can change at any time.

Note

There might be other ways of interacting with ODK Collect using an external app not described in this doc. If you want to explore them, check out the ODK Collect Intents Tester app.

Did this page help you?

Selecting an option will open a 1-question survey

👍 Yes 👎 No