Вы захотели сделать браузер с плагинами, программу с темами, игру с аддонами или какое-то другое модульное приложение для Android? Но как это сделать? Я расскажу, как сделать простое приложение, которое будет получать текст от модулей. Возможно, то, что тут написано является костылями, но на dev.android.com и в гугле на эту тему я ничего не нашёл. Те, кто не любит читать лишнего, могут сразу разбирать код.
Теория
То, что я придумал, смотря на шаблон темы ADW Launcher, это посылать особые запросы модулю. То есть у модуля в
<intent-filter> <action> параметр name будет иметь значение типа my.app.GET_DATA, а приложение будет с помощью startActivity (startActivityForResult) и startIntentSender (startIntentSenderForResult) посылать запросы. Хочу напомнить, что у одной Activity может быть несколько тегов <intent-filter>.Практика
Начнём с программирования самого приложения. Основа приложение не сильно сложнее Hello World, поэтому я только расскажу, как работать с модулями.
Самый простой вариант предпросмотра:
После вызова startActivity Android спросит у пользователя, какой модуль открыть и после выбора (можно назначить модуль по умолчанию) откроет.// "mod.ul.ed.MODULES" - action у одного из intent-filter'а Intent call = new Intent("mod.ul.ed.MODULES"); startActivity(call);
Для открытия какого-то определённого модуля (и его определённой Activity) можно воспользоваться таким кодом:
Модулю также можно передавать параметры, про это смотрите в описании класса Intent.Intent call = new Intent("mod.ul.ed.MODULES"); // mod.ule.first - первый модуль // mod.ule.first.ActivityMain - главная Activity первого модуля call.setClassName("mod.ule.first", "mod.ule.first.MainActivity"); startActivity(call);
Чтобы получить данные от модуля лучше воспользоваться startIntentSenderForResult:
Если пользоваться startActivityForResult, то пользователь сможет увидеть мелькание другого окна (Activity).Intent call = new Intent("mod.ul.ed.GET_TEXT"); // Если убрать следующую строчку, то поведение будет как у первого варианта предпросмотра call.setClassName("mod.ule.first", "mod.ule.first.MainActivity"); IntentSender sender = PendingIntent.getActivity(getApplicationContext(), 1, call, 0).getIntentSender(); try { startIntentSenderForResult(sender, 1, call, 0, 0, 0); } catch (SendIntentException e) { }
Ещё может понадобиться получить список модулей. Это реализует с помощью PackageManager.queryIntentActivities(Intent intent, int flags):
// Будем искать Activity, которые принимают action = "mod.ul.ed.MODULES" Intent intent = new Intent("mod.ul.ed.MODULES"); // Получаем список подходящих Activity List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, 0);
Приступим к созданию модуля. Сначала в AndroidManifest.xml для нужных Activity добавим нужные действия, например действие GET_TEXT:
<intent-filter> <action android:name="mod.ul.ed.GET_TEXT" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
Что-либо возвращать нужно после проверки действия, сделать это можно так:
// Проверяем action if(getIntent().getAction().equals("mod.ul.ed.GET_TEXT")) { // Возвращаем результат Intent data = new Intent(); data.putExtra("text", "This is first module"); setResult(RESULT_OK, data); // Устанавливаем результат finish(); // Завершаем Activity return; // Завершаем исполнение кода }
[UPD] Для создания тем лучше получать ресурсы темы через getPackageManager().getResourcesForApplication(...) и использовать их.
Итог
Вот так несложно можно сделать модульное приложение. Для тех, кто не увидел ссылку в начале: код приложения и 2-х модулей можно посмотреть на googlecode. Как я писал в начале, это возможно костыль. Если кто-то знает более элегантное и правильное решение просьба о нем рассказать.