CLI на DalvikVM терпит неудачу в JNI lib
Мне нужно запустить версию java-приложения для командной строки на Android (да, я знаю, что это не тривиально).
Я пытаюсь запустить его с помощью 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. Я даже пытался предварительно загрузить liblog с LD_PRELOAD, но ничего не исправил.
Кажется, что что-то неправильно/отличается тем, как dalvikvm устанавливает среду.
Ответы
Ответ 1
Хороший вопрос! Мне пришлось немного разобраться, чтобы понять это.
В libandroid_runtime.so есть множество методов JNI, которые не связаны по умолчанию, когда вы используете команду dalvikvm. К сожалению, вы не можете просто сделать System.loadLibrary( "android_runtime" ), потому что это фактически не связывает все собственные методы.
Однако после некоторого копания выясняется, что существует внутренний, непубличный, не гарантированный класс класса com.android.internal.util.WithFramework, целью которого является загрузка libandroid_runtime.so и привязка всех его JNI.
Чтобы использовать его, просто бросьте com.android.internal.util.WithFramework
перед именем вашего класса в команде dalvikvm, например:
dalvikvm -cp /some/path/classes.dex com.android.internal.util.WithFramework my.example.cls "This is an argument"
(Примечание. Это работает только на устройствах pre-M из-за того, что класс WithFramework
Ответ 2
Для android M, я нашел, что этот метод работает.
Создайте helloworld.sh script, чтобы сопровождать ваш файл 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 "[email protected]"
app_process, похоже, запускает ваш код Java со всеми классами Java и загруженными общими библиотеками, поэтому вы можете использовать оба класса SDK, такие как android. util.log.Log И "секретные" родные классы, например ActivityManagerNative, которые используются в других командах оболочки adb и не присутствуют в SDK.
BTW, для команды java shell, которую я создал, мне пришлось прибегнуть к использованию отражения для вышеуказанных классов, потому что мне кажется, что нет возможности правильно компилировать без клонирования и построения всего AOSP...
Если кто-то знает более простой способ, например, используйте ActivityManagerNative в Java-коде без отражения, я был бы признателен за помощь.