Android 4.2.1, Webview and JavaScript Interface Breaks

Android 4.2.1, WebView and javascript interface breaks

From the Android 4.2 documentation:

Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.

using javascript in android webview

You have to first register the JavaScriptInterface on your webview.
JavaScriptInterFace can be a inner class as shown below. This class will have a function that you can call from html page( via javaScript ) and inside this function you can write code to change activity.

Here is the working solution for you:

public class JavascriptInterfaceActivity extends Activity {
/** Called when the activity is first created. */

WebView wv;

JavaScriptInterface JSInterface;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
wv = (WebView)findViewById(R.id.webView1);

wv.getSettings().setJavaScriptEnabled(true);
// register class containing methods to be exposed to JavaScript

JSInterface = new JavaScriptInterface(this);
wv.addJavascriptInterface(JSInterface, "JSInterface");

wv.loadUrl("file:///android_asset/myPage.html");

}

public class JavaScriptInterface {
Context mContext;

/** Instantiate the interface and set the context */
JavaScriptInterface(Context c) {
mContext = c;
}

@android.webkit.JavascriptInterface
public void changeActivity()
{
Intent i = new Intent(JavascriptInterfaceActivity.this, nextActivity.class);
startActivity(i);
finish();
}
}
}

Here is the html page

<html>
<head>
<script type="text/javascript">
function displaymessage()
{
JSInterface.changeActivity();
}
</script>
</head>

<body>
<form>
<input type="button" value="Click me!" onclick="displaymessage()" />
</form>
</body>
</html>

Hope this helps...

What are valid return values for a Javascript Interface on an Android WebView?

I have not seen a list of valid types (for passing values to Java functions and to return), but only primitives and string seem to work.

You can use JSON (e.g. stringify and parse in Javascript, check various Java options at json.org

Proguard mess Javascript Interface functions when targeting SDK in Android Manifest above 17

I copy my answer from this topic for you: https://stackoverflow.com/a/19994873/1735499

And, if you are using Proguard, remember to add this

-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}

-keepattributes JavascriptInterface
-keep public class com.mypackage.MyClass$MyJavaScriptInterface
-keep public class * implements com.mypackage.MyClass$MyJavaScriptInterface
-keepclassmembers class com.mypackage.MyClass$MyJavaScriptInterface {
<methods>;
}

If it's still not OK, add this

-keepattributes *Annotation*

Note: your MyJavaScriptInterface must be Public class

Ref#: Android Proguard Javascript Interface Fail

Br,

Frank

How to pass non-primitive Object from Java to JS by Android addJavascriptInterface?

This has been one of the most hectic hack for me.

The major problem occurs from Android UI-thread and non-UI-thread bind with addJavascriptInterface

Firstly, my mention:
As far as I know, the only way to pass JAVA object to JS is :
wv.addJavascriptInterface(JavaObject, "JsObject");

is wrong.

In fact, I could pass WebSocketNew= my custom Java object properly to JS as return value of getInstance.

However, the object intended to pass/return to JS must be in scope of Android UI-thread.

If we just do return new WebSocketNew(new URI(url))), it's not found by JS, probably because JS runs in UI-thread, and the origin runs on non-UI-thread of addJavascriptInterface.

As I mentioned earlier, since WebScoket instance is on-demand, so I decided to create Object pool in UI-thread first.
This can be done with HashMap with the requested url String.

Java

    final HashMap<String, WebSocketNew> ws = new HashMap<>();
//runs on non-UI-thread
class WebSocketFactory
{
public WebSocketFactory()
{
}

@JavascriptInterface
public WebSocketNew getInstance(String url)
{
System.out.println("============WebSocketFactory============getInstance " + url);

try
{
ws.put(url, new WebSocketNew(new URI(url)));
ws.get(url).connect();

System.out.println("=====WebSocketNew=====" + url + " " + ws.get(url).getReadyState());

return ws.get(url);
}
catch (Exception e)
{
System.out.println("==========ERROR");
return null;
}
}
}

wv.addJavascriptInterface(new WebSocketFactory(), "factoryJ");

wv.loadUrl("file:///android_asset/Content/app.html");

JS

         window.WebSocket = function(url)
{
console.log('####################creating new WebScoketInstance JS ' + url);

var p = {
url: null
};
p.url = url;

var ws = factoryJ.getInstance(p.url);

var obj = {
send: function(data)
{
console.log('--- send: function(data)----- ws.send1(data);------');
ws.send1(data);
},
//.......
//.......

}
return obj;

};

The JS code is related to topic : JavaScript Event implementation to Closure based Object



Related Topics



Leave a reply



Submit