2009-06-16 11 views
15

Sto sviluppando una libreria per Android che richiede aggiornamenti frequenti da un server centrale. Stavo pensando a quanto sarebbe bello se la mia libreria potesse aggiornarsi da sola - o se potessi semplicemente rilasciare una libreria di bootstrap che scarica la libreria di destinazione quando l'app è installata.Caricamento codice remoto Android

Vedo questa classe in 1.5 denominata "DexClassLoader" ma sembra che ci sia poco prezioso sul Web oltre ai documenti API. Qualcuno ha usato questo con successo per lo scenario che ho descritto?

Inoltre, i termini dell'Android Market consentono una cosa del genere?

risposta

13

Ho utilizzato con successo DexClassLoader. È importante fornire un dexOutputDir effettivamente scrivibile dalla tua app, quindi non/data/dalvik-cache. In caso contrario, il registro mostrerà una o due righe sulla mancata scrittura, seguito da ClassNotFoundException.

cl = new DexClassLoader("/full/path/com.example.apk", 
         getFilesDir().getAbsolutePath(),// /data/data/foo/files 
         null, // native lib path, I haven't used this 
         MyClass.class.getClassLoader()); 
// This doesn't make Class.forName() work, instead I do this: 
Class<?> foo = cl.loadClass("com.example.foo"); 

Per rendere Class.forName() lavoro, si potrebbe provare Thread.setContextClassLoader() (non ho).

+0

Ciao, puoi aggiungere un codice sorgente completo. Sarà un grande aiuto. Grazie in anticipo. –

+1

non funziona per android5 lollipop e sopra a causa di ART: http://stackoverflow.com/questions/27349097/load-dex-file-dynamically-on-android-5-0 – gturedi

3

In effetti ciò che si desidera è supportato e funziona. DexClassLoader non funziona come previsto per me, ma il codice seguente funziona correttamente.

DexFile df = new DexFile(new File("/data/app/my_downloaded_lib.apk")); 
ClassLoader cl = getClassLoader(); 
Class clazz = df.loadClass("com/my/lib/MyClass", cl); 

Circa la questione del mercato, non vedo alcun problema con questo, ma si deve leggere l'EULA per essere sicuri.

+0

Questo funziona, ma rendere un oggetto File è controproducente: DexFile prenderà il percorso e lo aprirà da solo. È possibile utilizzare il costruttore che accetta un percorso String. –

+0

Ciao, forse hai ragione, ma quando ho risposto, questo era l'unico modo in cui funziona. –

2

DexClassLoader è la risposta giusta. Le applicazioni non dovrebbero mai utilizzare direttamente DexFile (è pensato per essere utilizzato dai programmi di caricamento classi).

È possibile utilizzare la memoria esterna (/sdcard) o l'area dati privata dell'app, per il parametro dexOutputDir. La memoria esterna è solitamente più grande, ma se la carta viene espulsa la tua app verrà uccisa e, a causa della mancanza di imposizione dei permessi sui file, è facile per una terza parte sostituire il tuo codice. Ciò può consentire alle app dannose di provocare azioni arbitrarie da parte della tua app. (Se si vuole fare in ogni caso, ottenere il percorso via Environment.getExternalStorageDirectory();. Richiede l'autorizzazione WRITE_EXTERNAL_STORAGE)

L'area di dati app-privato (ottenere il percorso da Context.getFilesDir()) è più sicuro, e ha anche il vantaggio di essere puliti automaticamente se l'app è stata disinstallata. Questo è l'approccio raccomandato.

+4

Vorrei anche pensare che il caricamento del codice off la scheda SD sarebbe alquanto insicura. – CommonsWare

+0

Non scrivere MAI il file dex sul percorso della scheda SD. Questo creerà una vulnerabilità di sicurezza. http://www.symantec.com/connect/blogs/android-class-loading-hijacking – ajma

+0

Aggiornato per risolvere problemi di sicurezza. – fadden