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
existsThat 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 clientWhen I call
view.loadUrl("javascript:console.log(test)
I gettest is not defined