Android webview doesn't execute javascript from script src

3.1k views Asked by At

The Problem

The webview doesn't actually execute the scripts loaded through src from a remote location

Checked and double checked

  • The permission: <uses-permission android:name="android.permission.INTERNET" />

  • That the file http://localhost/android/test.js exists

  • That it called view.getSettings().setJavaScriptEnabled(true); before loading an URL

The code

Given a WebView view and a Context context

Building a document

It will need cookies so need to dynamically build it. file:// urls don't allow for cookies. Either way, this 'should' work just fine.

String html =
        "<html>\n" +
        "<head>\n" +
        "</head>\n" +
        "<body>\n" +
        "<script src=\"http://localhost/android/test.js\"  type=\"text/javascript\"></script>\n" +
        "</body>\n" +
        "</html>";
String mime = "text/html";
String encoding = "utf-8";

Cookies enabled

Simple functions to make sure the device retains cookies.

CookieSyncManager.createInstance(context);
CookieSyncManager.getInstance().sync();

Creating a chrome client for logging

Logging all messages [twice] and when the page is done loading execute a function. This actually works well. Adding more [remote] script tags delays the execution.

WebChromeClient client = new WebChromeClient ( ) {
        @Override
        public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
            Log.e( "JSINTERFACE", consoleMessage.message() );
            return super.onConsoleMessage(consoleMessage);
        }

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
            loadingFinished = ( newProgress == 100 );
            Log.d( "JSINTERFACE", "Progress is:" + newProgress );
            if ( loadingFinished ) {
                Log.i( "JSINTERFACE", "Finished loading webclient" );
                execute();
            }
        }

    };

Loading the view

Attach the chrome client, enable javascript, add the interface and start loading!

view.setWebChromeClient( client );
view.getSettings().setJavaScriptEnabled(true);
view.addJavascriptInterface( new JSInterface(), "bridge" );
view.loadDataWithBaseURL( "http://localhost/android/", html, mime, encoding, null );

The Interface

The interface looks as follows

public class JSInterface{

    @JavascriptInterface
    public void result( int success, String message ) {
        Log.i( "JSINTERFACE", message );
        // TODO handler
    }
}

I can actually test javascript AND the interface by calling

view.loadUrl("javascript:bridge.result( 0, 'TESTING INTERFACE' );");

As long as this is postponed until after loading has completed (for example in the execute function this works fine. And the message is logged.

Inside the test.js script

A very simple script

console.log( 'test loaded' );
var test = function() { console.log( 'test' ); bridge.result( 1, 'res' ); }

Why doesn't it work?

  • I don't see the test loaded log, should be captured by the client

  • When I call view.loadUrl("javascript:console.log(test) I get test is not defined

0

There are 0 answers