Integrate h5p-standalone in Android app (Webview) for offline-usage: Path to content files not correct (solved)

programmieraffe's picture
Forums: 

Hey there,

H5P is great if there is internet access or a local server, but what if there is nothing and we have just a smartphone or tablet and no internet access?  I started a little experiment to check if the h5p standalone version can be integrated in simple android apps (i want to check out iOS apps later). In general the h5p types are working, but the files can not be found because the path generated by the standalone-h5p-script is not working.

My approach was the following:

Generate a standalone html version of a h5p content (interactive video)

  1. Download an h5p-Package (Interactive Video with video file, no youtube video)  as Video.h5p
  2. Download the h5p-standalone repository  (https://github.com/tunapanda/h5p-standalone), unzip it, install gulp (see README)
  3. Rename the video.h5p file to h5p.zip, unzip it
  4. Copy unzipped content to workspace/ directory of h5p-standalone/
  5. Run "gulp demo" in h5p-standalone
  6. I moved and renamed the h5p-standalone/demo/index.html to /h5p-standalone/index.html and changed the paths in the html file, see example: edited index.html

Create Android app with Webview

The webview component is basically just a webbrowser inside an app which can load local files as well - so it should load h5p as well, at least in theory ;-)

  1. Install Android Studio
  2. Create Android App with Webview-Component, following this tutorial: https://www.youtube.com/watch?v=eJa8xie9WZs
  3. Connect Android Device or Install virtual device, hit "Run"-button to initialize the project (otherwise you can not add asset folder)
  4. Copy the previous generated dist/, workspace/ and index.html from h5p-standalone to the created asset/www/-folder inside the app folder (see Step 6 above!)
  5. You need to activate javascript, localstorage (DomStorage) and allow file access for XHR-requests, i used this JAVA code (I changed my webview layout id to "webview1")
WebView MyWebView = (WebView)findViewById(R.id.webview1);

MyWebView.getSettings().setJavaScriptEnabled(true);

MyWebView.getSettings().setAllowFileAccess(true);
MyWebView.getSettings().setAllowContentAccess(true);
MyWebView.getSettings().setAllowFileAccessFromFileURLs(true);
MyWebView.getSettings().setAllowUniversalAccessFromFileURLs(true);

MyWebView.getSettings().setDomStorageEnabled(true);

MyWebView.loadUrl("file:///android_asset/www/index.html");

If you also add the following code, you can debug the the Webview with Chrome Developer tools in the browser (chrome://inspect), which is very handy:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
   WebView.setWebContentsDebuggingEnabled(true);
}

More information here: https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews

The error message

Hit Run and test the app. It now kind of works but the files (image/video) can not be found, in my case there was a double slash in the path:

Failed to load resource:  workspace/content//videos/files-598b7e3281cde.mp4 

Unfortunately I could not find the method to change this wrong path, my modifications of H5P.getPath were not successful in h5p-standalone-main.js. The H5P.getPath function is also twice in h5p-standalone-main.js which was a bit strange? Can anybody advide me how to fix the path to get videos and images to load? Thanks very much in advance! (I can also provide more source code later if necessary). Would be really awesome if we could get this to work together!

Update: I looked into the wrong file to fix the path, the correct file to fix the path is h5p-standalone-frame.js, change the following line in the last h5p.getPath function (it is the one which is generated from h5p-overwrite.js, see gulpfile on github for more information):

if (contentId !== undefined) {
        // was before:
        //prefix = H5PIntegration.url + '/content/';
        // Bugfix by MA, remove last slash:
        prefix = H5PIntegration.url + '/content';
  }

It's now working and I can continue testing the possibilities :-) (Pull request was also added on github)

PS: I also discovered cocoon.io where you can just upload a zip file to generate a webview app like my described approach. 
Possible alternatives to this approach are app frameworks like Ionic or Phonegap, which are based on Cordova. The h5p scripts here have to be integrated into Cordova/AngularJS for Ionic - which is possible, but I couldn't do it myself - integrating third party scripts in angular is a bit tricky, but not impossible. Maybe someone has already tried this. 

Another approach could be to use an android webserver app (like this one) which serves the files, but I think that is not a good idea in terms of battery consumption. ;-) I also thought about taking a battery powered raspberry pi as mobile h5p wifi server, but that would only be a workaround - my goal here is to bundle h5p packages into apps. 

PPS: I used Android 7.0 and WebView Chrome stable for my experiment.

thomasmars's picture

Hi,
This sounds very promising. I have not tried the h5p-standalone script from tunapanda. Have you tried to contact him/them or raise an issue in their repository ?
Unfortunately I don't have much insight into Android app development either, so can't help you with the making the paths work.
Please let us know how this progresses, would be fun to hear more about this. Good luck ;)

otacke's picture

If you use function expressions in JavaScript, you can change them just like variables (although this might lead to confusion, indeed). Did you check that the the function expression that you changed was actually used? Adding some console.log statements should help you to narrow down the line of code where the "correct" H5P.getPath constructs the URL.

If you want to share your Android code (on github), make sure to go to the gradle projects panel in AndroidStudio and to execute :app/Tasks/build/clean. Otherwise you might have to share a lot of build files that are not necessary.

programmieraffe's picture

I did a lot of checks with console.log, but unfortunately I didn't check the standalone-frame.js file, I only checked in h5p-standalone.js. I found the error in the frame.js and updated the post. D'oh! :D

Thanks for the advice regarding AndroidStudio - very good to know! 

otacke's picture

Glad you're making progress!

Mitt94's picture

Hello Programmieraffe , I am currently doing my masters mandatory internship on h5p and my task is to develop a h5p viewer for android and ios .the app should work without internet connection. I tried a lot of ways but did not succed yet. It would be great help if you provide the source code of this project.Thank you very much.