Intereting Posts
Как получить все растровое изображение, прикрепленное к ImageView? Как изменить ориентацию экрана в эмуляторе Android? Список PullToRefresh с прикрепленным заголовком раздела Самый быстрый способ дублирования проекта Android? Пример Android JSoup Как сделать приложение Facebook новым приложением на Android? Android – Вращение ImageView с пальцем перемещает другие виды вокруг Как нарисовать вектор направления в Android Кнопка Android. Как настроить фокусировку на истину и все еще принимать onClick прослушиватель при первом нажатии? OnCreate () вызывается при повторном открытии из недавней задачи после изменения настроек разрешения Как сделать прослушиватель прокрутки для WebView в Android API Android V2 и API для Google Maps EditText в Listview теряет фокус при нажатии на Android 4.x Google Maps V2 Android работает как фрагмент, но показывает белый экран (с управлением зумом) как дочерний фрагмент База данных Android – не может выполнять эту операцию, поскольку пул соединений был закрыт

Можно ли динамически загружать библиотеку во время выполнения из приложения Android?

Есть ли способ сделать приложение Android для загрузки и использования библиотеки Java во время выполнения?

Вот пример:

Представьте, что приложение должно выполнять некоторые вычисления в зависимости от входных значений. Приложение запрашивает эти входные значения, а затем проверяет наличие доступных Classe или Method s.

Если нет, он подключается к серверу, загружает нужную библиотеку и загружает ее во время выполнения, чтобы вызвать необходимые методы с использованием методов отражения. Реализация может измениться в зависимости от различных критериев, таких как пользователь, который загружает библиотеку.

Solutions Collecting From Web of "Можно ли динамически загружать библиотеку во время выполнения из приложения Android?"

Извините, я опаздываю, и вопрос уже принят, но да , вы можете загружать и выполнять внешние библиотеки. Вот как я это сделал:

Мне было интересно, возможно ли это, поэтому я написал следующий класс:

 package org.shlublu.android.sandbox; import android.util.Log; public class MyClass { public MyClass() { Log.d(MyClass.class.getName(), "MyClass: constructor called."); } public void doSomething() { Log.d(MyClass.class.getName(), "MyClass: doSomething() called."); } } 

И я упаковал его в файл DEX, который я сохранил на SD-карте своего устройства в качестве /sdcard/shlublu.jar .

Затем я написал «тупую программу» ниже, удалив MyClass из моего проекта Eclipse и очистив его:

 public class Main extends Activity { @SuppressWarnings("unchecked") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { final String libPath = Environment.getExternalStorageDirectory() + "/shlublu.jar"; final File tmpDir = getDir("dex", 0); final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader()); final Class<Object> classToLoad = (Class<Object>) classloader.loadClass("org.shlublu.android.sandbox.MyClass"); final Object myInstance = classToLoad.newInstance(); final Method doSomething = classToLoad.getMethod("doSomething"); doSomething.invoke(myInstance); } catch (Exception e) { e.printStackTrace(); } } } 

Он в основном загружает класс MyClass таким образом:

  • Создать DexClassLoader

  • Используйте его для извлечения класса MyClass из "/sdcard/shlublu.jar"

  • И сохраните этот класс в частной директории приложения "dex" (внутренняя память телефона).

Затем он создает экземпляр MyClass и вызывает doSomething() в созданном экземпляре.

И это работает … Я вижу следы, определенные в MyClass в моем LogCat:

Введите описание изображения здесь

Я пробовал как на эмуляторе 2.1, так и на моем физическом мобильном телефоне HTC (который работает под управлением Android 2.2 и который НЕ укоренен).

Это означает, что вы можете создавать внешние DEX-файлы для загрузки и выполнения приложения. Здесь это было сделано сложным способом (уродливые Method.invoke() , Method.invoke() уродливые звонки …), но должно быть возможно играть с Interface s, чтобы сделать что-то более чистым.

Вау. Я первый удивлен. Я ожидал исключения SecurityException .

Некоторые факты, которые помогут расследовать больше:

  • Мой DEX shlublu.jar был подписан, но не мое приложение
  • Мое приложение было выполнено из Eclipse / USB-соединения. Таким образом, это неподписанный APK, скомпилированный в режиме DEBUG

Взгляд Shlublu действительно хорош. Некоторые мелочи, хотя это поможет новичкам:

  • Для файла библиотеки «MyClass» создайте отдельный проект приложения для Android, в котором файл MyClass есть только файл в папке src (там также должны быть другие файлы, такие как project.properties, manifest, res и т. Д.).
  • В манифесте проекта библиотеки убедитесь, что у вас есть: <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".NotExecutable" android:label="@string/app_name"> </activity> </application> (« .NotExecutable »не является зарезервированным словом. Мне просто нужно что-то здесь положить)

  • Для создания файла .dex просто запустите проект библиотеки в качестве приложения для Android (для компиляции) и найдите файл .apk из папки bin проекта.

  • Скопируйте файл .apk на свой телефон и переименуйте его как файл shlublu.jar (APK на самом деле специализируется на банке)

Другие шаги такие же, как описано Shlublu.

  • Большое спасибо Шлюбру за сотрудничество.

Я не уверен, что вы можете добиться этого путем динамической загрузки java-кода. Может быть, вы можете попробовать внедрить скриптовый движок своего кода, например, rhino, который может выполнять java-скрипты, которые можно динамически загружать и обновлять.

Конечно, это возможно. Apk, который не установлен, может быть вызван хостом android application.generally, разрешить жизненный цикл ресурса и активности, а затем динамически загружать jar или apk. Подробно см. В моем исследовании с открытым исходным кодом по github: https://github.com/singwhatiwanna/dynamic-load-apk/blob/master/README-en.md

Кроме того, требуется DexClassLoader и отражение, теперь посмотрите на код ключа:

 /** * Load a apk. Before start a plugin Activity, we should do this first.<br/> * NOTE : will only be called by host apk. * @param dexPath */ public DLPluginPackage loadApk(String dexPath) { // when loadApk is called by host apk, we assume that plugin is invoked by host. mFrom = DLConstants.FROM_EXTERNAL; PackageInfo packageInfo = mContext.getPackageManager(). getPackageArchiveInfo(dexPath, PackageManager.GET_ACTIVITIES); if (packageInfo == null) return null; final String packageName = packageInfo.packageName; DLPluginPackage pluginPackage = mPackagesHolder.get(packageName); if (pluginPackage == null) { DexClassLoader dexClassLoader = createDexClassLoader(dexPath); AssetManager assetManager = createAssetManager(dexPath); Resources resources = createResources(assetManager); pluginPackage = new DLPluginPackage(packageName, dexPath, dexClassLoader, assetManager, resources, packageInfo); mPackagesHolder.put(packageName, pluginPackage); } return pluginPackage; } 

Ваши требования лишь частично функционируют в проекте с открытым исходным кодом, упомянутом в начале.

Если вы держите свои файлы .DEX во внешней памяти телефона, например, SD-карту (не рекомендуется! Любое приложение с одинаковыми разрешениями может легко перезаписать ваш класс и выполнить атаку инъекции кода), убедитесь, что вы предоставили Разрешение приложения читать внешнюю память. Исключением, которое возникает, если это так, является «ClassNotFound», который довольно вводит в заблуждение, добавьте в манифесте что-то вроде следующего (обратитесь к Google для самой последней версии).

 <manifest ...> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" /> ... </manifest>