使用localbroadcastmanager sendorderedbroadcast的组合发送广播

时间:2012-12-18 20:30:29

标签: android service broadcastreceiver commonsware

我想在这篇博文中实现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 个答案:

答案 0 :(得分:10)

  

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

没有。 LocalBroadcastManager仅适用于使用LocalBroadcastManager单身人士注册的接收者。此外,LocalBroadcastManager不支持有序广播,最后我查了一下。

  

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

只要您未在清单中的<intent-filter>上使用BroadcastReceiver,因此使用明确的Intent作为广播本身,您的广播将只会被你自己和管理广播的操作系统。其他应用程序将无法监视它。

答案 1 :(得分:3)

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

一般的想法是:

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

    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实现有序广播!

答案 2 :(得分:1)

我知道你想要实现以下目标:

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

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

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

希望它有所帮助。

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

答案 3 :(得分:-2)

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

如果在后台发生事件,我不赞成更新活动。用户可能已在Activity中执行其他操作。在我看来,通知就足够了;它始终可见并保持不变,直到用户解雇它。 Gmail和Gcal的工作方式如下;如果有新邮件,Gmail不会更新当前屏幕。如果您想知道当用户已经在应用程序中时如何处理用于处理通知的任务流,请参阅Notifications API指南以及[通知用户2培训课程。