2010-03-25 2 views
16

Я пытаюсь сделать что-то похожее на это stackoverflow posting. Что я хочу сделать, так это прочитать определение активности или услуги с SD-карты. Чтобы избежать явных проблем с разрешениями, я создаю оболочную версию этого действия в .apk, но пытаюсь заменить его активностью с тем же именем, который находится на SD-карте во время выполнения. К сожалению, я могу загрузить определение класса активности с SD-карты с помощью DexClassLoader, но исходное определение класса - это тот, который выполняется. Есть ли способ указать, что новое определение класса заменяет старый, или какие-либо предложения по устранению проблем с разрешениями манифеста без фактического предоставления необходимой активности в пакете? Пример кода:Android, как использовать DexClassLoader для динамической замены активности или службы

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 о запуске com.android.my.path.to.a.loaded.activity указанных в /sdcard/mypath/My.apk, он запускает деятельность статический загруженную в проект.

+0

У меня такое чувство, что это невозможно сделать просто из-за того, как Android обрабатывает активы. Если вы вызвали startActivity для класса в другом приложении, ему пришлось бы загружать в поток этого приложения не свой собственный и, следовательно, быть просто опасной альтернативой намерениям Android. – Tom

ответ

13

Запуск Activity через DexClassLoader будет очень сложным, потому что вы не установили APK, и поэтому вам нечего справиться с вашим намерением.

Вы должны иметь тот же класс активности на своей платформе APK и объявить его в AndroidManifest.xml. Затем вы должны изменить текущий ClassLoader на желаемый DexClassLoader. В результате он запустит ваш плагин APK. (Примечание: «APK платформы» относится к приложению, которое уже установлено в телефоне, тогда как «плагин APK» относится к файлу apk, сохраненному на вашей SD-карте.)

Приложение платформы должно выглядеть примерно так:

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); 
    } 
} 

для более коды, вы можете посетить https://github.com/Rookery/AndroidDynamicLoader

Я читаю исходный код Android, чтобы найти более изящный способ реализации этой функции. Если у вас есть идеи, не стесняйтесь обращаться ко мне.

+0

Ваш ответ потрясающий +1 для него. Это делает мой день. – Krypton

+0

отличный ответ !! связь мне очень помогла. – qiuping345

+1

Лучше, если вы объясните класс Смита здесь. –