I have code written in HTML, CSS and JS for a Three.js scene showing a 3D headmodel and marks on it. It works on my Angular project.
I was also able to get it to work in my Xamarin Forms project for both Android and iOS by just adding the HTML code into a webview.
However, when I try to do the same in an Android native app in a webview, it does not work.
Here is what I am trying;
// get the reference from the XML Layout
final WebView wv = (WebView) findViewById(R.id.web_view_impact_detail);
/*
WebSettings
Manages settings state for a WebView. When a
WebView is first created, it obtains a set
of default settings.
setJavaScriptEnabled(boolean flag)
Tells the WebView to enable JavaScript execution.
*/
wv.getSettings().setJavaScriptEnabled(true);
String htmlData = "<html lang = 'en'><head> <meta name='viewport' content='width=device-width, height=device-height initial-scale=1'> <script src='three.min.js'></script> <script src='OBJLoader.js'></script> <script src='OrbitControls.js'></script> <script src='GeometryUtils.js'></script> <script src='CanvasRenderer.js'></script> <script src='DecalGeometry.js'></script> </head> <body> <label hidden id='x' value='-0.712'></label> <label hidden id='y' value='0.539'></label> <label hidden id='z' value='-0.448'></label> <label hidden id='alert' value='false'></label> <h4>Hello World</h4><script src='3d-head-mobile.js'></script> </body> </html> ";
wv.loadData(htmlData, "text/html; charset=utf-8", "UTF-8");
Here is the logcat info once I loaded the relevant layout
03-06 22:03:10.870 20385-20385/com. W/FA: Service connection failed: ConnectionResult{statusCode=SERVICE_VERSION_UPDATE_REQUIRED, resolution=null, message=null}
03-06 22:03:10.871 20385-20409/com. V/FA: Processing queued up service tasks: 0
03-06 22:03:10.883 20385-20385/com. W/chromium: [WARNING:ipc_message_attachment_set.cc(49)] MessageAttachmentSet destroyed with unconsumed attachments: 0/1
03-06 22:03:10.883 20385-20385/com. W/zygote: Attempt to remove non-JNI local reference, dumping thread
03-06 22:03:10.886 20385-20418/com. D/EGL_emulation: eglMakeCurrent: 0xdd205480: ver 3 0 (tinfo 0xdd203460)
03-06 22:03:10.942 20385-20441/com.aW/cr_CrashFileManager: /data/user/0/com./cache/WebView/Crash Reports does not exist or is not a directory
03-06 22:03:11.828 20385-20556/com.D/EGL_emulation: eglCreateContext: 0xc1b710e0: maj 3 min 0 rcv 3
03-06 22:03:11.840 20385-20556/com. D/EGL_emulation: eglMakeCurrent: 0xc1b710e0: ver 3 0 (tinfo 0xc8b58cc0)
03-06 22:03:11.924 20385-20556/com.I/VideoCapabilities: Unsupported profile 4 for video/mp4v-es
03-06 22:03:11.928 20385-20556/com.W/cr_MediaCodecUtil: HW encoder for video/avc is not available on this device.
03-06 22:03:11.952 20385-20556/com.D/EGL_emulation: eglCreateContext: 0xc1b71f20: maj 3 min 0 rcv 3
03-06 22:03:11.962 20385-20556/com.D/EGL_emulation: eglMakeCurrent: 0xc1b71f20: ver 3 0 (tinfo 0xc8b58cc0)
03-06 22:03:12.155 20385-20385/com.W/zygote: Attempt to remove non-JNI local reference, dumping thread
03-06 22:03:12.190 20385-20385/com.W/zygote: Attempt to remove non-JNI local reference, dumping thread
03-06 22:03:12.392 20385-20385/com.W/zygote: Attempt to remove non-JNI local reference, dumping thread
03-06 22:03:12.487 20385-20385/com.I/chatty: uid=10080(com.) identical 3 lines
03-06 22:03:12.515 20385-20385/com.W/zygote: Attempt to remove non-JNI local reference, dumping thread
03-06 22:03:12.895 20385-20385/com.W/zygote: Attempt to remove non-JNI local reference, dumping thread
I was able to get a THREE.js scene fully loaded into an Android webview. Here is how.
In the onCreate method of my activity;
// get the reference from the XML Layout
final WebView wv = (WebView) findViewById(R.id.web_view_impact_detail);
I needed to add more settings and allow access to the specific files referenced in my Javascript files that were linked in my HTML string.
Big help for that from this answer XMLHttpRequest cannot load file from android asset folder on emulator
/*
WebSettings
Manages settings state for a WebView. When a
WebView is first created, it obtains a set
of default settings.
setJavaScriptEnabled(boolean flag)
Tells the WebView to enable JavaScript execution.
etc.
*/
wv.getSettings().setJavaScriptEnabled(true);
wv.getSettings().setPluginState(WebSettings.PluginState.ON);
wv.getSettings().setAllowFileAccess(true);
wv.getSettings().setAllowContentAccess(true);
wv.getSettings().setAllowFileAccessFromFileURLs(true);
wv.getSettings().setAllowUniversalAccessFromFileURLs(true);
I then needed to pass in my variables differently in Java than in C#. I found that help here. How to format strings in Java
// create a string of our HTML data
String htmlData = "<html lang = 'en'><head> <meta name='viewport' content='width=device-width, height=device-height initial-scale=1'> <script src='three.min.js'></script> <script src='OBJLoader.js'></script> <script src='OrbitControls.js'></script> <script src='GeometryUtils.js'></script> <script src='CanvasRenderer.js'></script> <script src='DecalGeometry.js'></script> </head> <body> <label hidden id='x' value='%1$f'></label> <label hidden id='y' value='%2$f'></label> <label hidden id='z' value='%3$f'></label> <label hidden id='alert' value='%4$s'></label> <script src='3d-head-mobile.js'></script> </body> </html> ";
// format the HTML string to include our variables
htmlData = String.format(htmlData,
passedImpactMobile.getImpactDirection().getX(),
passedImpactMobile.getImpactDirection().getY(),
passedImpactMobile.getImpactDirection().getZ(),
passedImpactMobile.getAlert()
);
Lastly, I switched from loadData() to loadDataWithBaseUrl().
wv.loadDataWithBaseURL("file:///android_asset/", htmlData, "text/html", "utf-8", null);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With