I need to run a command line version of java application on Android(Yeah I know it's not trivial).
I'm trying to start it using Dalvikvm, it actually starts but somewhere later my code fails because it starts using android.util.log and throws this exception.
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)
I tried setting the environment variables, I set the LD_LIBRARY_PATH and the BOOTCLASSPATH variables. I even tried preloading liblog with LD_PRELOAD but nothing fixed that. It seems that something is wrong/different with the way dalvikvm sets the environment.
Good question! I had to dig a bit to figure this out.
There are a slew of JNI methods in libandroid_runtime.so that don't get bound by default, when you're using the dalvikvm command. Unfortunately, you can't just do a System.loadLibrary("android_runtime"), because this doesn't actually bind all the native methods.
However, after some digging, it turns out there is an internal, non-public, not guaranteed to be there class called com.android.internal.util.WithFramework, whose purpose is to load libandroid_runtime.so and bind all its JNI methods.
To use it, just throw com.android.internal.util.WithFramework
in front of your class name, on the dalvikvm command, like so:
dalvikvm -cp /some/path/classes.dex com.android.internal.util.WithFramework my.example.cls "This is an argument"
(Note: This only works on pre-M devices, due to the WithFramework class being removed in M - thanks for the heads up @JaredRummler)