Thursday, January 7, 2016

Android: From Java to JavaScript and Back


After the fight with Android Studio and Eclipse yesterday, I finally got to try what I was planning to do all day:

  • From within JavaScript running in a WebView, Invoke Android Java code , and  
  • From Android Java code, inject JavaScript code into an HTML page in a WebView. 

There are a few samples that can be found for both routes, either in the official docs or in blog posts. However, there were some tricks to get even the simplest example running.

Other than the standard issues of having to enable JavaScript in the WebView and annotate the callback method, here are a couple of interesting ones that I faced trying the first route:

  • Default WebViewClient: Attempted to run some trivial JavaScript inside the WebView to make sure it is enabled. The simplest of examples (popping an alert) did not work. After looking around, it turns out that you must set a WebViewClient on the WebView, even if it is simply the default one from the SDK. Apparently, it provides a method that handles showing alerts to make them fit with the theme, etc.
  • Method Signature: The simplest of examples for calling Java from JavaScript did not work for me. I was getting a "Error calling method on NPObject" message. After trying a couple of things I decided to post on StackOverflow, but I had to double check my code before doing so. And guess what I found? I found that the method signature called from JavaScript did not match the one declared in Java. Fixing that got the sample to work.

The second route was not a smooth ride either. Here are a few issues I encountered:


  • Threading: Apparently, any interaction with a WebView has to happen on the 'same' thread (as the error stated). I figured that this meant the event thread, and indeed scheduling the injection of JavaScript using runOnUiThread solved this.
  • Navigation: Upon successful execution of JavaScript code, the original page content was replaced by the result of the JavaScript statement that just executed. Apparently, this is to be expected and others have solved this by appending a void(0); to the JavaScript code. The reason is explained here in detail.
  • Arguments: When passing JavaScript code as a String do not forget to quote values that are supposed to be String valued. This simple advice might save you considerable time if you are passing around element IDs. Apparently, when an element ID appeared in the JavaScript unquoted the interpreter took at it as a reference to the element!


No comments:

Post a Comment