Возможно ли динамически загружать класс Activity из библиотеки jar на sdCard и фактически использовать его?
У меня есть файл .jar на sdCard (я использовал инструмент dx для компиляции обычного .jar для dex.. в противном случае андроид будет жаловаться во время выполнения)
Класс, который я хочу использовать, на самом деле представляет собой Activity и "use", я имею в виду Inflate!
A) Я заметил, что если я загружаю класс таким образом, загруженный класс будет иметь пакетный пакет пакета parrent-класса (тот, в котором я запускаю код: example: real-package of class в библиотеке jar: "com.something" и my-app-package: "com.wonderfull" → загруженный класс находится в "com.wonderfull.com.something":)) → проверено: он сохраняет оригинальный пакет, так же, как в библиотеке
B) В случае "наилучшего" сценария я получаю эту ошибку:
Невозможно создать экземпляр активности ComponentInfo {com.appno2/com.appno1.futureLib.LibActivity}: java.lang.ClassNotFoundException: com.appno1.futureLib.LibActivity в loader dalvik.system.PathClassLoader [/data/app/com.appno2-1.apk]
C) В манифесте я разместил Activity (тот, который будет загружен динамически) следующим образом:
активность Android: name= "com.appno1.futureLib.LibActivity" android: label = "@string/app_name" > /Деятельность >
Итак, я повторяю вопрос из заголовка: возможно ли динамически загружать класс Activity из библиотеки jar на sdCard и фактически использовать его?
В случае "Зачем вам это нужно?" - просто любопытные!
+ как концепция: возможность загрузить фактический код приложения (в форме банки чего-то) сразу после того, как пользователь ввел действительную лицензию
Обновление:
- этот идеал работает с фрагментами (значит, класс, который должен быть импортирован, является фрагментом)
Текущее заключение:
- возможно, существуют классы lame java или даже классы, связанные с интерфейсом Android в внешнем .jar(например, на SDCard или для загрузки из интернета и т.д.) и загружать их динамически при необходимости. О да: вы не можете работать так, как это делают:(.. возможно даже не службы..
Дополнительная информация # 1: Возможно ли динамически загружать библиотеку во время выполнения из приложения Android?
Дополнительная информация # 2: http://android-developers.blogspot.ro/2011/07/custom-class-loading-in-dalvik.html
Regardin URLClassLoader: это работает (без привлечения DalvikClassLoader - ClassNotFoundException & & obviosly: по-прежнему не может надуть активность, загруженную таким образом)
File file = new File("/sdcard/myLib.jar");
File tmpDir = getDir("dex", 0);
ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}, this.getClass().getClassLoader());
DexClassLoader classloader = new DexClassLoader(file.getAbsolutePath(), tmpDir.getAbsolutePath(), null, loader);
Class<Object> classref = (Class<Object>) classloader.loadClass("packageInLib.ClassName");
Object myInstance = classref.getConstructor().newInstance();
Or instead of "loadClass"
Class<?> classref = Class.forName("packageInLib.ClassName", true, dalvikClassLoader);
Ответы
Ответ 1
У меня были похожие сценарии.
Если u не помещается ниже кодов в AndroidManifest.xml
<activity android:name="com.appno1.futureLib.LibActivity" android:label="@string/app_name" > </activity>
U будет ниже ошибки.
10-21 17:04:25.860: E/AndroidRuntime(11050): Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {... ...}; have you declared this activity in your AndroidManifest.xml?
Но если вы зарегистрируете активность в своем клиентском приложении, тогда будет получено java.lang.ClassNotFoundException.
Загрузитель попытался выполнить поиск com.appno1.futureLib.LibActivity в [/data/app/com.appno2-1.apk]. Очевидно, этого не ожидается. Я считал, что com.appno.futureLib.LibActivity находится в файле .jar.
Если есть способ позволить загрузчику искать LibActivity в файле .jar, проблема может быть решена.
Ответ 2
Вы можете сканировать файлы JAR для своего содержимого и загружать классы с помощью URLClassloader. Это стандартная Java (у меня есть реализация JavaSE, если вы хотите взглянуть), но она включена в Android API, поэтому я думаю, что она должна работать нормально.
URLClassloader на developer.android.com
В основном вы получаете ClassLoader (предупреждение о грязном коде!):
File file = new File("/sdcard/jars/myDynamicLib.jar");
ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}, this.getClass().getClassLoader());
вам нужны ваши метаданные XML или что-то другое, что нужно загрузить:
jar.getInputStream(jar.getEntry("myMetaData.xml"));
Вы загружаете информацию (способ ее анализа зависит от формата, который вы используете: вы можете уже загрузить его с вашим приложением) - теперь у вас есть имя класса.
И теперь вы просто пытаетесь загрузить:
Class<?> classref = Class.forName(className, true, loader);
instance = (MyType) classref.getConstructor().newInstance();
Опять же, хотя я не пробовал такие вещи на Droid, я думаю, что это должно работать нормально.
Вот и все. Вам нужен путь к файлу JAR и имя загружаемого класса. Класс загрузчик вытащит классы из JAR для вас.