I have to develop an e-commerce mobile app. In order to show the products into the app, I have to use a webview that point to a mobile web site. Associate to each product there is the “add to basket” button. Also this button is an element of the mobile site. In the tab bar (and not in the webview) of the mobile app there is the icon of the basket with the number of elements of the basket. How the webview can know that the user has added one or more element to the basket and send to this information to the native mobile app that can update the icon of the basket?
2.1 To receive data from webview ,we can create an interface, which will enable webview to connect the native layer and pass data. From native layer, create a class and replicate the following. While configuring web view, we need to set JavaScript interface as above JSBridge class.
Import the React Native WebView package in App. js . We will create a normal HTML page in WebView and use “script” tags to let the HTML page communicate with the React Native app. In the “script” tag, we are going to call a sendDataToReactNativeApp() function in which we will use a window property called window.
They get their information from a website rather than from the original surroundings. A webview app does not provide the same seamless experience as a native app because users effectively access a web page. Native apps are also significantly faster because they take advantage of the device's processing capability.
A WebView is an embeddable browser that a native application can use to display web content. There are a two sets of words to highlight here: The first set of words is native application (aka app).
Javascript. You bind the WebView to your Android application with the JavascriptInterface. Here are some reference docs: Building Web Apps in WebView
To call Java (or Kotlin) methods in your Javascript code, first create a class and mark the methods you need to use in Javascript with @JavascriptInterface
:
public class WebAppInterface{
Activity _activity;
WebAppInterface(Activity context){
_activity = activity;
}
@JavascriptInterface
public void javaMethodToBeCalledFromJavascript(){
//Your code here
}
}
Note that @JavascriptInterface
methods must be public, otherwise you can't call them from Javascript.
Then you need to create an instance of that class and pass that instance as an argument to the WebView
's addJavascriptInterface
:
WebAppInterface interface = new WebAppInterface(this); //this refers to the current activity
webView.addJavascriptInterface(interface, "Android");
The first argument of addJavascriptInterface
is the object with the methods you want to call from Javascript, and the second argument is what the interface will be called in Javascript. Since in this example the second argument is "Android"
, this will create a Javascript object called Android
with the methods that were marked as @JavascriptInterface
(if you passed "Foo"
as second argument instead, the Javascript object would be called Foo
). So to call the javaMethodToBeCalledFromJavascript()
method in Javascript, do this:
Android.javaMethodToBeCalledFromJavascript();
The basics are as simple as that. However, there are a few things that are useful to know to avoid spending a lot of time debugging.
The most important thing to know is that Java objects called from Javascript are run on a separate thread. This has two major practical consequences.
First, Android will only let you access UI elements from the UI thread. Therfore, the following code will throw a CalledFromWrongThreadException
exception (though it will probably look like it does nothing, I will get to that later):
@JavascriptInterface
public void changeTextOnTextView(String newText){
_activity.someTextView.setText(newText);
}
Android.changeTextOnTextView("Hello World!");
This is because you can only access _activity.someTextView
on _activity
's UI thread, but here you're trying to access it from the Javascript thread. To solve this problem, use the activity's runOnUiThread
method:
@JavascriptInterface
public void changeTextOnTextView(String newText){
_activity.runOnUiThread(() -> {
_activity.someTextView.setText(newText);
});
}
Second, any uncaught Java exceptions that were thrown from the Javascript thread are treated as Javascript errors. This has multiple issues. The first issue is that by default, Android's WebView
doesn't show Javascript errors at all. And even if you solve that (either on the Javascript side with window.onerror
or on the Java side as explained in one of the answers here), you will run into the second issue, which is that the Javascript error will only tell you that a "Java exception was raised during method invocation", without giving you any indication whatsoever about what the Java exception was or where in the Java code it was thrown.
To get around this, you can use runOnUiThread
as explained above, since uncaught Java exceptions thrown on the UI thread will behave as usual, giving you a detailed stack trace in Android Studio. If you want to catch the exception, you can also use try/catch blocks in your Java code (but not in your Javascript code otherwise you won't be able to get any information about the exception).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With