Pytanie Android, jak używać DexClassLoader do dynamicznego zastępowania działania lub usługi


Próbuję zrobić coś podobnego do tego wysyłanie stackoverflow. Chcę tylko odczytać definicję działania lub usługi z karty SD. Aby uniknąć jawnych problemów z uprawnieniami, tworzę wersję powłoki tego działania w pliku .apk, ale staram się zastąpić ją działaniem o tej samej nazwie, które znajduje się na karcie SD w czasie wykonywania. Niestety, jestem w stanie załadować definicję klasy aktywności z karty SD za pomocą DexClassLoader, ale oryginalna definicja klasy jest tą, która jest wykonywana. Czy istnieje sposób na określenie, czy nowa definicja klasy zastępuje starą, czy też sugestie dotyczące unikania jawnych problemów z uprawnieniami, bez faktycznego dostarczania wymaganej aktywności w pakiecie? Przykład kodu:

    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 of launch the com.android.my.path.to.a.loaded.activity określone w /sdcard/mypath/My.apk, uruchamia aktywność statycznie załadowaną do projektu.


16
2018-03-25 22:04


pochodzenie


Mam wrażenie, że nie można tego zrobić po prostu z powodu sposobu, w jaki Android obsługuje zasoby. Gdybyś wywołał startActivity na klasie w innej aplikacji, musiałby wczytać wątek tej aplikacji nie swoją, a tym samym byłby po prostu niebezpieczną alternatywą dla Intents Androida. - Tom


Odpowiedzi:


Rozpoczęcie działania przez DexClassLoader będzie bardzo trudne, ponieważ nie zainstalowałeś pakietu APK, a więc nie masz nic do obsłużenia swojego zamiaru.

Powinieneś mieć tę samą klasę aktywności w pakiecie APK platformy i zadeklarować ją w AndroidManifest.xml. Następnie powinieneś zmienić aktualną klasę ClassLoader na żądaną DexClassLoader. W rezultacie rozpocznie się pakiet APK wtyczki. (Uwaga: "APK platformy" odnosi się do aplikacji, która jest już zainstalowana w telefonie, a "wtyczka APK" odnosi się do pliku APK zapisanego na karcie SD.)

Aplikacja platformy powinna wyglądać mniej więcej tak:

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

Aby uzyskać więcej kodu, możesz odwiedzić https://github.com/Rookery/AndroidDynamicLoader

Czytam kod źródłowy Androida, aby znaleźć bardziej elegancką metodę implementacji tej funkcji. Jeśli masz jakiś pomysł, skontaktuj się ze mną.


13
2018-04-08 03:21



Twoja odpowiedź jest wspaniała +1 za to. To sprawia, że ​​mój dzień. - Krypton
świetna odpowiedź !! ten link bardzo mi pomógł. - qiuping345
Lepiej, jeśli wytłumaczysz tutaj klasę Smith. - k__gc_im_o_
Smith jest klasą pomocniczą do refleksji. - Sim Sun
@Simpleton Znalazłem lepsze rozwiązanie i rozwiązanie, które podałeś. Przeszedłem przez projekt github i próbowałem siebie, ale pokazuje on aktywność pakietu, a nie aktywność w apk - Sai Krishna