7

我想实现 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

4 回答 4

11

我很好奇是否调用 LocalBroadcastManager.getInstance(UnzipService.this).sendBroadcast(broadcast); 服务内部仍然会被您在清单中定义的类型的广播接收器接收。

不,仅适用于在单例本身LocalBroadcastManager注册的接收器。LocalBroadcastManager而且,LocalBroadcastManager不支持有序广播,上次我查了一下。

我想做的是使用 LocalBroadcastManager 因为来自我的服务的广播不一定需要在系统范围内看到,如果可能的话我宁愿将它们保密

只要您没有<intent-filter>BroadcastReceiver清单中使用 an ,因此使用显式Intent作为广播本身,您的广播只会被您自己和管理广播的操作系统的位看到。其他应用程序将无法监视它。

于 2012-12-18T20:38:55.903 回答
3

如果您只有 2 个可能处理您的广播的对象(在您的情况下是一个 Activity 和一个通知控制器),您可以仅使用 LocalBroadcastManager 实现有序广播的行为。

总体思路是:

  1. 设置您的服务,以便在您想要显示结果时通过特定操作向您的 Activity 广播 Intent
  2. 在您的 Activity 中创建一个处理您的服务结果 Intent 的 BroadcastReceiver,并使用步骤 1 中的操作在 LocalBroadcastManager 上使用 IntentFilter 注册它
  3. 在您的服务中,当结果可用时,尝试使用 LocalBroadcastManager.getInstance(Context).sendBroadcast(Intent) 发送结果 Intent,此方法返回一个布尔值,指示广播是否已发送到至少一个接收器。如果此布尔值为 false,则表示您的 Activity 没有处理您的广播,您应该改为显示通知。

在您的服务中:

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 实现有序广播的人有所帮助!

于 2015-03-04T21:52:28.023 回答
1

我了解您希望实现以下目标:

“我有一个在后台发生的事件。如果活动在屏幕上,我想更新我的活动。否则,我想发出通知。” (@TheCommonsBlog)

您可以通过实现 ResultReceiver 来实现此行为。示例Restful API 服务http://itekblog.com/background-processing-with-intentservice-class/

您基本上所做的是在您的 Activity 中实例化一个 ResultReceiver 并通过意图将其像 Parcelable 参数一样传递给服务。然后,每次您的服务更新 UI 时,服务都会验证 ResultReceiver 对象是否为 NULL。如果不为 NULL,则通过 onReceiveResult 接口更新 Ui。否则,您提出通知。当您的活动关闭时,请确保将服务上的 ResultReceiver 设置为 NULL。

希望能帮助到你。

PS:IMO,广播工作量太大,难以控制。

于 2012-12-18T20:44:40.040 回答
-2

使用 LocalBroadcastManager,广播变得易于使用。

如果后台发生事件,我不赞成更新 Activity。用户可能已经在 Activity 中执行其他操作。在我看来,通知就足够了;它始终可见并一直存在,直到用户将其关闭。Gmail 和 Gcal 是这样工作的;如果有新邮件进来,Gmail 不会更新当前屏幕。如果您想知道当用户已经在应用程序中时如何处理处理通知的任务流程,请参阅Notifications API 指南以及 [Notifying The用户2培训班。

于 2012-12-18T21:10:00.000 回答