2010-03-25 3 views
16

che sto cercando di fare qualcosa di simile a questo stackoverflow posting. Quello che voglio fare è leggere la definizione di un'attività o servizio dalla scheda SD. Per evitare problemi di autorizzazione manifest, creo una versione di shell di questa attività in .apk, ma provo a sostituirla con un'attività con lo stesso nome che si trova sulla scheda SD in fase di esecuzione. Sfortunatamente, sono in grado di caricare la definizione della classe di attività dalla scheda SD utilizzando DexClassLoader, ma la definizione della classe originale è quella che viene eseguita. Esiste un modo per specificare che la nuova definizione di classe sostituisce quella precedente o qualsiasi suggerimento su come evitare i problemi di autorizzazione manifest senza effettivamente fornire l'attività necessaria nel pacchetto? L'esempio di codice:Android, come utilizzare DexClassLoader per sostituire in modo dinamico un'attività o servizio

ClassLoader cl = new DexClassLoader("/sdcard/mypath/My.apk", 
      getFilesDir().getAbsolutePath(), 
      null, 
      MainActivity.class.getClassLoader()); 

    try { 
     Class<?> c = cl.loadClass("com.android.my.path.to.a.loaded.activity"); 
     Intent i = new Intent(getBaseContext(), c); 
     startActivity(i); 
    } 
    catch (Exception e) { 

intead del lancio del com.android.my.path.to.a.loaded.activity specificato nel /sdcard/mypath/My.apk, si lancia l'attività caricata staticamente nel progetto.

+0

Ho la sensazione che questo non può essere fatto semplicemente a causa di come Android gestisce asset. Se hai chiamato startActivity su una classe in un'altra applicazione, dovrebbe caricare nel thread di quella applicazione non la tua, e quindi essere semplicemente un'alternativa pericolosa agli Intenti di Android. – Tom

risposta

13

all'avvio di un'attività attraverso DexClassLoader sarà molto difficile, perché non è stato installato l'APK, e quindi non c'è nulla per gestire il vostro intento.

si dovrebbe avere la stessa classe di attività nel vostro APK piattaforma e dichiarare in AndroidManifest.xml. Quindi, è necessario modificare il ClassLoader corrente sul DexClassLoader desiderato. Di conseguenza, inizierà l'APK del plugin. (Nota: "APK piattaforma" si riferisce all'app che è già installata nel telefono, mentre "APK plugin" si riferisce al file apk salvato nella scheda SD.)

L'applicazione della piattaforma dovrebbe essere simile a questa:

public static ClassLoader ORIGINAL_LOADER; 
public static ClassLoader CUSTOM_LOADER = null; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    try { 
     Context mBase = new Smith<Context>(this, "mBase").get(); 

     Object mPackageInfo = new Smith<Object>(mBase, "mPackageInfo") 
       .get(); 
     //get Application classLoader 
     Smith<ClassLoader> sClassLoader = new Smith<ClassLoader>(
       mPackageInfo, "mClassLoader"); 
     ClassLoader mClassLoader = sClassLoader.get(); 
     ORIGINAL_LOADER = mClassLoader; 

     MyClassLoader cl = new MyClassLoader(mClassLoader); 
     //chage current classLoader to MyClassLoader 
     sClassLoader.set(cl); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

class MyClassLoader extends ClassLoader { 
    public MyClassLoader(ClassLoader parent) { 
     super(parent); 
    } 

    @Override 
    public Class<?> loadClass(String className) 
      throws ClassNotFoundException { 
     if (CUSTOM_LOADER != null) { 
      try { 
       Class<?> c = CUSTOM_LOADER.loadClass(className); 
       if (c != null) 
        return c; 
      } catch (ClassNotFoundException e) { 
      } 
     } 
     return super.loadClass(className); 
    } 
} 

per ulteriori codice, è possibile visitare https://github.com/Rookery/AndroidDynamicLoader

sto leggendo il codice sorgente di Android al fine di trovare un metodo più elegante per implementare questa funzione. Se hai qualche idea, sentiti libero di contattarmi.

+0

La tua risposta è fantastica +1 per questo. Questo rende la mia giornata. – Krypton

+0

ottima risposta !! il collegamento mi ha aiutato molto. – qiuping345

+1

È meglio che tu spieghi la classe Smith qui. –