Android uses V8 without WebView

I am running javascript with Java. Rhino works very well for this on the desktop, but should return to (slow) interpreted mode on Android (due to the fact that dalvik cannot execute Java bytecode, compiles the Rhino JIT).

Android has a built-in JavaScript V8 engine, accessed through JNI, and it should provide much better performance than Rhino; however, the only way to find access to it is indirectly through WebView.

Unfortunately, WebView requires context and a failure with NPE with zero context, so I cannot even create an instance of a dummy WebView to just execute the code and return the result. The nature of my exercise does not actually allow me to provide context for the WebView, so I hope that maybe I don’t notice something there.

Some of these V8Threads work in parallel, so it is not possible (as far as I know) to add a WebView to my layout and hide it, since I do not think that one WebView can perform functions in several threads.

private class V8Thread extends Thread { private WebView webView; private String source; private double pi; private int i, j; public V8Thread(int i, int j) { pi = 0.0; this.i = i; this.j = j; source = ""; try { InputStreamReader isReader = new InputStreamReader(assetManager.open("pi.js")); int blah = isReader.read(); while (blah != -1) { source += (char)blah; blah = isReader.read(); } webView = new WebView(null); webView.loadData(source, "text/html", "utf-8"); webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(this, "V8Thread"); } catch (IOException e) { e.printStackTrace(); } } public double getResult() { return pi; } @Override public void run() { webView.loadUrl("javascript:Androidpicalc("+i+","+j+")"); } } 

Ideally, there should be some supported way to directly call V8, or at least run javascript without requiring an actual WebView, since it looks like a rather awkward and confusing method to run javascript code.

UPDATE

I changed my code a bit, although it is unclear that now I am creating an instance of V8Threads in AsyncTasks onPreExecute (), saving everything else in doInBackground (). The source code is read earlier in the program, so it is not redundantly re-read for each stream.

Since V8Thread is now created in the user interface thread, I can pass it the current View of the Context (I use fragments, so I can’t just pass it “this”), so it won’t work anymore.

 private class V8Thread extends Thread { private WebView webView; private double pi; private int i, j; public V8Thread(int i, int j) { pi = 0.0; this.i = i; this.j = j; source = ""; webView = new WebView(v.getContext()); } @SuppressWarnings("unused") public void setResult(String in) { Log.d("Pi",in); } public double getResult() { return pi; } @Override public void run() { webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(this, "V8Thread"); webView.loadData(source, "text/html", "utf-8"); //webView.loadUrl("javascript:Androidpicalc("+i+","+j+")"); webView.loadUrl("javascript:test()"); Log.d("V8Thread","Here"); } } 

However, when executing, logcat throws one error out of the stream "Unable to get width view after first layout", and javascript code never executes. I know that the thread is fully triggered because the “Here” log message is being sent. Here is the corresponding test () function in the js code.

 function test() { V8Thread.setResult("blah"); } 

When working correctly, "blah" should appear four times in logcat, but it never appears. Maybe my source code does not read correctly, but I doubt it.

 Scanner scan = new Scanner(assetManager.open("pi.js")); while (scan.hasNextLine()) source += scan.nextLine(); 

The only thing I can imagine is that due to these aforementioned errors, webView can never cope with javascript execution.

I will also add that pi.js only contains javascript, no HTML. However, even when I wrap it with enough HTML to qualify as a web page, I still have no luck.

+45
javascript android v8
Jul 30 2018-11-11T00:
source share
5 answers

You can create a new V8 context through your API and use it to execute JavaScript, look in the https://android.googlesource.com/platform/external/v8 include directory, which contains two C ++ header files, Link to libwebcore.so (compiled from https://android.googlesource.com/platform/external/webkit ) via the NDK, nothing special.

 v8::Persistent<v8::Context> context = v8::Persistent<v8::Context>::New(v8::Context::New()); context->Enter(); 

See https://developers.google.com/v8/get_started , which will run on Android. Just make sure the device really comes with V8 (some older devices come with AO [JavaScript Core]).

+10
Aug 15 '12 at 16:59
source share

A little late answer, but it can be useful to anyone who stumbles on this question. I used the J2V8 library, which is a Java shell on the Google V8 engine. This library comes with pre-compiled V8 binaries for x86 and armv7l Android devices. It works without a problem. See here for tutorials. Just keep in the middle that, since pure V8 is just an Ecmascript engine, there is no DOM element available.

+4
Jan 21 '16 at 12:48
source share

I found this really great open source ECMAScript JS Engine compatible fully written in C called duktape

Duktape is an embedded Javascript engine with an emphasis on portability and compactness.

You still have to do the ndk-jni business, but it’s pretty straight forward. Just include duktape.c and duktape.h from the redistributable here (if you do not want to go through the build process yourself) in the jni folder, update Android.mk and all that.

Here is an example C snippet to get you started.

 #include "duktape.h" JNIEXPORT jstring JNICALL Java_com_ndktest_MainActivity_evalJS (JNIEnv * env, jobject obj, jstring input){ duk_context *ctx = duk_create_heap_default(); const char *nativeString = (*env)->GetStringUTFChars(env, input, 0); duk_push_string(ctx, nativeString); duk_eval(ctx); (*env)->ReleaseStringUTFChars(env, input, nativeString); jstring result = (*env)->NewStringUTF(env, duk_to_string(ctx, -1)); duk_destroy_heap(ctx); return result; } 

Good luck

+2
Feb 11 '15 at 15:10
source share

Can you hold on to Context , which is your Application ? There are several ways to do this.

UPDATE

According to this Android documentation, your associated Javascript code will work in a separate process, so there is no need to configure it in your own Thread .

From the link:

Note. The object associated with your JavaScript runs in a different thread, not in the thread in which it was created. ("Object" refers to the JavascriptInterface class)

+1
Jul 30 2018-11-11T00:
source share



All Articles