如果它是开源的,您可以轻松地在源代码中插入一些日志并重新编译。一些代码覆盖率工具允许您记录执行的方法,但我不确定参数(例如EMMA 覆盖率)。
如果它是闭源的,那么你可以用 Xposed 来做,但它有一些挑战。Xposed 允许你挂钩 Java 方法,如果它是开源的,你可以查找你想要拦截的特定方法并打印它们的参数。如果它是闭源的,您可以随时通过使用apktool反编译应用程序来检查方法名称。
查看有关如何注册钩子的Xposed 教程。假设您创建了扩展 XC_MethodHook 的类,以下方法应该可以解决原始参数的问题:
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String threadname = Thread.currentThread().getName();
String d = _dateFormat.format(new Date());
Class<?> cls = param.this.getClass();
//Extend XC_MethodHook to receive the mthName in the constructor
//and store it as a static field.
Log.v("MethodInvocation", "[A][" + d + "]"
+ "[" + cls.getName() + "."
+ mthName
+ "(" + args(param) + ")" + " = " + result(param)
+ "]" + " [" + threadname + "]");
}
public boolean shouldPrintContent(Object o) {
if (o.getClass().isPrimitive()
|| o.getClass().getName().contains("java.lang"))
return true;
return false;
}
public String args(MethodHookParam param) {
String args = "";
int counter = 0;
if (param != null) {
for (Object o : param.args) {
if (counter > 0)
args += ",";
// argument can be null
if (o == null) {
args += "null";
} else { // if it is an object lets print its type and content.
args += printclean(o.getClass().getName());
if (shouldPrintContent(o)) {
args += ":" + printclean(o.toString());
} else
args += ":nonPrimitiveOrJavaLang";
}
counter++;
}
}
return args;
}
//avoid identation chars in strings
public String printclean(String str) {
char[] res = str.toCharArray();
for (int i = 0; i < str.length(); i++) {
if (res[i] == '\n' || res[i] == '\r' || res[i] == '\t'
|| res[i] == '[' || res[i] == ']') {
res[i] = '*';
}
}
return String.valueOf(res);
}
public String result(MethodHookParam param) {
String res = "";
Object retobj = param.getResult();
if (retobj == null) {
res += "null";
} else {
res += printclean(retobj.getClass().getName());
if (shouldPrintContent(retobj)) {
res += printclean(retobj.toString());
} else
res += "(nonPrimitiveOrJavaLang)";
}
return res;
}
请注意,打印任何对象都不是小事。在这里,我只打印了已知类型,如原语或其他 java.lang 对象。更复杂的对象(包括集合)你可以尝试使用 Gson 来表示它们,但这也有限制(例如不能经常处理引用循环)。
最后,要小心你挂钩的方法,因为经常调用的挂钩和日志记录方法会影响应用程序的性能。
祝你好运!