Pull to refresh

Создаём модульное приложение

Reading time3 min
Views7.5K
Вы захотели сделать браузер с плагинами, программу с темами, игру с аддонами или какое-то другое модульное приложение для Android? Но как это сделать? Я расскажу, как сделать простое приложение, которое будет получать текст от модулей.

Возможно, то, что тут написано является костылями, но на dev.android.com и в гугле на эту тему я ничего не нашёл. Те, кто не любит читать лишнего, могут сразу разбирать код.

Теория


То, что я придумал, смотря на шаблон темы ADW Launcher, это посылать особые запросы модулю. То есть у модуля в <intent-filter> <action> параметр name будет иметь значение типа my.app.GET_DATA, а приложение будет с помощью startActivity (startActivityForResult) и startIntentSender (startIntentSenderForResult) посылать запросы. Хочу напомнить, что у одной Activity может быть несколько тегов <intent-filter>.

Практика


Начнём с программирования самого приложения. Основа приложение не сильно сложнее Hello World, поэтому я только расскажу, как работать с модулями.

Самый простой вариант предпросмотра:
// "mod.ul.ed.MODULES" - action у одного из intent-filter'а
Intent call = new Intent("mod.ul.ed.MODULES");
startActivity(call);
После вызова startActivity Android спросит у пользователя, какой модуль открыть и после выбора (можно назначить модуль по умолчанию) откроет.

Для открытия какого-то определённого модуля (и его определённой Activity) можно воспользоваться таким кодом:
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);
Модулю также можно передавать параметры, про это смотрите в описании класса Intent.

Чтобы получить данные от модуля лучше воспользоваться startIntentSenderForResult:
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) { }
Если пользоваться startActivityForResult, то пользователь сможет увидеть мелькание другого окна (Activity).

Ещё может понадобиться получить список модулей. Это реализует с помощью 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. Как я писал в начале, это возможно костыль. Если кто-то знает более элегантное и правильное решение просьба о нем рассказать.
Tags:
Hubs:
+4
Comments11

Articles