Landing into ODK Collect, into a specific form, with some pre-set fields

I am the current maintainer of ghini.desktop and author of ghini.pocket, a small Android app. ghini.pocket is a database viewer which includes a small copy of a central database, it is used to review the situation on the field (in a garden, the database is the garden collection), and we're using ODK Collect to correct or complete record information.

when the user finds anything wrong in the ghini.pocket database, they can click on 'correct' and ghini.pocket copies the current plant code to the clipboard, then activates ODK Collect, making it land in the 'fill blank form' page.

the user now has to activate the correct form (ghini.collect already knows which form should be activated) and the user has to copy the plant code from the clipboard into the Plant ID entry (we have users forgetting this step).

I would like to simplify the above user actions, I would like to activate ODK Collect directly in the right blank form, and possibly pre-fill the Plant ID field in the new form.

any hints on where to start?

cheers,
Mario

1 Like

I like this concept a lot @mfrasca! I think @Grzesiek2010's demo app that shows the intents Collect can respond to will provide you with the information you need: https://github.com/grzesiek2010/collectTester He's in the process of doing a little bit more cleanup and then it will be an official ODK resource. It's complete enough to illustrate the concepts in the mean time and you'll also find the readme helpful.

reading from a couple of StackOverflow question/answers (eg: https://stackoverflow.com/questions/3913592/start-an-activity-with-a-parameter), looks like this is not going to be difficult. my first guess from the client side would be:

try {
    Intent i = new Intent(Intent.ACTION_VIEW);
    i.setType(FORMS_CHOOSER_INTENT_TYPE);
    i.putExtra("form_id", "plant_form_s");
    i.putExtra("plant_id", searchedPlantCode);
    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clip = ClipData.newPlainText("last plant search", searchedPlantCode);
    clipboard.setPrimaryClip(clip);
    startActivity(i);
} catch (ActivityNotFoundException e) {
    Toast.makeText(this, R.string.missing_web_browser, Toast.LENGTH_LONG).show();
}

then, within ODK Collect, where is my intent received?

Did you get a chance to look at the app @LN mentioned above? It'll give you a concrete example of everything you need to get started!

I have indeed used the collectTester to understand what I could do
"client-side", and it did help me, but I don't see how it can help me
with something not yet implemented in Collect itself.

I might be missing the point, obviously.

What I think I need (and I can't find): send an extra dictionary
together with the intent »vnd.android.cursor.dir/vnd.odk.form« (this
part is easy), and that Collect uses one key in the dictionary to select
the form, and other keys to pre-fill fields in the form (this part I miss).

I don't think there is this functionality in ODK Collect, or is there?

@Grzesiek2010, you have concrete hints, haven't you?

ciao,

Mario

@mfrasca
You can open a specific form directly from your app but if you want to do something extra like pasting values automatically (don't know if I understand everything well) it will require changes on the Collect side.

Regards,
Grzegorz

Hi @Grzesiek2010,

how do I do this 'open a specific form'? collectTester doesn't show it,
or you just added the example and I didn't yet see your commits? could
be, I'm not well connected at the moment, I only updated two days ago.

you see, the use case is:

  • review a database record (identified by its primary key),

  • open collect to correct / integrate the data,

  • pass the value of the primary key from the reviewer to the collector.

and yes, I was sure I would need changes on the Collect side, and I want
to make them and share them on github, but I don't recognize where and
how the vnd.android.cursor.dir/vnd.odk.form intent is received and handled.

thank you all for all information and help,

MF

@mfrasca
This is the line where I open a specific form https://github.com/grzesiek2010/collectTester/blob/master/collectTester_app/src/main/java/org/odk/collectTester/activities/ListActivity.java#L72

Let me know if you need more help.

Regards,
Grzegorz

I think what people have done to pre-populate instances is to generate the instance XML, write it into the appropriate directory and push the record to the DB. I believe that's what @yanokwa did with ODK Clinic.

1 Like

Hi Hélène,

I think what people have done to pre-populate instances is to generate
the instance XML, write it into the appropriate directory and push the
record to the DB. I believe that’s what @yanokwa
http://forum.getodk.org/u/yanokwa did with ODK Clinic.
I see, and I see two problems with this approach:

  • the record would be in the database before the user has confirmed he
    wants to insert it.
  • the client software (ghini.pocket in my case) needs insider
    information about ODK Collect.

I'm sorry I'm asking so many questions, but I'm not yet able to compile
Collect and collectTester, I'm in marginal internet area, where
downloads are quite expensive, I'm trying to keep things under control,
but it's difficult.

thanks,
Mario

Hi Grzegorz,

@mfrasca http://forum.getodk.org/u/mfrasca
This is the line where I open a specific form
https://github.com/grzesiek2010/collectTester/blob/master/collectTester_app/src/main/java/org/odk/collectTester/activities/ListActivity.java#L72

Let me know if you need more help.

Regards,
Grzegorz


thanks, it was not where I had expected it, my best guess was in
MainActivity.java, and my search term was
"vnd.android.cursor.dir/vnd.odk.form", which led me to
FORMS_CHOOSER_INTENT_TYPE.

I expected the form name to be given in an extra string.

is there any reason for the two styles? (ActionEdit, URI) /
'vnd.android.cursor.dir/*' ?
are they received differently in Collect ?

thanks, and regards,
Mario

You can't relay on form name since you can have many forms with the same name so you need to use an URI with form ID but if you are sure you have only one form with that name you can read all, then filter by name, read the required form ID and use that value with the URI.

is there any reason for the two styles? (ActionEdit, URI) /
‘vnd.android.cursor.dir/*’ ?

If you want to open a specific form you have to use URI otherwise you just set your intent type to open one of available activities.

Regards,
Grzegorz