Pre-load forms in Collect APK

odk-collect
odk-xlsform
#1

Hi,

I intend to put (pre-load before distribution/installation) project forms into Collect APK (I will distribute this customized APK offline to my project team). I have already opened the collect source in Android Studio. Can someone please let me know where should I place the form XML file, for the app to show the form in the FILL NEW FORM tab already after the APK installation (without doing GET NEW FORM)?

Thanks,
Saad

#2

Hi Saad,

While I couldn't answer your question directly as I'm not an Android developer, I just want to share a personal view. I have run many surveys and almost every case we had to update the form during the fieldwork. So baking it into the app is quite 'dangerous'. Maybe your case is different, but I think it's better to bring this up.
Trung.

2 Likes
#3

@Saad There currently isn't a way to load the forms into the application in this way. Collect looks for the forms in /sdcard/odk/forms.

If the goal is to have a quick way to install a pre-configured copy of Collect with some forms, what I usually do is use adb on my computer to push both the APK and the necessary files.

Below are some scripts for Windows and macOS/Linux that uninstall Collect, delete all form and submission data, push previously exported settings, and a form to the SD card, and the install a local copy of Collect.

You'll likely have to weak the scripts, but hopefully it's a good starting place.

Windows Batch script

@echo off
REM :start
cls
REM pause
C:/adb.exe uninstall org.odk.collect.android
C:/adb.exe shell rm -r "/sdcard/odk/"
C:/adb.exe push "%cd%/collect.settings" /sdcard/odk/collect.settings
C:/adb.exe push "%cd%/training.xml" /sdcard/odk/forms/training.xml
C:/adb.exe push "%cd%/itemsets.csv" /sdcard/odk/forms/training-media/itemsets.csv
C:/adb.exe install "%cd%/collect.apk"
REM pause
REM goto start

macOS/Linux shell script -

#!/bin/bash

adb uninstall org.odk.collect.android;
adb shell "rm -r /sdcard/odk/";
adb push collect.settings /sdcard/odk/collect.settings;
adb push training.xml /sdcard/odk/forms/training.xml;
adb push itemsets.csv /sdcard/odk/forms/training-media/itemsets.csv;
adb install collect.apk;
1 Like
#4

Thanks for replying @yanokwa. I don't want to modify or add forms to an installed version of collect on the phone. My aim is to distribute the collect app with one form already present in it. So basically I want to put one form into the app, compile the app to make an APK, and then distribute it to my team. When they download, install and open the application, it should have one form already present in it, which they can start filling straight away. I don't want them to do GET NEW FORM because there would be no net connectivity there. Neither can I process 200+ phones through ADB.

I assume I clarified the thing here. Any possible way to put the form in the app and then compile the APK, in android studio?

Thanks,
Saad

#5

Hi @Saad,

Please refer Yaw post

He already answered your question and gave you an alternative way of doing it.

You are a technology person and I believe you know where these xml file get stored. In a directory created by the collect app.

1 Like
#6

Hi,

Please correct my understanding of Yaw's statement if it is wrong: Collect can look for /sdcard/odk/form directory on the phone when the APK has already been installed on the phone (Right or wrong?).

On the other hand, I am trying to push the form into APK 'before' it is installed on the phone. In other words, I wish to bundle the form inside the APK, so that it gets ported with the APK (not separately), and gets installed in the relevant directory as part of standard application installation (just like images are placed in assets, etc).

Please do correct me if I am missing the point.

Thanks a lot! :slight_smile:

#7

No you are not missing anything, you are right on Yaw's comment.

Being still a junior developer i dont know if it possible to create a directory and push content on fly. May be to change the path where to look for the forms , from what ever it is , to the assets path.

1 Like
#8

@Saad It is possible to modify Collect to place the necessary files on install, but you (or some Android dev you hire) have to make those changes. It's not as straight forward as putting some files in the source directory with Android Studio.

#9

Thanks. If there is some help material online in docs or some forum thread that could explain how to do it, please do direct me to it. Else, I will just let it go sadly :slight_smile:

#10

I'm no Collect expert, but because you would have to be building a custom version of Collect in any case to accomplish what you want, you might be able to 'hardcode' the form simply by putting the necessary XML form definition data inline in the code, in the appropriate place. Looking at the src, this looks promising: https://github.com/opendatakit/collect/blob/master/collect_app/src/main/java/org/odk/collect/android/tasks/FormLoaderTask.java

private FormDef createFormDefFromCacheOrXml(String formPath, File formXml) {
    ...
    fis = new FileInputStream(formXml);
    ...
    FormDef formDefFromXml = XFormUtils.getFormFromInputStream(fis, lastSavedSrc);
    if (formDefFromXml == null) {
        errorMsg = "Error reading XForm file";
    } else {
        Timber.i("Loaded in %.3f seconds.",
            (System.currentTimeMillis() - start) / 1000F);
        formDef = formDefFromXml;

        FormDefCache.writeCache(formDef, formPath);

        return formDefFromXml;
    }
    ....

If you have enternal datasets that would complicate matters a little, but again just search for "itemsets.csv" in the source and see if you can replace it with inline data/string.

Personally, I never tried anything like this, but for adding in a single custom form into Collect it might work, and it would avoid having to worry about somehow packaging an external form file alongside base Collect, which as @yanokwa alludes to isnt straightforward.

Again, this is a TOTAL hack, but it may serve your specific purpose. YMMV... There is obviously no online material or docs about such hacks, so you'd probably need to hire a ODK/Android dev to do it.