Как использовать InMemoryDexClassLoader? - PullRequest
0 голосов
/ 21 апреля 2020

Я хотел бы иметь возможность запускать код, не установленный как часть приложения в памяти. Я предположил, что InMemoryDexClassLoader был создан именно для этого, поэтому я попытался использовать его для выполнения метода в том же приложении (даже в том же классе), но из памяти. Для этого я загружаю сам APK в буфер и передаю этот буфер InMemoryDexClassLoader. Тем не менее, я получаю ClassNotFoundException.

public class Test {
    public void loadSelf(Context c) {
        try {
            FileInputStream fis = new FileInputStream(c.getApplicationInfo().publicSourceDir);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int bytesRead;
            byte[] buffer = new byte[1024];
            while ((bytesRead = fis.read(buffer, 0, buffer.length)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            baos.flush();
            byte[] dex = baos.toByteArray();
            ByteBuffer bb = ByteBuffer.allocate(dex.length);
            bb.put(dex);
            bb.position(0);
            ClassLoader loader = new InMemoryDexClassLoader(bb, null);
            Class thisClass = loader.loadClass(this.getClass().getName()); //ClassNotFoundException
            Method method = thisClass.getMethod("sayHi", Context.class);
            method.invoke(thisClass.newInstance(), c);
            bb.clear();
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sayHi(Context c) {
        Toast.makeText(c, "Hi!", Toast.LENGTH_LONG).show();
    }
}

То же самое с DexClassLoader работает отлично! Кто-нибудь может понять в чем дело?

//This works fine and shows the Toast
public class Test {
    public void loadSelf(Context c) {
        try {
            ClassLoader loader = new DexClassLoader(c.getApplicationInfo().publicSourceDir, null, null, null);
            Class thisClass = loader.loadClass(this.getClass().getName());
            Method method = thisClass.getMethod("sayHi", Context.class);
            method.invoke(thisClass.newInstance(), c);
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sayHi(Context c) {
        Toast.makeText(c, "Hi!", Toast.LENGTH_LONG).show();
    }
}

1 Ответ

0 голосов
/ 21 апреля 2020

похожих вещей, с которыми я сталкивался

, затем я добавил эту строку

 minifyEnabled true

в эту часть app.gradle

 android {
 buildTypes {
    debug {
        minifyEnabled true
        useProguard false
        proguardFiles getDefaultProguardFile('proguard-android.txt')
    }
   }
 }

, кроме того, вы можете добавить зависимость ниже

 dependencies {
   compile 'com.android.support:multidex:1.0.0'
}

надеюсь, это поможет вам

...