Skip to content

Instantly share code, notes, and snippets.

@2lazy2debug
Last active September 12, 2019 17:30
Show Gist options
  • Save 2lazy2debug/789b5c70ae95cacbd27e55b8f6a10735 to your computer and use it in GitHub Desktop.
Save 2lazy2debug/789b5c70ae95cacbd27e55b8f6a10735 to your computer and use it in GitHub Desktop.
Use ScriptEngineManager to load JavaScript on Android
/*
* Add the following to your build.gradle file :
* implementation 'io.apisense:rhino-android:1.0'
*/
package vergecurrency.vergewallet.helpers;
import android.content.Context;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.NativeObject;
import java.io.InputStream;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import vergecurrency.vergewallet.Constants;
import vergecurrency.vergewallet.helpers.utils.FileUtils;
public class SJCL {
private ScriptEngine engine;
private org.mozilla.javascript.Context jsContext;
public SJCL(Context c) {
init(c);
}
public void init(Context c) {
ScriptEngineManager manager = new ScriptEngineManager();
engine = manager.getEngineByName("rhino");
try {
//this is just my way to access a script, which is SJCL for the purpose
InputStream is = c.getAssets().open(Constants.SJCL_FILE_PATH);
String sjcl = FileUtils.convertStreamToString(is);
// read script file
engine.eval(sjcl);
} catch (Exception e) {
e.printStackTrace();
//don't be like me kids, do proper error management
System.err.println("Can't do something..................................................");
}
}
/**
* This method might look confusing. So here a detailed explanation.
* The SJCL Library has nested objects, sorry if it's not the correct phrasing, I'm no JS expert.
* So, while in JS (and in Swift too) you could call the "toBits" method by just typing "sjcl.codec.base64.toBits",
* well, you can't in Java because we are Java devs and don't give a flying fuck about doing things easily (Just Kidding!)
* So, we have to use the ScriptEngine to get the SJCL object as a NativeObject, which is basically a key-value pair
* that will have as a key the object name and as values the sub-objects/methods.
* So I had to cast the returned objects as NativeObjects and retrieve the correct keys according to the file structure.
*
* The result will come as a native array whereas the 0 index contains the result, which is turned to a String.
*
* @param encryptingKey the key in a string form
* @return the string represantation of a bit array.
*/
public String base64ToBits(String encryptingKey) {
try {
Invocable invocable = (Invocable) engine;
Object o = ((NativeObject) ((NativeObject) engine.get("sjcl")).get("codec")).get("base64");
NativeArray o2 = (NativeArray) invocable.invokeMethod(o, "toBits", encryptingKey);
String result = o2.get(0).toString();
return result;
} catch (ScriptException | NoSuchMethodException e) {
e.printStackTrace();
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment