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
Adding a Background Video with React
D3 Bar Chart Not Showing First Element in Array
How to Reasonably Animate Font Awesome Lock Icons
Get Pixelcolor of CSS Background Image
Modify Pseudo Select :After in JavaScript
Highlight Active Menu Item on Scroll
Change Image Onclick for a Set Amount of Time
Change the Color of a Text in Div Using Jquery Contains
How to Activate a CSS3 (Webkit) Animation Using JavaScript
How to Replay a CSS3 Animation in Reactjs
CSS in My JavaScript Widget Colliding with Target Page CSS
JavaScript .Replace Alternative
Detect Support for Background-Size: Cover
Find Next Cell Contained in Sibling Row with Queryselector
Onclick JavaScript Function Working Only on Second Click