2

I am using NanoHTTPD in an Android application to serve a webpage that is forced to be hosted in a server, so I can't load it directly to the webview.

If I load a single html file, the server and client works.

If I then serve an index.html with includes to javascript files I get an error of Chromium (Crosswalk) per included js file:

06-24 17:27:28.473: I/chromium(16287): [INFO:CONSOLE(1)] "Uncaught SyntaxError: Unexpected end of input", source: http://localhost:8080/interface.js (1)

I thought that the problem was not giving the correct MIME type in these cases but I changed the code in order to do that but it stills failing:

private class WebServer extends NanoHTTPD {
    public static final String MIME_JAVASCRIPT = "text/javascript";
    public static final String MIME_CSS = "text/css";

    public WebServer() {
        super(8080);
    }

    @Override public Response serve(IHTTPSession session) {
        String mime_type = NanoHTTPD.MIME_HTML;
        Method method = session.getMethod();
        String uri = session.getUri();
        System.out.println(method + " '" + uri + "' ");
        String answer = "";
        if(method.toString().equalsIgnoreCase("GET")){
            String path;
            if(uri.equals("/")){
                path="/index.html";
            }else{
                path = uri;
                try{
                    if(path.substring(path.length()-2, path.length()).equalsIgnoreCase("js")){
                        mime_type = MIME_JAVASCRIPT;
                    }else if(path.substring(path.length()-3, path.length()).equalsIgnoreCase("css")){
                        mime_type = MIME_CSS;
                    }
                }catch(Exception e){

                }
            }
            try {
                // Open file from SD Card
                InputStream descriptor = getAssets().open("www/attitude"+path);
                InputStreamReader index = new InputStreamReader(descriptor);
                BufferedReader reader = new BufferedReader(index);
                String line = "";
                while ((line = reader.readLine()) != null) {
                    answer += line;
                }
                reader.close();

            } catch(IOException ioe) {
                Log.w("Httpd", ioe.toString());
            }
        }
        return new NanoHTTPD.Response( Response.Status.OK,mime_type,answer);

    }

}

My javascript files contain directly functions, e.g. init.js:

function init() 
{

setLoadingProgress(1);  
//setLoadingProgress(15);
initScene();

//setLoadingProgress(35);
setLoadingProgress(5);
initReference();

initAngles();
//setLoadingProgress(65);
setLoadingProgress(10);
initIndicators();
//setLoadingProgress(75);
setLoadingProgress(13);
initSun();
//setLoadingProgress(85);
setLoadingProgress(15);
initEarth();
changeView(selected_view);
//setLoadingProgress(100);
setLoadingProgress(18);

}

I would accept also simpler ways to serve a multi-file webpage in the same Android application as the client other than NanoHTTPD.

My only purpose is to skip the restriction of having a server hosting the webpage, but I guess many other people would want to know also how to use this class with complex webpages.

Thanks.

Edit 1: New code with many MIME type detection

    public static final String MIME_JAVASCRIPT = "text/javascript";
    public static final String MIME_CSS = "text/css";
    public static final String MIME_JPEG = "image/jpeg";
    public static final String MIME_PNG = "image/png";
    public static final String MIME_SVG = "image/svg+xml";
    public static final String MIME_JSON = "application/json";

@Override public Response serve(IHTTPSession session) {
        String mime_type = NanoHTTPD.MIME_HTML;
        Method method = session.getMethod();
        String uri = session.getUri();
        System.out.println(method + " '" + uri + "' ");
        InputStream descriptor = null;
        if(method.toString().equalsIgnoreCase("GET")){
            String path;
            if(uri.equals("/")){
                path="/index.html";
            }else{
                path = uri;
                try{
                    if(path.endsWith(".js")){
                        mime_type = MIME_JAVASCRIPT;
                    }else if(path.endsWith(".css")){
                        mime_type = MIME_CSS;
                    }else if(path.endsWith(".html")){
                        mime_type = MIME_HTML;
                    }else if(path.endsWith(".jpeg")){
                        mime_type = MIME_JPEG;
                    }else if(path.endsWith(".png")){
                        mime_type = MIME_PNG;
                    }else if(path.endsWith(".jpg")){
                        mime_type = MIME_JPEG;
                    }else if(path.endsWith(".svg")){
                        mime_type = MIME_SVG;
                    }else if(path.endsWith(".json")){
                        mime_type = MIME_JSON;
                    }
                }catch(Exception e){

                }
            }
            try {
                // Open file from SD Card
                descriptor = getAssets().open("www/orbit"+path);

            } catch(IOException ioe) {
                Log.w("Httpd", ioe.toString());
            }
        }
        return new NanoHTTPD.Response( Response.Status.OK,mime_type,descriptor);

    }

