Android - использование DexClassLoader для загрузки файла apk
Я ударил немного о стену. Любая помощь будет оценена по достоинству. У меня есть приложение, которое я хочу использовать DexClassLoader для загрузки другого файла apk.
Вот мой код:
DexClassLoader dLoader = new DexClassLoader("/sdcard/download/test.apk","/sdcard/download",null,ClassLoader.getSystemClassLoader().getParent());
Class calledClass = dLoader.loadClass("com.test.classname");
Intent it=new Intent(this, calledClass);
it.setClassName("com.test", "com.test.classname");
startActivity(it);
Теперь я уже установил test.apk, поэтому, когда я запускал вышеуказанный код, он
работал отлично и запустил приложение. Однако я хочу иметь возможность
запустите это без установки test.apk(так как это будет
победить всю точку приложения). Поэтому я удалил его и
когда я снова запустил приложение, я получаю эту ошибку:
android.content.ActivityNotFoundException: Unable to find explicit
activity class {com.test/com.test.classname}; have you declared this
activity in your AndroidManifest.xml.
Итак, я немного здесь. Эта деятельность объявлена в манифесте
из apk я пытаюсь запустить. Я не могу объявить это в своих приложениях
Manifest. Любые идеи?
Спасибо,
Крейг
Ответы
Ответ 1
Попробуйте использовать Android PathClassLoader:
String packagePath = "com.mypackage";
String classPath = "com.mypackage.ExternalClass";
String apkName = null;
try {
apkName = getPackageManager().getApplicationInfo(packagePath,0).sourceDir;
} catch (PackageManager.NameNotFoundException e) {
// catch this
}
// add path to apk that contains classes you wish to load
String extraApkPath = apkName + ":/path/to/extraLib.apk"
PathClassLoader pathClassLoader = new dalvik.system.PathClassLoader(
apkName,
ClassLoader.getSystemClassLoader());
try {
Class<?> handler = Class.forName(classPath, true, pathClassLoader);
} catch (ClassNotFoundException e) {
// catch this
}
Ответ 2
Хотя вопрос старый, я отвечу, потому что я изо всех сил пытался найти ясный ответ по тому же самому вопросу. Во-первых, я хотел бы подчеркнуть, что четкое требование в вашем вопросе - загрузить класс из .apk, который еще не установлен на устройстве. Поэтому вызов диспетчера пакетов с помощью getPackageManager() и предоставление ему пути пакета явно приведет к методу NameNotFoundException, поскольку .apk, у которого есть пакет, не установлен на устройстве.
Итак, способ загрузки классов из файла .apk, который не установлен на устройстве (т.е. у вас есть только .apk, хранящийся в каталоге на SDCARD), используя DexClassLoader следующим образом:
1- Убедитесь, что у вас есть файл .apk в каталоге на SDCARD. У меня есть Offloadme.apk в папке "Загрузить" на SDCARD.
2- Добавьте разрешение на чтение в свой AndroidManifest.xml, чтобы ваше приложение могло читать из манифеста.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
3 Используйте следующие определения для определения пути .apk, имени класса внутри apk и имени метода в этом классе, который вы хотите вызвать:
final String apkFile =Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/Offloadme.apk";
String className = "com.khaledalanezi.offloadme.SimpleCalculator";
String methodToInvoke = "add";
4- Используйте DexClassLoader для загрузки .apk и вызовите метод добавить в класс SimpleCalculator, используя отражение следующим образом:
final File optimizedDexOutputPath = getDir("outdex", 0);
DexClassLoader dLoader = new DexClassLoader(apkFile,optimizedDexOutputPath.getAbsolutePath(),
null,ClassLoader.getSystemClassLoader().getParent());
try {
Class<?> loadedClass = dLoader.loadClass(className);
Object obj = (Object)loadedClass.newInstance();
int x =5;
int y=6;
Method m = loadedClass.getMethod(methodToInvoke, int.class, int.class);
int z = (Integer) m.invoke(obj, y, x);
System.out.println("The sum of "+x+" and "+"y="+z);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Обратите внимание, что в моем простом примере я добавил два числа, используя метод добавить, доступный в классе SimpleCalculator, загруженном из Offloadme.apk файл, хранящийся на SDCARD, и я смог напечатать правильный ответ, который равен 11.
Ответ 3
Вы не можете этого сделать. Даже если вы можете получить доступ к классам из внешнего файла, Android все еще не знает их. И вы не запускаете действия напрямую, а попросите Android запустить их, поэтому их необходимо зарегистрировать/установить в систему.