Kotlin Call Javascript function in Android without webView

6k views Asked by At

Is there any way we can call JS function from Kotlin without having WebView in Android?

Let's say as mentioned below I have one JS function helloJS() in test.js file,

test.js:-

function helloJS(){
    return "Hello from JS"
}

And now I want to call this function from Kotlin file like

TestClass.kt:-

class TestHello{

    fun getHelloFromJS(){
        val name = test.helloJS()
    }
}

Till now I am using Webview and loading JS file into that and getting result as call back

But, I read that Kotlin is interoperable with JS like Java

So I am curious to know if there is any way we can use that on Android without having webView

4

There are 4 answers

2
Niranj Patel On

This is not possible straight forward but I found one library Execute JavaScript in Android without WebView for achieve this.

Read that blog carefully and follow below step.

Keep your JavaScript file (test.js) in assets folder in android project.

I have converted that code into Kotlin.

CallJavaScript.jks

import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import java.io.InputStreamReader


object CallJavaScript {

    fun callFunction(mContext: android.content.Context): Any? {

        var jsResult: Any? = null

        val params = arrayOf<Any>("")

        // Every Rhino VM begins with the enter()
        // This Context is not Android's Context
        val rhino = Context.enter()

        // Turn off optimization to make Rhino Android compatible
        rhino.optimizationLevel = -1
        try {
            val scope = rhino.initStandardObjects()

            // Note the forth argument is 1, which means the JavaScript source has
            // been compressed to only one line using something like YUI

            val assetManager = mContext.assets
            try {
                val input = assetManager.open("test.js")
                val targetReader = InputStreamReader(input)
                rhino.evaluateReader(scope, targetReader, "JavaScript", 1, null)
            } catch (e: Exception) {
                e.printStackTrace()
            }


            // Get the functionName defined in JavaScriptCode
            val obj = scope.get("helloJS", scope)

            if (obj is Function) {

                // Call the function with params
                jsResult = obj.call(rhino, scope, scope, params)
                // Parse the jsResult object to a String
                val result = Context.toString(jsResult)
            }
        } finally {
            Context.exit()
        }
        return jsResult
    }
}

Add this line to build.gradle:

implementation 'org.mozilla:rhino:1.7R4'

In your assets folder, create a file called test.js:

function helloJS()
{
    return "Hello from JS";
}

Now simply call above function from Activity.

 Log.e("JS : ", CallJavaScript.callFunction(this).toString());

Output :

E/JSĀ :: Hello from JS
0
GaetanZ On

It's not possible. You must not confuse the language with the platform.

Kotlin is interoperable with JS like Java

means Kotlin/JS can use and be used in a Javascript platform (Node.js or browsers). The Kotlin code compiled (transpiled) into js is able to call other js files. And external Js code can call the js code build from Kotlin. This is the interoperability with JS.

There is no interoperability between Kotlin/JS and Kotlin/JVM.

enter image description here

0
Fung On

Kt looks like JS, but it is not. It will be compiled for Android runtime, not for the java script engine.

JS code require a JS runtime, but it is not in Android Runtime.

i.e. you cannot run JS directly in Java / Kt code for Android.

0
Lucem On

Am not a pro in Kotlin but Java is a pie for me. Anything you can implement in Java can be implemented in Kotlin and To execute Javascript code, I use rhino which does the job pretty easier than using the webview Implement it:

try {
   Scriptable scope = rhino.initStandardObjects();
   rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
   Object obj = scope.get(functionNameInJavaScriptCode, scope);

   if (obj instanceof Function) {

       Function jsFunction = (Function) obj;
       // Call the function with params
       Object jsResult = jsFunction.call(rhino, scope, scope, params);
       // Parse the jsResult object to a String
       String result = Context.toString(jsResult);
   }

}finally {
   Context.exit();
}