3

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
tommyboy
  • 756
  • 6
  • 11

2 Answers2

2

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);
tommyboy
  • 756
  • 6
  • 11
0

You are not using WebViewClient correctly. Either remove this line:

wv.setWebViewClient(new WebViewClient());

Or create a WebViewClient children class and override shouldOverrideUrlLoading with something like this:

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    view.loadUrl(url);
    return true;
}
Chisko
  • 3,092
  • 6
  • 27
  • 45
  • I edited my code above to show how I am just trying to send in a String. I can't do it by file. – tommyboy Mar 06 '18 at 21:02
  • @tommyboy you removed the client and still doesn't load? What does LogCat show? – Chisko Mar 06 '18 at 21:49
  • added logcat info above – tommyboy Mar 06 '18 at 22:19
  • @tommyboy yeah that doesn't say anything helpful. Could you update your question and show your layout and more logic code of your activity/fragment? And try searching for something useful on LogCat – Chisko Mar 06 '18 at 23:25