Hi all,
I want to explain what I do with my project but do not confuse it with sophysticated things, the question here is just one, how to download a file from a WebView, how to handle it so when I press on the link the file should download.
Suppose you have a page with download link, how to download a file?
I've developed an app that permits to manage threejs javascript 3D library and WebGL.
It is a small JS IDE that works on Android.
It can create simple and very complex scenes.
This app have 2 pages in a TabHost:
- Page1 There is a big EditText inside a ScrollView2D, here I can write HTML + Javascript code to execute. There are options to Save and Load HTML files.
- Page2 There is a WebView, when I press the TabHost page2 the HTML file is saved to DirRootInternal, then loaded inside a WebView where the 3D scene is rendered.
To be more precise I recreated the threejs distribution (just folders and files needed mantaining original structure) inside the app folder (in DirRootExternal) where the library search all files like JS imports, textures, models etc.
Initially I had problem to reference files URL pointing to DirRootExternal but then I added this sub
and now I'm able to import any file I need, this worked well and I'm really impressed on what this library can do, I've managed to create some simples and complex scenes, import 3D models like STL, OBJ, 3DS, Collada, 3MF, PLY, apply textures, mipmapping etc.
------
Now I've the opposed problem, that library have Exporters, so I can create objects starting from primitives, boxes, spheres, cylinders etc. manage these with boolean operations like subtract, union, intersect, then export the result as OBJ, STL and other 3D file formats.
My goal is to export objects in STL file format so I can import these inside a 3D printing slicing program like RepetierHost, Cura etc., slice and print with my 3D printer.
To start with, this is a simple Javascript code that add to the scene a simple cube (screenshot attached) and then add to the page 2 links, one to export it as STL in ASCII format and one to export to BINARY format.
The problem here is that by clicking on these links nothing happen, threejs library should save files in the root where HTML file is, but I need to manage a WebView to do downloads. I've tried in a lots of ways but without success, probably I missed something basic.
You can see this yourself online on, by clicking on right-bottom you can see html code.
https://threejs.org/examples/misc_exporter_stl.html
Please, can someone help me figure how to do it in the right way ?
Possibly that works on older and newer Android versions so the app can work on older and newer devices.
Many thanks
I want to explain what I do with my project but do not confuse it with sophysticated things, the question here is just one, how to download a file from a WebView, how to handle it so when I press on the link the file should download.
Suppose you have a page with download link, how to download a file?
I've developed an app that permits to manage threejs javascript 3D library and WebGL.
It is a small JS IDE that works on Android.
It can create simple and very complex scenes.
This app have 2 pages in a TabHost:
- Page1 There is a big EditText inside a ScrollView2D, here I can write HTML + Javascript code to execute. There are options to Save and Load HTML files.
- Page2 There is a WebView, when I press the TabHost page2 the HTML file is saved to DirRootInternal, then loaded inside a WebView where the 3D scene is rendered.
To be more precise I recreated the threejs distribution (just folders and files needed mantaining original structure) inside the app folder (in DirRootExternal) where the library search all files like JS imports, textures, models etc.
Initially I had problem to reference files URL pointing to DirRootExternal but then I added this sub
B4X:
Sub AllowUniversalAccessFromFileURLs(wv As WebView)
Dim jo As JavaObject = wv
Dim settings As JavaObject = jo.RunMethod("getSettings", Null)
Dim r As Reflector
r.Target = settings
r.RunMethod2("setAllowUniversalAccessFromFileURLs", True, "java.lang.boolean")
End Sub
------
Now I've the opposed problem, that library have Exporters, so I can create objects starting from primitives, boxes, spheres, cylinders etc. manage these with boolean operations like subtract, union, intersect, then export the result as OBJ, STL and other 3D file formats.
My goal is to export objects in STL file format so I can import these inside a 3D printing slicing program like RepetierHost, Cura etc., slice and print with my 3D printer.
To start with, this is a simple Javascript code that add to the scene a simple cube (screenshot attached) and then add to the page 2 links, one to export it as STL in ASCII format and one to export to BINARY format.
JavaScript:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ThreeJs</title>
<!-- This is important to get the correct canvas size on mobile devices -->
<meta name='viewport' content='width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'/>
<style>
/* Set margin to 0 and overflow to hidden, to go fullscreen */
body { margin: 0; overflow: hidden; }
</style>
</head>
<body>
<!-- Import three.js Note that this can be changed with minified three.min.js -->
<script src="../build/three.js"></script>
<!-- [STEP 1] INSERT HERE IMPORTS. HERE A TEMPLATE, JUST EDIT AND/OR REMOVE, COMMENT, UNCOMMENT AS NECESSARY -->
<script src="js/controls/OrbitControls.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/libs/dat.gui.js"></script> <!-- minified dat.gui.min.js can be used instead -->
<script src="js/exporters/STLExporter.js"></script> <!-- IMPORT STL EXPORTER -->
<!-- <script src="js/utils/GeometryUtils.js"></script> -->
<!-- <script src="js/utils/BufferGeometryUtils.js"></script> -->
<!-- <script src="js/loaders/STLLoader.js"></script> -->
<script>
///// [STEP 2] INSERT HERE JAVASCRIPT CODE /////
let scene, camera, renderer, exporter, mesh, controls;
const params = {
exportASCII: exportASCII,
exportBinary: exportBinary
};
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 5000 );
camera.position.set( 200, 100, 200 );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
exporter = new THREE.STLExporter(); // HERE THE STL EXPORTER
// Lights
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 200, 0 );
scene.add( hemiLight );
const directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 0, 200, 100 );
scene.add( directionalLight );
// Ground plane
const ground = new THREE.Mesh( new THREE.PlaneGeometry( 500, 500 ), new THREE.MeshPhongMaterial( { color: 0x0000FF, depthWrite: false } ) );
ground.rotation.x = - Math.PI / 2;
scene.add( ground );
const grid = new THREE.GridHelper( 500, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// Export mesh
const geometry = new THREE.BoxGeometry( 50, 50, 50 ); // THE BOX TO BE EXPORTED, 50x50x50 MILLIMETERS
const material = new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
mesh = new THREE.Mesh( geometry, material );
mesh.position.y = 25;
scene.add( mesh );
// WebGL renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio ); // Adjust with DPI
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// OrbitControls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 25, 0 );
controls.update();
// Resize event listener
window.addEventListener( 'resize', onWindowResize );
// GUI
const gui = new dat.GUI();
gui.add( params, 'exportASCII' ).name( 'Export STL (ASCII)' );
gui.add( params, 'exportBinary' ).name( 'Export STL (Binary)' );
gui.open();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
controls.update();
}
function exportASCII() {
Log ("Export ASCII STL file");
const result = exporter.parse( mesh );
saveString( result, 'box.stl' );
}
function exportBinary() {
Log ("Export bynary STL file");
const result = exporter.parse( mesh, { binary: true } );
saveArrayBuffer( result, 'box.stl' );
}
const link = document.createElement( 'a' ); // CREATE DOWNLOAD LINK
link.style.display = 'none';
document.body.appendChild( link );
function save( blob, filename ) {
Log ("Save the file: " + filename);
link.href = URL.createObjectURL( blob );
link.download = filename;
link.click();
}
function saveString( text, filename ) {
Log ("Save string: " + filename);
save( new Blob( [ text ], { type: 'text/plain' } ), filename );
}
function saveArrayBuffer( buffer, filename ) {
Log ("Save array buffer: " + filename);
save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
}
function Log (text) {
console.log(text);
}
//////////// END OF JAVASCRIPT CODE ////////////
</script>
</body>
</html>
You can see this yourself online on, by clicking on right-bottom you can see html code.
https://threejs.org/examples/misc_exporter_stl.html
Please, can someone help me figure how to do it in the right way ?
Possibly that works on older and newer Android versions so the app can work on older and newer devices.
Many thanks
Attachments
Last edited: