Отправить трансляцию с комбинацией локального широковещательного менеджера sendorderedbroadcast
Я хочу реализовать то, что CommonsWare описывает в этом сообщении в блоге: http://commonsware.com/blog/2010/08/11/activity-notification-ordered-broadcast.html. Пост имеет смысл, и я смог просмотреть пример источника здесь: https://github.com/commonsguy/cw-advandroid/tree/master/Broadcast.
Что меня интересует, так это звонки LocalBroadcastManager.getInstance(UnzipService.this).sendBroadcast(broadcast);
внутри службы по-прежнему будет приниматься вещательный приемник того типа, который вы определили в своем манифесте.
В случае, если то, что я спрашиваю, неясно, то, что я пытаюсь сделать, это использовать LocalBroadcastManager, потому что трансляции из моего сервиса не обязательно должны просматриваться в масштабе всей системы, и я предпочел бы сохранить их конфиденциальными, если это возможно, но я также хочу отображать уведомления, если пользователь закрывает мое приложение и служба все еще работает. Есть ли способ объединить обе эти возможности, не отправляя трансляцию дважды внутри службы?
(Что я не хочу делать) вроде:LocalBroadcastManager.getInstance(UnzipService.this).sendBroadcast(broadcast);
sendOrderedBroadcast(broadcast);
4 ответа
Что мне любопытно, так это если вы вызываете LocalBroadcastManager.getInstance(UnzipService.this).sendBroadcast(broadcast); внутри службы по-прежнему будет приниматься вещательный приемник того типа, который вы определили в своем манифесте.
Нет. LocalBroadcastManager
работает только с получателями, зарегистрированными в LocalBroadcastManager
сам синглтон. Более того, LocalBroadcastManager
не поддерживает заказанные трансляции, последний раз проверял.
то, что я пытаюсь сделать, это использовать LocalBroadcastManager, потому что трансляции из моего сервиса не обязательно должны быть просмотрены во всей системе, и я бы предпочел сохранить их частными, если это возможно
Пока вы не используете <intent-filter>
на ваше BroadcastReceiver
в манифесте, и, следовательно, используют явное Intent
Что касается самой трансляции, то ваша трансляция будет видна только вам и той части ОС, которая управляет трансляциями. Другие приложения не смогут шпионить за ним.
Если у вас есть только 2 объекта, которые могут обрабатывать вашу трансляцию (в вашем случае контроллер Activity и контроллер уведомлений), вы можете добиться поведения упорядоченной трансляции, используя только LocalBroadcastManager.
Общая идея такова:
- Настройте свою Службу так, чтобы она передавала Намерение вашей Деятельности с определенным действием, когда вы хотите отобразить свой результат.
- В своей Деятельности создайте BroadcastReceiver, который обрабатывает ваш Intent результат Intent, и зарегистрируйте его в LocalBroadcastManager с помощью IntentFilter, используя действие из шага 1
- В вашей службе, когда результаты доступны, попытайтесь отправить результат Intent с помощью LocalBroadcastManager.getInstance(Context).sendBroadcast(Intent) этот метод возвращает логическое значение, которое указывает, была ли широковещательная рассылка отправлена хотя бы одному получателю. Если это логическое значение false, это означает, что ваша активность не обрабатывает вашу трансляцию, и вы должны вместо этого показывать уведомление.
К вашим услугам:
public UnzipService extends IntentService {
public static final String ACTION_SHOWRESULT = UnzipService.class.getCanonicalName() + ".ACTION_SHOWRESULT";
@Override
protected void onHandleIntent(Intent intent) {
Thread.sleep(500); // Do the hard work
// Then try to notify the Activity about the results
Intent activityIntent = new Intent(this, YourActivity.class);
activityIntent.setAction(ACTION_SHOWRESULT);
activityIntent.putExtra(SOME_KEY, SOME_RESULTVALUE); // Put the result into extras
boolean broadcastEnqueued = LocalBroadcastManager.getInstance(this).sendBroadcast(activityIntent);
if (!broadcastEnqueued) { // Fallback to notification!
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
.notify(SOME_ID, new NotificationCompat.Builder(this)
.setContentIntent(pendingIntent)
.setTicker("results available")
.setContentText("results")
.build());
}
}
}
В вашей деятельности:
public YourActivity extends Activity {
private BroadcastReceiver resultReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
processResult(intent); // Results Intent received through local broadcast
}
}
private IntentFilter resultFilter = new IntentFilter(UnzipService.ACTION_SHOWRESULT);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate();
Intent intent = getIntent();
if (UnzipService.ACTION_SHOWRESULT.equals(intent.getAction())) {
// The Activity has been launched with a tap on the notification
processResult(intent); // Results Intent contained in the notification PendingIntent
}
}
@Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this)
.registerReceiver(resultReceiver, resultFilter);
}
@Override
protected void onPause() {
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(resultReceiver);
super.onPause();
}
private void processResult(Intent intent) {
// Show the results from Intent extras
}
}
Это должно быть полным рабочим примером.
Надеюсь, это поможет тем, кто пытается реализовать упорядоченные трансляции с LocalBroadcastManager из библиотеки поддержки!
Я понимаю, что вы хотите добиться следующего:
"У меня есть событие, которое происходит в фоновом режиме. Я хочу обновить свою активность, если она отображается на экране. В противном случае я хочу вызвать Уведомление". (@TheCommonsBlog)
Вы можете достичь этого поведения, реализуя ResultReceiver. Примеры сервиса Restful API и http://itekblog.com/background-processing-with-intentservice-class/
В основном вы делаете экземпляр ResultReceiver в своей деятельности и передаете его в службу как параметр Parcelable через намерение. Затем каждый раз, когда ваша служба обновляет пользовательский интерфейс, служба проверяет объект ResultReceiver на NULL. Если не NULL, вы обновляете пользовательский интерфейс через интерфейс onReceiveResult. Иначе, вы поднимаете уведомление. Когда ваша активность будет прекращена, убедитесь, что для ResultReceiver на Сервисе установлено значение NULL.
Надеюсь, поможет.
PS: IMO, трансляции - это слишком много работы и их трудно контролировать.
Используйте LocalBroadcastManager и трансляции становятся простыми в использовании.
Я не сторонник обновления Activity, если событие происходит в фоновом режиме. Пользователь может уже делать что-то еще в Деятельности. Мне кажется, что Уведомление достаточно; он всегда виден и остается, пока пользователь не отклонит его. Gmail и Gcal работают так; Gmail не обновляет текущий экран, если приходит новое письмо. Если вы хотите знать, как обрабатывать поток задач для обработки уведомлений, когда пользователь уже находится в приложении, см. Руководство по API уведомлений, а также [Уведомление Пользователь 2 учебного класса.