Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you implement Three.js code into an Android mobile application?

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
like image 561
tommyboy Avatar asked Dec 11 '25 18:12

tommyboy


1 Answers

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);
like image 160
tommyboy Avatar answered Dec 14 '25 09:12

tommyboy