| 28 | import java.util.HashMap; |
| 29 | |
| 30 | public class JsCallJava { |
| 31 | private final static String TAG = "JsCallJava"; |
| 32 | private final static String RETURN_RESULT_FORMAT = "{\"CODE\": %d, \"result\": %s}"; |
| 33 | private static final String MSG_PROMPT_HEADER = "AgentWeb:"; |
| 34 | private static final String KEY_OBJ = "obj"; |
| 35 | private static final String KEY_METHOD = "method"; |
| 36 | private static final String KEY_TYPES = "types"; |
| 37 | private static final String KEY_ARGS = "args"; |
| 38 | private static final String[] IGNORE_UNSAFE_METHODS = {"getClass", "hashCode", "notify", "notifyAll", "equals", "toString", "wait"}; |
| 39 | private HashMap<String, Method> mMethodsMap; |
| 40 | private Object mInterfaceObj; |
| 41 | private String mInterfacedName; |
| 42 | private String mPreloadInterfaceJs; |
| 43 | |
| 44 | public JsCallJava(Object interfaceObj, String interfaceName) { |
| 45 | try { |
| 46 | if (TextUtils.isEmpty(interfaceName)) { |
| 47 | throw new Exception("injected name can not be null"); |
| 48 | } |
| 49 | mInterfaceObj = interfaceObj; |
| 50 | mInterfacedName = interfaceName; |
| 51 | mMethodsMap = new HashMap<String, Method>(); |
| 52 | // getMethods会获得所有继承与非继承的方法 |
| 53 | Method[] methods = mInterfaceObj.getClass().getMethods(); |
| 54 | // 拼接的js脚本可参照备份文件:./library/doc/injected.js |
| 55 | StringBuilder sb = new StringBuilder("javascript:(function(b){console.log(\""); |
| 56 | sb.append(mInterfacedName); |
| 57 | sb.append(" init begin\");var a={queue:[],callback:function(){var d=Array.prototype.slice.call(arguments,0);var c=d.shift();var e=d.shift();this.queue[c].apply(this,d);if(!e){delete this.queue[c]}}};"); |
| 58 | for (Method method : methods) { |
| 59 | Log.i("Info","method:"+method); |
| 60 | String sign; |
| 61 | if ((sign = genJavaMethodSign(method)) == null) { |
| 62 | continue; |
| 63 | } |
| 64 | mMethodsMap.put(sign, method); |
| 65 | sb.append(String.format("a.%s=", method.getName())); |
| 66 | } |
| 67 | sb.append("function(){var f=Array.prototype.slice.call(arguments,0);if(f.length<1){throw\""); |
| 68 | sb.append(mInterfacedName); |
| 69 | sb.append(" call result, message:miss method name\"}var e=[];for(var h=1;h<f.length;h++){var c=f[h];var j=typeof c;e[e.length]=j;if(j==\"function\"){var d=a.queue.length;a.queue[d]=c;f[h]=d}}var k = new Date().getTime();var l = f.shift();var m=prompt('"); |
| 70 | sb.append(MSG_PROMPT_HEADER); |
| 71 | sb.append("'+JSON.stringify("); |
| 72 | sb.append(promptMsgFormat("'" + mInterfacedName + "'", "l", "e", "f")); |
| 73 | sb.append("));console.log(\"invoke \"+l+\", time: \"+(new Date().getTime()-k));var g=JSON.parse(m);if(g.CODE!=200){throw\""); |
| 74 | sb.append(mInterfacedName); |
| 75 | sb.append(" call result, CODE:\"+g.CODE+\", message:\"+g.result}return g.result};Object.getOwnPropertyNames(a).forEach(function(d){var c=a[d];if(typeof c===\"function\"&&d!==\"callback\"){a[d]=function(){return c.apply(a,[d].concat(Array.prototype.slice.call(arguments,0)))}}});b."); |
| 76 | sb.append(mInterfacedName); |
| 77 | sb.append("=a;console.log(\""); |
| 78 | sb.append(mInterfacedName); |
| 79 | sb.append(" init end\")})(window)"); |
| 80 | mPreloadInterfaceJs = sb.toString(); |
| 81 | sb.setLength(0); |
| 82 | } catch (Exception e) { |
| 83 | if (LogUtils.isDebug()) { |
| 84 | Log.e(TAG, "init js result:" + e.getMessage()); |
| 85 | } |
| 86 | } |
| 87 | } |
nothing calls this directly
no outgoing calls
no test coverage detected