It crashes with this error:

06-25 10:27:03.470: I/System.out(19604): GET '/Cesium/Workers/cesiumWorkerBootstrapper.js' 
06-25 10:27:03.480: I/System.out(19604): GET '/Cesium/Workers/transferTypedArrayTest.js' 
06-25 10:27:03.520: I/System.out(19604): GET '/Cesium/Assets/Textures/moonSmall.jpg' 
06-25 10:27:03.550: I/System.out(19604): GET '/Cesium/Assets/Textures/SkyBox/tycho2t3_80_py.jpg' 
06-25 10:27:03.550: I/System.out(19604): GET '/Cesium/Assets/Textures/SkyBox/tycho2t3_80_my.jpg' 
06-25 10:27:03.550: I/System.out(19604): GET '/Cesium/Assets/Textures/SkyBox/tycho2t3_80_pz.jpg' 
06-25 10:27:03.560: I/System.out(19604): GET '/Cesium/Assets/Textures/SkyBox/tycho2t3_80_mx.jpg' 
06-25 10:27:03.560: I/System.out(19604): GET '/Cesium/Assets/Textures/SkyBox/tycho2t3_80_px.jpg' 
06-25 10:27:03.570: I/System.out(19604): GET '/Cesium/Assets/Textures/SkyBox/tycho2t3_80_mz.jpg' 
06-25 10:27:03.980: A/libc(19604): Fatal signal 11 (SIGSEGV) at 0x00000080 (code=1), thread 19696 (Chrome_InProcGp)

If you open this example with the debug console of the browser opened you will see which is the following GET that is not executed. It is an image/png but some of the fields like the status are different to otherones. Also there are some .js files that are application/javascript and others application/x-javascript

cesiumjs.org/Cesium/Build/HelloWorld.html

XaviGG
  • 171
  • 2
  • 19
  • Have you tried wit browsers on your device? – greenapps Jun 24 '14 at 18:54
  • Do not read the contents of the file into a `String` which you then pass to `Response`. Just open a `FileInputStream` and pass the stream to `Response()`. Check extension with `if (path.endsWith(".js"))`. – greenapps Jun 24 '14 at 19:01
  • Probably the last line of the .js file was not read in. You could add some empty lines to the file to see if that was the culprit. – greenapps Jun 24 '14 at 19:07
  • `to serve a webpage that is forced to be hosted in a server` ? Who/what is forcing that? – greenapps Jun 24 '14 at 19:15
  • By order of comments: 1- I just tried and they don't work either, is a problem of server not client. 2- It works for my example webpage but now the problem is that the webpage that I actualy want to work with has multiple file extensions including pictures, is there a way to know the myme type by file extension or I have to do it manually? 3- thanks but the previous solution already worked. 4- is a complex 3D application and probably they require that, if not they wont force it, I removed the IF clause blocking and it didn't work in local. – XaviGG Jun 25 '14 at 07:29
  • Please do not sum up my comments by 1. 2. And so on. It makes it very difficult for me to understand where you are talking about. Just rephrasing the comments is easier for me. – greenapps Jun 25 '14 at 07:45
  • Sorry, I am going to edit with the new code, including a manual detection of all the used mime types, but it still crashes. With a navigator too. – XaviGG Jun 25 '14 at 07:48
  • Please explain better when you have the error. Is it at the first html file or at retrieving a .js or .css or .jp?? – greenapps Jun 25 '14 at 08:15
  • It is at the end of a lot of different GETs with different extensions, after some .jpg files is when it crashes. – XaviGG Jun 25 '14 at 08:19
  • Please place the errors also in a code block as now they wrap without newlines. – greenapps Jun 25 '14 at 09:08
  • And what is your browser? The new WebView of kitkat? – greenapps Jun 25 '14 at 09:11
  • Crosswalk (chromium based), but with the chrome app also crashes. – XaviGG Jun 25 '14 at 10:19
  • It is very unclear to me where your problem resides. As a test I changed my NanoWebserver app to serve a site from assets and .html, .js, .jpg and .png are served. Not that all goes fluently. Sometimes I have following error `Console: Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png data:text/html,chromewebdata:12`. I checked and see that the .png is there. – greenapps Jun 25 '14 at 10:24
  • Since the webpage is very complex I think it will be better to use another, already implemented, web server. The instructions recomend node.js but it is not possible or easy to install inside the Android application. Do you have any recomendation about embedable webservers? – XaviGG Jun 25 '14 at 11:49
  • Embedable, sorry never did that. But are you referring to `node.js` as a `webserver` ? Even if a `website` is complex then the only task of `nanohttp` is to serve some files. And that is does ok. (my error meanwhile is gone). – greenapps Jun 25 '14 at 12:03
  • The thing is that I didn't implement that webpage (Cesium) and therefore I don't know what kind of PNG they are loading or where is the problem because using my own web page with multiple files also works like in your case. but probably if you try to load CESIUM you will get the same error. I will appreciate you a lot if you have time to download the Cesium files and try to run it. The first page appears because it is a single html, when you click in the helloWorld example then it crashes. – XaviGG Jun 25 '14 at 12:59
  • You are not telling where I can find a Cesium website. You are not telling how many files would have to be downloaded. You realize that I have never heard of Cesium? – greenapps Jun 25 '14 at 13:06
  • Sorry, I wrote the link in the last edit of the question. http://cesiumjs.org/downloads.html There are many files there but you only need to call index.html or helloWorld.html to skip the first page and go directly to the problem. The installation is just copy paste in the assets folder, if you are also loading from assets. Thanks for the effor, really. – XaviGG Jun 25 '14 at 13:15
  • Which file do you want me to download exactly? There are so many zip's. And when will you format the errors in a code block? – greenapps Jun 25 '14 at 13:18
  • http://cesiumjs.org/releases/Cesium-b29.zip is the one I am using. I am going to do it now. – XaviGG Jun 25 '14 at 13:24
  • Ok. Then now tell what I have to put in assets to reproduce the problem. I wil not put 38MB in it! – greenapps Jun 25 '14 at 13:28
  • I have just tried with EmbedHTTP, an alternative to nanoHTTPD and I get the same error in the same line, after loading the last jpg file before the png file. This server doesn't establish the mime types. – XaviGG Jun 25 '14 at 13:29
  • I guess you can delete the folder Documentation, that has almost all the size, but I am not sure, again I didn't implement this application. – XaviGG Jun 25 '14 at 13:31
  • That is irrelevant. You somewhere have an error using files from this download. So you know exactly which files you used I would think. – greenapps Jun 25 '14 at 13:33
  • I didn't put all the lines of the logcat because there are many, I told you what is the last file loaded before error and the next one that should load: /Assets/Textures/SkyBox/tycho2t3_80_mz and the next one that should load I've just realized that is loading it from a URL. – XaviGG Jun 25 '14 at 13:40
  • For which html page is that? Now post the exact sequence of what i should do. Start with some index.html ? or HelloWorld.html ? This png from which html page is it requested? Is that an extern png? If so what is the url? If not which is it? Does it display normally? If the error is on a png then you should put that error certainly in the logcat. – greenapps Jun 25 '14 at 13:45
  • Yes all the files loaded locally have their GET call and are processed correctly. I guess it is then a problem with the files loaded externally with URLs. I have no idea about how to debug this to find the problem... – XaviGG Jun 25 '14 at 13:46
  • Which png is it? I asked that before. – greenapps Jun 25 '14 at 13:55
  • On my pc with firefox requesting HelloWorld.html I have error `Error constructing CesiumWidget. Check if WebGL is enabled. RuntimeError: The browser supports WebGL, but initialization failed.`. On an Android tablet: `An error occurred while rendering. Rendering has stopped. Runtime error: Program failed to link. Link log: Uniforms with the same name but different type/precision`; For both all errors are in Cesium.js – greenapps Jun 25 '14 at 13:57
  • I am debuging in Chrome desktop connected with Android Wifi hotspot. I once got an error at Cesium.js too but now it is always working if I load the webpage in the desktop, but from the webview or Android Chrome it crashes. That means that the server is probably not the problem, but then what could be? – XaviGG Jun 25 '14 at 14:06
  • SIGSEGV invalid memory access (segmentation fault). Sorry I cannot help you if I cannot reproduce your errors. Bye. – greenapps Jun 25 '14 at 14:15
  • did you ever get this to work? i'm attempting the same thing (cesium with nano on android) – spy Mar 20 '16 at 20:50

0 Answers0