我需要在Android上运行java应用程序的命令行版本(是的,我知道这不是一件小事)。
我正在尝试使用Dalvikvm启动它,它实际上已启动,但稍后我的代码失败,因为它开始使用android.util.log并抛出此异常。
java.lang.UnsatisfiedLinkError: println_native
at android.util.Log.println_native(Native Method)
at android.util.Log.i(Log.java:159)
at org.slf4j.impl.AndroidLogger.info(AndroidLogger.java:151)
at org.gihon.client.TunnelingClient.<init>(TunnelingClient.java:62)
at org.gihon.client.CLI.main(CLI.java:95)
at dalvik.system.NativeStart.main(Native Method)
我尝试设置环境变量,我设置了LD_LIBRARY_PATH和BOOTCLASSPATH变量。我甚至尝试用LD_PRELOAD预加载liblog但没有修复它。 似乎dalvikvm设置环境的方式有些不对劲/不同。
答案 0 :(得分:12)
好问题!我不得不挖掘一下来解决这个问题。
当你使用dalvikvm命令时,libandroid_runtime.so中有很多JNI方法在默认情况下不会被绑定。不幸的是,你不能只做一个System.loadLibrary(“android_runtime”),因为这实际上并没有绑定所有的本机方法。
然而,经过一番挖掘后,事实证明有一个内部的,非公开的,不能保证有一个名为com.android.internal.util.WithFramework的类,其目的是加载libandroid_runtime.so并绑定其所有的JNI方法。
要使用它,只需在dalvikvm命令上将com.android.internal.util.WithFramework
放在类名前面,如下所示:
dalvikvm -cp /some/path/classes.dex com.android.internal.util.WithFramework my.example.cls "This is an argument"
(注意:这仅适用于pre-M设备,因为WithFramework类为removed in M - 感谢抬头@JaredRummler)
答案 1 :(得分:5)
对于Android M,我发现这种方法有效 创建一个helloworld.sh脚本以附带jar \ zip文件:
#!/system/bin/sh
# Copied by example from am command
base=/system
export CLASSPATH=/path/to/your/jar/HelloWorld.jar
exec app_process $base/bin HelloWorldMainClass "$@"
app_process似乎启动了所有java类和加载的共享库的java代码,因此您可以使用两个SDK类,如android.util.log.Log AND&#34; secret&#34;本机类,例如ActivityManagerNative,用于其他adb shell命令,并且不存在于SDK中。
顺便说一句,对于我创建的java shell命令,我不得不求助于上面的类使用反射,因为在我看来,没有克隆和构建整个AOSP就无法正确编译...
如果有人知道更简单的方法,例如在没有反射的java代码中使用ActivityManagerNative,我很感激帮助。