I have loaded a webpage using WebView component and added a JavascriptInterface. Please check the code below,
val webview = WebView(this)
setContentView(webview)
webview.settings.javaScriptEnabled = true
webview.loadUrl(HOME_PAGE_URL)
webview.addJavascriptInterface(JavascriptInterface(),”javascript_bridge”)
And when I call the invoke from Javascript using window.javascript_bridge.showToast(“Information Saved”);
private inner class JavascriptInterface
{
#android.webkit.JavascriptInterface
fun showToast(text: String?)
{
Log.d("WEBVIEW", text);
}
}
I am able to call the method from Javascript to Kotlin without any trouble.
But now I want to pass an Object from Javascript to Kotlin like below,
var info = {
message: “Information Saved”,
ID: 123456
}
And when I call the invoke from Javascript using window.javascript_bridge.showToast(info);
I tried to change to the data type to Any, but the value passed from Javascript is null
private inner class JavascriptInterface
{
#android.webkit.JavascriptInterface
fun showToast(text: Any?)
{
Log.d("WEBVIEW", text.toString());
}
}
As far as i know, the javaScript interface methods only accepts primitive types of data as parameters (as discussed on this question).
If you still want to achieve that, you may serialize the object (to JSON format, for instance) in the javaScript and then Deserialize it in Java.
Hope it helps :)
Related
After creating a ‘register’ button in the webview, I want to navigate directly to a specific component when I click ‘func register’ in Kotlin.
Kotlin logic is structured like this.
// Android
inner class JavaScriptInterface
{
#JavascriptInterface
#SuppressWarnings("unused")
fun register(data: String){
navigate(
ridday202208Ev.actionHaydxn2208EventToEventJoinForm()
)
}
}
This is javascript code.
function register() {
}
return (
<button onClick={() => register()}></button>
)
When you click the register function in Javascript code, the webview recognizes the register function and wants to call navigate. I don't know how to deal with it.
If you want JS to be able to execute kotlin code, you need to call addJavascriptInterface(JavaScriptInterface(), "Native") That will create an object in JS called native with all the functions your annotated on that class. Calling one of them will call directly to Kotlin or Java. Remember that you'd call Native.register(), not just register() (the object name is the second parameter to the call above, change it to whatever you want).
Remember that any function you call like this can only take null, String, or Number (int, double, etc) as parameters. You can't pass objects. You can't pass arrays (you kind of can, but you need to pass a Java array, at which point its easier to write in Java). You can't pass functions. You can work around those limitations (except functions) by passing JSON strings and serializing/deserializing them as needed.
I am coding in Unity using C# and developing for WebGL. I need to use browser JavaScript so have written a .jslib from which I call methods in C# using Marshalling.
Is it possible for me to set a JavaScript callback to a C# Action, Func, or Event Handler like so:
// Javascript in .jslib called from C# using static extern
// action being the C# method that I want to call
// On callback I get -> TypeError: action is not a function
SetOnOpen: function (action) {
$jsobj.onopen = function () {
action();
};
},
I've tried each of these, but don't appear to be doing it properly. I know that C++ can call C# functions, but JavaScript must communicate differently somehow.
Attempts:
[DllImport("__Internal")]
private static extern void SetOnOpen(ref OnOpenHandler handler);
[DllImport("__Internal")]
private static extern void SetOnOpen(ref Action action);
[DllImport("__Internal")]
private static extern void SetOnOpen(IntPtr handler);
No matter what I try, I get a TypeError stating that the object that I'm passing over to the JavaScript isn't a function. I've tried:
Using Action and Event Delegates
Using ref, IntPtr, and neither
Anyone know if this is even possible? Like I said, I successfully called a C# method in a C++ .dll before, so figured it would be possible to do so from a .jslib.
From my experience, the only way to make the two communicate is by SendMessage. If you need to carry over multiple parameters, you can attach an array.
I followed the tutorial on this site:
https://facebook.github.io/react-native/docs/embedded-app-android.html
Now I want to have a function in my javascript code like this:
greetingFunction(){
return "HELLO, WORLD";
}
I want to pass the string "HELLO, WORLD" to my java android code and set the screen to display that string.
How can I do this?
You should create a custom module to call custom native methods in Java where you can pass the data you need.
For instance if your custom native module implements the following method:
#ReactMethod
public void myMethod(String message) {
// Here we show a toast message
Toast.makeText(getReactApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
Then you can call that method from JavaScript:
NativeModules.MyCustomModule.myMethod("HELLO WORLD");
Be sure to properly follow all steps described in the doc above to properly register your custom module.
As far as I know we can call C# function from Javascript, that is loaded inside a WebBrowser control, following code shows how I usually do it.
Form1.cs
public partial class Form1 : Form{
private WebBrowser webBrowser1;
public ApplicationWindow(){
InitializeComponent();
WebBrowser webBrowser1 = new WebBrowser();
//some code follows
webBrowser1.ObjectForScripting = new ScriptManager();
this.webBrowser1.Url = new Uri("file:///d:/ui/application.html");
}
}
}
ScriptManager.cs
namespace WindowsFormsApplication10 {
[ComVisible(true)]
public class ScriptManager{
public string GetAllDomains(){
string result=null;
//does something;
return result;
}
}
}
application.html
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
var result = window.external.GetAllDomains();
//it works but this is what puzzles me.
});
</script>
The questions that intrigues me are
why we need ComVisible to be true for class whose object we are going to use as objectForScripting?
How Javascript object window.external has the same methods as in objectForScripting?
How they handle cross language type conversion?
I wonder why no one answered for so long. The answer to all your questions is COM - Component Object Model.
Windows is providing ability (using COM) for classes and functions from one program (exe) to be accessible outside the exe.
So
1) why we need ComVisible to be true for class whose object we are going to use as objectForScripting?
-> This tells windows to make the class and its methods visible to the webbrowser.
2) How Javascript object window.external has the same methods as in objectForScripting?
-> The javascript is calling methods of the class made visible in above answer.
3) How they handle cross language type conversion?
-> COM handles the types internally so methods in one programming language can be called from another programming language.
How can I extract this variable bellow from a website to my android code?
I guess it should work using javascript interface but how do I get it?
<script type="text/javascript">
var Ids = "[4161, 104, 121, 202, 1462]";
</script>
And I can't change the code on the website to a method that returns the value.
Any suggestions?
You can use the javascript: scheme in a webview.loadurl call. It will execute the javascript in the webview page.
From there you can make it call a function in your javascript interface.
webview.loadUrl("javascript:Android.getIds(Ids);");
Android being the name space used to declare your javascript interface.
//Add the javascript interface to your web view
this.addJavascriptInterface(new CustomJavaScriptInterface(webViewContext), "Android");
Beware that javascriptinterface only work with primitive types. So you actually can't pass directly an array. Just use the javascript scheme to loop through your array. I see it is not really an array so you should be fine with just :
public class CustomJavaScriptInterface {
Context mContext;
/** Instantiate the interface and set the context */
CustomJavaScriptInterface(Context c) {
mContext = c;
}
/** retrieve the ids */
public void getIds(final String myIds) {
//Do somethings with the Ids
}
}