Opening Local HTML Files in PSLab Android App

The PSLab Android App allows users to perform experiments using the PSLab device. The experience to perform an experiment should resemble the generic way to perform the experiment. So we associated an Experiment Doc file which the user can refer to while performing experiment. Just like a regular lab manual, the experiment doc contains the AIM, THEORY & FORMULAS, SCHEMATIC, OUTPUT, etc. In the PSLab Desktop App, since there was already a provision for using HTML docs and so I  avoided reinventing the wheel and used those html files as it is.

    

The problem we faced was how to open a bunch of HTML files with their corresponding CSS, JS files in Android’s webView.

There are two ways it can be done:

  • Host the experiment docs on a server and make a request from the android app for the specific experiment doc like Diode I-V, Zener I-V, etc.
  • Put the folder containing all html, CSS, js files in assets folder and request for the HTML doc files locally.

The PSLab developer team went with the second option as the availability of  Internet  is necessary for the performing experiment if we follow the first option and so to avoid this dependence on the Internet, we went with the second option and stored HTML docs locally in assets folder.

Implementation

  • Put the folder containing all the HTML, CSS, JS files in the assets folder in your android project. In this case the folder is DOC_HTML.

  • Define the WebView in xml and take the webView’s reference in your activity/fragment
    In xml
<WebView
   android:id="@+id/perform_experiment_wv"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

In activity/fragment

webView = (WebView) view.findViewById(R.id.perform_experiment_wv);
  • Load the url in webView in the format as shown below
webView.loadUrl("file:///android_asset/DOC_HTML/apps/" + htmlFile);

“file:///” acts as resource identifier, so file:///android_asset/ actually points to “pslab-android/app/src/main/assets/”.
From the assets directory, we can a provide route to any HTML file. Here I put all HTML files in apps folder and used the string variable “htmlFile” to point to the specific html file.

Similarly html files stored in the external storage can also be accessed but there are some cases you need to handle. For example,if external storage is mounted, you can’t request the html file from external storage.

To request html files from external storage, make sure that you have the following permission in your AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();

Relative to baseDir you can specify the path from your html files, like

baseDir + “DOC_HTML/apps” + htmlFile

Conclusion

Putting HTML files in the assets folder and requesting it by webView’s loadURL() method is the best but there are various drawbacks of using this method like the increase in size of the apk. In our case, the normal apk size was 3MB but after adding the html doc folder it increased to 7MB. It increased by almost an additional size of the html folder added in assets. As it’s written, in the android’s project overview guide, the assets folder contains files that should be compiled into an .apk file as-is.

Resources

Unit testing JSON files in assets folder of Android App

So here is the scenario, your android app has a lot of json files in the assets folder that are used to load some data when in first runs.
You are writing some unit tests, and want to make sure the integrity of the data in the assets/*.json are preserved.

You’d assume, that reading JSON files should not involve using the Android Runtime in any way, and we should be able to read JSON files in local JVM as well. But you’re wrong. The JSONObject and JSONArray classes of Android are part of android.jar, and hence

 
JSONObject myJson = new JSONObject(someString);

The above code will not work when running unit tests on local JVM.

Fortunately, our codebase already using Google’s GSoN library to parse JSON, and that works on local JVM too (because GSoN is a core Java library, not specifically an Android library).

Now the second problem that comes is that when running unit tests on local JVM we do not have the getResources() or getAssets() functions.
So how do we retrieve a file from the assets folder ?

So what I found out (after a bit of trial and error and poking around with various dir paths), is that the tests are run from the app folder (app being the Android application module – it is named app by default by Android Studio, though you might have had named it differently)

So in the tests file you can define at the beginning

    public static final String  ASSET_BASE_PATH = "../app/src/main/assets/";

And also create the following helper function

    public String readJsonFile (String filename) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(ASSET_BASE_PATH + filename)));
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();
        while (line != null) {
            sb.append(line);
            line = br.readLine();
        }

        return sb.toString();
    }

Now wherever you need this JSON data you can just do the following

        Gson gson = new GsonBuilder().create();
        events = gson.fromJson(readJsonFile("events.json"),
                Event.EventList.class);
        eventDatesList = gson.fromJson(readJsonFile("eventDates.json"), EventDates.EventDatesList.class);