Полная поддержка Android для комплектов OSGi
В этом разделе объясняется, как вы можете преобразовать среду OSGI для работы на Android. Затем он дает советы по конвертации пакетов Android в пакеты OSGI, способные вызывать API Android.
На текущем этапе единственное, что не могут сделать эти пакеты Android OSGI, - это манипулировать действиями и использовать ресурсы и ресурсы. Я постоянно работаю над устранением этого ограничения. Я надеюсь получить хорошие новости на эту тему.
Мне было труднее использовать средство проекта "Создать плагин" в Eclipse, чем конвертировать стандартные пакеты Android в пакеты OSGI, поэтому я не буду много говорить об этом.
Вы можете отслеживать мои достижения в разделе "Журнал" в конце этого сообщения.
Я имею в виду проекты Knopflerfish, потому что это было основой для моей работы. Изменения предназначены для выполнения проектов Android OSGi Knopflerfish, но на самом деле применимы к другим средам OSGI. Нет необходимости изменять саму структуру OSGi, мы будем только обновлять проекты KfServiceLib
а также KfBasicApp
в tool
каталог распространения Knopflerfish.
Добавить базовую поддержку Android в пакеты
Особенности и ограничения
Это первый уровень настройки фреймворка для Android. Эти изменения пока не будут иметь ничего общего с контекстом или вызывающим потоком, но они позволяют использовать ограниченный набор классов API Android, таких как android.util.Log
,
Благодаря этим изменениям, пакеты смогут использовать классы Android в своих прототипах и в их реализации. Тем не менее, они не будут иметь ничего общего с графическим интерфейсом пользователя, поставщиками контента, системными службами и т. Д., Поскольку у них нет обязательных ссылок для него.
Изменения в приложениях Knopflerfish
Как они есть, приложения в tools/android/apk могут выполнять OSGi Framework на Android, но только если пакеты вызывают только Java-классы. Это относится к пакетам, которые являются частью платформы Knopflerfish, но как насчет пользовательских пакетов, которые хотят вызывать Android API? Вот изменения, которые нужно внести в платформу, чтобы разрешить пакеты, разрешающие классы Android.
Во-первых, пакеты Android должны быть частью пакетов платформы, чтобы их можно было разрешить. Это цель свойства OSGi org.osgi.framework.system.packages.extra
Установите свойство в список пакетов Android для экспорта перед созданием фреймворка, и все готово. Обратите внимание, что дикий голец android.*
кажется, не имеет никакого эффекта: мы должны сказать каждый пакет один за другим, как показано ниже.
Добавить в KfServiceLib
в файле src/org/knopflerfish/android/service/KfApk.java
static final String ANDROID_FRAMEWORK_PACKAGES = (
"android,"
+ "android.app,"
+ "android.content,"
+ "android.database,"
+ "android.database.sqlite,"
+ "android.graphics,"
+ "android.graphics.drawable,"
+ "android.graphics.glutils,"
+ "android.hardware,"
+ "android.location,"
+ "android.media,"
+ "android.net,"
+ "android.net.wifi,"
+ "android.opengl,"
+ "android.os,"
+ "android.provider,"
+ "android.sax,"
+ "android.speech.recognition,"
+ "android.telephony,"
+ "android.telephony.gsm,"
+ "android.text,"
+ "android.text.method,"
+ "android.text.style,"
+ "android.text.util,"
+ "android.util,"
+ "android.view,"
+ "android.view.animation,"
+ "android.webkit,"
+ "android.widget");
Затем мы устанавливаем дополнительные пакеты в KfApk.newFramework()
config.put(Constants.FRAMEWORK_STORAGE, fwDir);
// Export android packages so they can be referenced by bundles
config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
ANDROID_FRAMEWORK_PACKAGES);
Примечание: если вы можете, лучше настроить дополнительную конфигурацию с помощью файла, а не кода в программе.
Импорт пакетов Android в пакетах
Даже если пакеты Android были добавлены в системные пакеты, объявленные платформой, пакет все равно должен импортировать их для разрешения, как и любой другой импортированный пакет.
Пример:
Пакет импорта: org.osgi.framework, android.content, android.widget, android.util
Примечание: вы можете использовать кнопку "auto" плагина Knopflerfish Eclipse для автоматического обновления импорта, как и должно быть.
Передать контекст в пакеты
Больше изменений в приложениях Knopflerfish
После этих изменений вы сможете запускать пакеты, начиная действия самостоятельно или обращаясь к ресурсам контекста. Весь набор классов Android API должен быть полностью доступен для пакетов. Но есть некоторые ограничения, применимые к пакетному кодированию, чтобы достичь этого. Все, что нам нужно, это ссылка на контекст приложения, поэтому мы собираемся поместить его в структуру!
Добавить в org.knopflerfish.android.service.Knopflerfish.onStartCommand()
if (fw != null) {
// Register the application's context as an OSGi service!
BundleContext bundleContext = fw.getBundleContext();
regContext = bundleContext.registerService(Context.class,
getApplicationContext(), new Hashtable());
sendMessage(Msg.STARTED, (Serializable) KfApk.getFrameworkProperties());
} else {
// framework did not init/start
sendMessage(Msg.NOT_STARTED);
stopSelf();
return;
}
Мы передаем контекст приложения, и только этот, потому что это единственный Контекст, который будет существовать на протяжении всей жизни приложения. Он будет установлен сразу после запуска приложения, то есть после установки или загрузки системы. Связки могут поддерживать сильную ссылку на этот контекст, это нормально.
Как связки используют контекст
Пучок получает Context
от BundleContext
перешел к его активатору:
static Context context;
public void start(BundleContext bc) throws Exception {
ServiceReference<Context> ref = bc.getServiceReference(Context.class);
context = bc.getService(ref);
}
Поскольку пакет выполняется в потоке, отличном от потока пользовательского интерфейса, операции пользовательского интерфейса могут выполняться только в том случае, если они "выдвинуты" в поток пользовательского интерфейса. Для этого целесообразно спроектировать повторно используемый метод:
public static void runOnContext(Context context, Runnable runnable) {
Handler handler = new Handler(context.getMainLooper());
handler.post(runnable);
}
Этот метод должен быть частью сервиса из пакета утилит, так как он должен быть доступен для множества различных пакетов Android одинаковым образом.
Например, этот пакет показывает "Hello" при запуске:
public void start(BundleContext bc) throws Exception {
ServiceReference<Context> ref = bc.getServiceReference(Context.class);
final Context context = bc.getService(ref);
runOnContext(context, new Runnable() {
public void run() {
Toast.makeText(context, "Hello", Toast.LENGTH_LONG).show();
}
});
}
Дешевый способ использовать приложения, такие как пакеты
Для краткости я буду ссылаться на APK, преобразованный в комплект OSGI, как комплект APK.
- Создайте обычный APK, например, благодаря Eclipse Android Project
- Добавьте справочную библиотеку в проект Build Path для вашей платформы OSGi (в моем случае framework.jar)
- Изменить файл манифеста пакета
bundle.manifest
описание пакета (см. пример ниже). Этот файл не является частью APK, но будет использоваться во время пользовательских шагов сборки - Скажите, что ваш пакет приложений
com.acme.helloworld
(это значение устанавливается с помощью manifest: package в AndroidManifest.xml), класс Activator вашего OSGI-пакета ДОЛЖЕН быть помещен в пакетcom.acme.helloworld
и вы ДОЛЖНЫ установитьBundle-SymbolicName: com.acme.helloworld
в связке манифеста. Если какое-либо из этих условий не будет выполнено, это приведет кjava.lang.NoClassDefFoundError
во время выполнения.
Напоминаем, что ваш файл манифеста пакета должен выглядеть так:
Manifest-Version: 1.0
Bundle-Vendor: Acme
Bundle-Version: 1.0.0
Bundle-Name: HelloWorldBundle
Bundle-ManifestVersion: 2
Bundle-Activator: com.acme.helloworld.Activator
Bundle-Description: Hello World Bundle
Import-Package: org.osgi.framework
Bundle-SymbolicName: com.acme.helloworld
Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.0
- Используйте Инструменты Android> Экспортировать неподписанный пакет Android
- копия
bundle.manifest
в сгенерированном неподписанном APK какMETA-INF/MANIFEST.MF
- Подпишите APK, используя любой сертификат, который вы хотите. Здесь у вас есть готовый пакет APK
- Установите пакет APK как обычно. Установка необходима для разрешения действий. Без этого активность не разрешится и пакет не будет выполнен
- Загрузите фреймворк OSGi и запустите пакет APK (тот же файл APK)
Чтобы запустить действие из комплекта APK, используйте следующий код.
// This is the application's context provided by the framework
// Context ctx = ...
Intent intent = new Intent();
String pkgName = YourActivity.class.getPackage().getName();
String clssName = YourActivity.class.getName();
intent.setClassName(pkgName, clssName);
// You may add the NEW_TASK flag
intent.addFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
// Important: do not use startActivity(Context, Class) version because it will fail to resolve the activity
ctx.startActivity(intent);
Журнал
начальный
На данный момент мои усилия, Android-связки:
- может вызывать классы Android SDK, если они не требуют ресурсов или объявления в AndroidManifest.xml,
- иметь доступ к приложениям
android.content.Context
, который может быть использован для запуска деятельности из каркаса OSGi.
Связки не могут:
- запросить разрешение Android,
- строить мероприятия из макета, даже не начинать их вообще,
- определить статический приемник вещания, объявленный в
AndroidManifest.xml
хотя получатель, созданный с помощью кода, должен быть в порядке.
Это те ограничения, которые я испытал до сих пор, которые я пытаюсь преодолеть, и цель моей просьбы о помощи.
На что я нацеливаюсь:
- иметь поддержку внутренних ресурсов, особенно макетов,
- быть в состоянии создавать и запускать внутренние действия с помощью кода, если это невозможно с помощью XML Builder.
Каковы мои достижения на данный момент, через испытания:
- Сделайте проект Android видимым как пакет OSGi и библиотека APK/android, смешивая Builders, экспортируя неподписанные двоичные файлы и объединяя вручную
bundle.manifest
в MANIFEST.MF перед подписью сjarsigner
, В результате APK загружается фреймворком OSGi и достигает разрешенного состояния, но не может запуститься из-заjava.lang.NoClassDefFoundError
в моем классе-активаторе, даже если этот класс является частью classes.dex и на пути нет явной ошибки. Создание проекта как пакета OSGi с зависимостями android позволяет получить доступ к активатору, но не к ресурсам android в JAR. Непонятные. - Проверьте все функции, описанные в разделе "можно сделать" данного руководства.
Редактировать 2013-09-03
Я нашел способ начать действия, принадлежащие пакетам Android. Смотрите соответствующую главу.
Редактировать 2013-09-10: стандартный контейнер OSGI
Через несколько дней я сделал программы Knopflerfish универсальными для запуска любой среды OSGi, которую я хочу. Например, в настоящее время я использую Knopflerfish или Felix таким же образом. Все еще существует потребность в конкретной конфигурации фреймворка.
Это означает, что тема больше не только Knopflerfish, даже если необходимые программы были выпущены Knopflerfish.
2013-09-27: общее сравнение состояния и рамок
Я должен отложить этот проект на некоторое время из-за изменения приоритета. Однако до сих пор я оценивал следующие решения:
- Knopflerfish OSGi [Открытый исходный код],
- Felix и FelixDroid [Открытый исходный код],
- ProSyst mBS SDK (на основе Equinox, для коммерческого использования)
Подводя итог, ни один из них не имеет полезного преимущества, когда дело доходит до поддержки графического интерфейса: ни один из них не может обрабатывать ресурсы или ресурсы (строки, макеты, изображения) в андроиде, но вы все равно можете обрабатывать их как ресурс OSGi с помощью OSGi API, но вы не сможете использовать их в Android как обычно.
Мне лично нравится сервлет консоли администрирования Knopflerfish, но его поддержка GUI ничего не значит. Felix + FelixDroid имеет хороший баланс для бесплатного решения OSGi, в то время как mBS SDK поддерживает широкий ряд различных целей для виртуальных машин и определяет основанную на намерениях структуру приложения, которая может больше соответствовать вкусу профессиональных разработчиков.
В то время как Knopflerfish и Felix используются практически одинаково, mBS SDK во многих отношениях сильно отличается. Knopflerfish и Felix взаимозаменяемы: я написал контейнерную программу, в которой выбор OSGi-фреймворка зависит только от выбора другой зависимости JAR, созданной вручную!
Когда дело доходит до GUI, Knopflerfish ничего не дает. Вам нужно будет пройти мои рекомендации, чтобы получить немного больше поддержки. Основная идея в FelixDroid хороша, на самом деле это нечто подобное, реализованное в mBS SDK, но это пустая трата, если не иметь реализацию в виде пакета. Более того, mBS SDK добился большего успеха, определив среду приложений OSGi, созданную с особыми намерениями. Оба объединяют взгляды в основной деятельности примерно одинаково.
Еще одно поразительное отличие mBS SDK заключается в том, что вам не нужно добавлять зависимости фреймворка android и не добавлять для них директивы Import-Package. Это, безусловно, вызывает беспокойство после того, как вы некоторое время полагаетесь на Knopflerfish или Felix. Кроме того, он полностью интегрирован в Eclipse и предоставляет разработчику множество удобных задач: ПК для мониторинга инфраструктуры OSGi (Kf и Felix предоставляют только целевую консоль администрирования) и быстрое развертывание. Ямы, по сути, являются несвободными и что приложение контейнера практически невозможно настроить.
1 ответ
По чистой случайности я нашел многообещающую платформу с открытым исходным кодом (Apache License 2), которая может представлять интерес. Это называется DEMUX Framework. Не стесняйтесь оценить это решение. Я сам, но просматривая функции и исходный код, я думаю, что у него хороший потенциал и аккуратная интеграция. Что касается поддержки графического интерфейса, он использует подход, аналогичный FelixDroid. Это может стать открытой альтернативой Prosyst mBS SDK.
Вот как его дизайнер определяет структуру:
DEMUX Framework позволяет разработчикам Java легко создавать приложения для настольных, веб-и мобильных устройств из единой кодовой базы. Он предоставляет модульную архитектуру приложений, основанную на OSGI, которая позволяет легко создавать надежные и расширяемые приложения.
Тем не менее, Android - единственная мобильная ОС, поддерживаемая на данном этапе, и я желаю ему удачи в двух других (у меня был некоторый болезненный опыт в прошлом на эту тему)