Launching External Apps

Launching external apps to populate single fields

ODK Collect can launch external applications to populate string, integer or decimal fields using the ex:intentAction(intentExtras) appearance.

This feature configures an Android intent. Intents are messaging objects used to request an action from another app component. Learn more in the Android docs.

Collect builds the action using the text immediately after ex: and before an opening parenthesis (if it exists). For example, in the string ex:org.opendatakit.counter(intentExtras), the action name is org.opendatakit.counter. An action name must include a namespace, such as org.opendatakit or com.google. For example, ex:org.opendatakit.counter is valid but ex:counter is not.

The parameters defined in the optional parentheses represent extended data ("extras") to be added to the intent. Extras are specified by a comma-delimited list of name=value pairs. The text to the left of the equals sign represents the extra name and may require a namespace. The text to the right of the equals sign represents the extra value.

The values of extras can be:

  • XPath expressions referring to other fields and including function calls
  • String literals defined in single quotes
  • Raw integers or decimals

An extra named value that holds the current value for the current field is always passed with the intent. Since v1.4.3, additional parameters with user-defined names can be specified. There are two reserved names: value and uri_data.

Since Collect v1.16.0, the data that the intent operates on can be set by using the reserved uri_data parameter. This is particularly useful for implicit intents such as android.intent.action.SENDTO.

XLSForm

survey
type name label appearance
integer counter Click launch to start the counter app ex:org.opendatakit.counter(form_id='counter-form', form_name='Counter Form', question_id='1', question_name='Counter')

In the examples above, the extras specified have names form_id, form_name, question_id, and question_name.

Launching external apps to populate multiple fields

Since v1.4.3, a field-list group can have an intent attribute that allows an external application to populate it.

XLSForm

survey
type name label appearance body::intent
begin_group mygroup Fields to populate field-list org.mycompany.myapp(my_text='Some text', uuid=/myform/meta/instanceID)
text sometext Some text    
integer someinteger Some integer    
end_group        
<group ref="/myform/mygroup" appearance="field-list"
        intent="org.mycompany.myapp(my_text='Some text',
                                    uuid=/myform/meta/instanceID)">
  <label>Fields to populate</label>
  <input ref="/myform/mygroup/sometext">
    <label>Some text</label>
  </input>
  <input ref="/myform/mygroup/someinteger">
    <label>Some integer</label>
  </input>
</group>

The intent attribute is only used when the group has an appearance of field-list. The format and the functionality of the intent value is the same as above. If bundle of values returned by the external application contains values whose keys match the type and the name of the sub-fields, then these values overwrite the current values of those sub-fields.

The external app is launched with the parameters that are defined in the intent string plus the values of all the sub-fields that are either text, decimal, or integer. Any other sub-field is invisible to the external app.

Specifying a URI as intent data

Since Collect v1.16.0, the value for the reserved parameter name uri_data is converted to a URI and used as the data for the intent. The intent data determines which application to launch when using implicit intents such as SENDTO. For example:

ex:android.intent.action.SENDTO(uri_data='smsto:5555555', sms_body=${message})
Launches a new message in an SMS app with the destination number set to 5555555 and the message body set to the contents of the message field.
ex:android.intent.action.SENDTO(uri_data='mailto:example@example.com?subject=${subject}&body=${message})
Launches a new message in an email app with destination address set to example@example.com, the subject set to the contents of the subject field and the body set to the contents of the message field.
ex:android.intent.action.DIAL(uri_data='tel:5555555')
Launches a phone dialer with the number 5555555 as the number to dial.

Notice that the URI must include a scheme, such as mailto: or https://.