Отправка Intent из виджета в стороннее приложение (Android)

Поделюсь своим опытом, ведь не каждый разработчик сталкивается с разработкой абсолютно каждой фичи в Android.
Как то меня посетила идея прикрутить к своему приложению виджет. Но прикрутить его по хитрому — сделав его совершенно отдельной программой.
Для чего это нужно? Ну, предположим, что вы хотите продавать некоторые части (функционал) приложения отдельно. Будь то чат, виджет календаря, виджет погоды и т.д.
Как осуществить связь разрабатываемого отдельно виджета с основным приложением? На самом деле, не долго думая, в голову приходит элементарно простое решение — с помощью Intent-ов, Receiver-ов и общего Action.
Сейчас я покажу, как с минимальными затратами усилий подключить только что созданный виджет к своему приложению.
Создаём виджет через автоматический шаблон в Android Studio. Получаем что-то вроде такого:
public class SomeWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager
appWidgetManager,int appWidgetId) {
RemoteViews views = new
RemoteViews(context.getPackageName(),
R.layout.some_widget);
appWidgetManager.updateAppWidget(appWidgetId, views);}
@Override
public void onUpdate(Context context, AppWidgetManager
appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
}
@Override
public void onDisabled(Context context) {
}
}
Ничего удивительного в этом коде нет. Обычный шаблон.
Теперь нам надо сделать 3 вещи:
- Добавить элемент в layout файл нашего виджета (R.layout.some_widget)
- Присвоить этому элементу (не важно что это, кнопка, текстовое поле или рисунок) идентификатор
- Так как виджет является Receiver-ом, то нам надо придумать название Action и прописать его в манифесте в теге <intent-filter> (в шаблоне это уже сделано, но я советую сделать новый Action). Например: com.example.myApp.SOME_BUTTON_PRESSED
Далее, работаем с кодом. В качестве примера я добавил кнопку с id “button”.
public class SomeWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager
appWidgetManager,int appWidgetId) {
RemoteViews views = new
RemoteViews(context.getPackageName(),
R.layout.some_widget);Intent intent = new Intent();
intent.setAction("com.example.myApp.SOME_BUTTON_PRESSED");
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context,0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager
appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
}
@Override
public void onDisabled(Context context) {
}
}
Мы сделали следующее:
- Создали Intent и присвоили ему наш Action
- Обернули наш Intent в PendingIntent с флагом FLAG_UPDATE_CURRENT
- Указали, что при клике на элементе “button” в виджете будет запущено PendingIntent
Далее, ниже мы пишем метод OnReceive (ведь у нас всё же Receiver).
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction()
.equals("com.example.myApp.SOME_BUTTON_PRESSED"))
{
Intent toMainApp = new Intent();
toMainApp.setAction
("com.example.anotherApp.SOME_BUTTON_PRESSED");
context.sendBroadcast(toMainApp);
}
}
Здесь мы создаём новый Intent и задаём ему Action, который будет отлавливаться Receiver-ом на стороне другого приложения и отправляем его.
После этого остаётся лишь создать в основном приложении Receiver, который на вход принимает Action: com.example.anotherApp.SOME_BUTTON_PRESSED и обработать его.
Вот и всё.
С наилучшими пожеланиями.