2012-10-21 9 views
7

Ho bisogno di eseguire una versione da riga di comando dell'applicazione java su Android (Sì, lo so che non è banale).CLI su DalvikVM non riesce su JNI lib

Sto provando ad avviarlo usando Dalvikvm, in realtà inizia ma da qualche parte più tardi il mio codice fallisce perché inizia a utilizzare android.util.log e lancia questa eccezione.

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) 

ho provato a installare le variabili di ambiente, ho impostato il LD_LIBRARY_PATH e le variabili bootclasspath. Ho anche provato il precaricamento del liblog con LD_PRELOAD ma nulla ha risolto il problema. Sembra che qualcosa sia sbagliato/diverso dal modo in cui dalvikvm imposta l'ambiente.

+0

Qual è il comando che hai usato per avviarlo ... iniziare da lì. –

risposta

11

Buona domanda! Ho dovuto scavare un po 'per capirlo.

Esistono numerosi metodi JNI in libandroid_runtime.so che non vengono associati per impostazione predefinita quando si utilizza il comando dalvikvm. Sfortunatamente, non puoi semplicemente fare un System.loadLibrary ("android_runtime"), perché questo in realtà non lega tutti i metodi nativi.

Tuttavia, dopo alcuni scavi, risulta che esiste una classe interna, non pubblica, non garantita, denominata com.android.internal.util.WithFramework, il cui scopo è caricare libandroid_runtime.so e associare tutto i suoi metodi JNI.

Per usarlo, basta gettare com.android.internal.util.WithFramework davanti al nome della classe, sul comando dalvikvm, in questo modo:

dalvikvm -cp /some/path/classes.dex com.android.internal.util.WithFramework my.example.cls "This is an argument" 

(Nota: Questo funziona solo su dispositivi pre-M, a causa della classe WithFramework essendo removed in M - grazie per l'heads up @JaredRummler)

+0

Credo di essere stato abbastanza fortunato da avere WithFramework sul mio dispositivo e funziona. – ApriOri

+0

Sì, è quasi certamente presente su tutti i dispositivi. Ma non è garantito che ci sia, e potrebbe andare via/cambiare in futuro. (come qualsiasi apice non pubblico) – JesusFreke

+0

'System.load ("/system/lib/libandroid_runtime.so ");'? –

3

Per Android M, ho trovato questo metodo per funzionare.
creare uno script helloworld.sh per accompagnare il vostro barattolo file \ 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 sembra iniziare il vostro codice Java con tutte le classi Java e librerie condivise caricati, in modo da poter utilizzare entrambe le classi SDK come android.util .log.Log E classi native "segrete", ad es ActivityManagerNative, che vengono utilizzati in altri comandi della shell adb e non sono presenti nell'SDK.
BTW, per il comando java shell che ho creato, ho dovuto ricorrere all'utilizzo del reflection per le classi precedenti, perché mi sembra che non ci sia modo di compilare correttamente senza clonare e costruire l'intero AOSP ...
Se qualcuno conosce un modo più semplice per es utilizzare ActivityManagerNative nel codice java senza riflessione, apprezzerei l'aiuto.

+0

Per rispondere alla mia domanda: puoi creare implementazioni di stub per le classi e i metodi che sai che userete e compilare contro di loro – Tolstoyevsky

+0

app_process richiede l'accesso di root al dispositivo mentre dalvikvm non è – francogrex

+0

OK? Visto che molti utenti eseguiranno questo usando la shell adb, non mi sembra un grosso problema. Se è un problema per te, puoi sicuramente provare a eseguire direttamente dalvikvm. Se si dispone di un modo semplice per farlo, si prega di postarlo qui. – Tolstoyevsky