kupilot
kupilot

Reputation: 504

Android call javascript function with parameters without webview

I would like to call a javascript function with parameters from Java in an android app, I don't need to load it in webview as I just need to call it and get the results from the JS file which is in the assets folder.

I did it on iOS using JavascriptCore, but I can't find the same functionality in android.

Looked up AndroidJSCore and Rihno but the docs and tutorials are not clear on the subject.

I load the JS file into a String , further I can't go as how to send the parameters and get the results.

Here is how load the file into a string :

    AssetManager assetManager = getAssets();
    String jsFile;

    // To load js file
    InputStream input;
    try {
        input = assetManager.open("authenticate.js");

        int size = input.available();
        byte[] buffer = new byte[size];
        input.read(buffer);
        input.close();

        // byte buffer into a string
        jsFile = new String(buffer);
        resultTV.setText(jsFile);
        Log.d("TAG", jsFile);
    } catch (IOException e) {
        e.printStackTrace();
    }

The parameters to send come from Edittexts.

The javascript function take 2 parameters and return JSON

   function authenticate(uName, pWord)
    {
        var authenString = JSON.stringify(authenJSON);

        return authenString;
    }

Any help is appreciated.

Upvotes: 0

Views: 1040

Answers (1)

nasch
nasch

Reputation: 5498

Here's how I use Rhino in Android:

/**
     *
     * @param javaScriptCode
     * @param functionNameInJavaScriptCode
     * @param params Do not pass an array of primitives!  For example if passing doubles, pass Double[], not double[]
     * @return
     */
    public Map<String,Object> execute(String javaScriptCode, String functionNameInJavaScriptCode, Iterable<String> returnObjectKeys, Object... params){

        Map<String,Object> rtn = null;
        // Every Rhino VM begins with the enter()
        // This Context is not Android's Context
        Context rhino = Context.enter();

        // Turn off optimization to make Rhino Android compatible
        rhino.setOptimizationLevel(-1);
        try {
            final Object[] parameters = new Object[params.length + 1];
            for(int i=0; i < params.length; i++){
                parameters[i] = params[i];
            }
            parameters[parameters.length - 1] = BuildConfig.DEBUG;

            Scriptable scope = rhino.initStandardObjects();

            rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);

            // Get the functionName defined in JavaScriptCode
            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, parameters);
                if(jsResult == null){
                    return null;
                }
                Scriptable s = (Scriptable) jsResult;
                rtn = convert(s, returnObjectKeys);
            }
            else {
                throw new IllegalArgumentException("No function " + functionNameInJavaScriptCode + " found in supplied script");
            }
        } finally {
            Context.exit();
        }

        return rtn;
    }

    private Map<String,Object> convert(Scriptable object, Iterable<String> keys){

        Map<String,Object> rtn = new HashMap<>();
        for(String s : keys){
            if(object.has(s,object)){
                rtn.put(s, object.get(s, object));
            }
        }

        return rtn;
    }

I think I got most of this from SO but can't find the question now.

Upvotes: 1

Related Questions