使用广播意图/广播接收器从服务向活动发送消息



所以我理解(我认为(广播意图和接收消息。

所以现在,我的问题/我不能解决的是如何从接收器的onReceive方法向活动发送消息。假设我有一个这样的接收器:

public class ReceiveMessages extends BroadcastReceiver 
{
@Override
   public void onReceive(Context context, Intent intent) 
   {    
       String action = intent.getAction();
       if(action.equalsIgnoreCase(TheService.DOWNLOADED)){    
           // send message to activity
       }
   }
}

如何向活动发送消息?

我是否必须在要向其发送消息的活动中实例化接收器并以某种方式监视它?还是怎样我理解这个概念,但不是真正的应用程序。

任何帮助都会非常棒,谢谢。

Tom

已编辑更正了注册/注销BroadcastReceiver的代码示例,还删除了清单声明。

ReceiveMessages定义为Activity中的内部类,该类需要侦听来自Service的消息。

然后,声明类变量,例如…

ReceiveMessages myReceiver = null;
Boolean myReceiverIsRegistered = false;

onCreate()中使用myReceiver = new ReceiveMessages();

然后在onResume()。。。

if (!myReceiverIsRegistered) {
    registerReceiver(myReceiver, new IntentFilter("com.mycompany.myapp.SOME_MESSAGE"));
    myReceiverIsRegistered = true;
}

在CCD_ 9中。。。

if (myReceiverIsRegistered) {
    unregisterReceiver(myReceiver);
    myReceiverIsRegistered = false;
}

Service中创建并广播Intent。。。

Intent i = new Intent("com.mycompany.myapp.SOME_MESSAGE");
sendBroadcast(i);

仅此而已。使"操作"对于您的包/应用程序是唯一的,即com.mycompany...,如我的示例所示。这有助于避免其他应用程序或系统组件可能试图处理它的情况。

无意冒犯,但你的问题仍然非常模糊。所以,我将概述一大堆场景,并希望其中一个能真正解决你认为的任何问题。

场景A:仅活动

如果您只需要在前台有活动时接收广播,请让活动使用registerReceiver()注册BroadcastReceiver。正如@MisterSquonk所指出的,您将在onResume()中注册接收器,并在onPause()中注销它。

场景B:活动如果在前景,其他;有序广播

如果您希望前台活动处理广播,但如果该活动不在前台(例如,引发Notification(,并且广播是有序广播(例如,传入SMS(,则您仍将使用场景a解决方案,但使用更高优先级的IntentFilter(请参阅setPriority()(。此外,您可以通过清单中的<receiver>元素注册BroadcastReceiver,对于同一广播,<intent-filter>的优先级较低。在活动的BroadcastReceiver中,调用abortBroadcast()以使用该事件,并阻止它到达已注册的清单BroadcastReceiver

场景C:活动如果在前景,其他;定期广播

如果场景B几乎适合,但你正在收听的广播不是有序广播,你需要从场景B开始。然而,按照@MisterSquonk的建议,使用私人操作字符串,让两个接收器在各自的过滤器中都有自己的广播。此外,在清单中注册另一个BroadcastReceiver,其<intent-filter>用于您正在收听的真实广播。该接收器将简单地调用sendOrderedBroadcast()来发送其他接收器正在收听的有序广播

场景D:不考虑前景的活动

如果你的一些活动需要了解广播,而它是否在前台并不重要,你需要重新思考你的意思。通常,这确实意味着广播在某种程度上影响了您的数据模型,在这种情况下,您应该而不是让活动知道,而是更新数据模型,并使用您已经存在的"让活动知道数据模型更改"逻辑来处理其余部分。

但是,如果您确信这不是数据模型的一部分,那么您可以实现场景B或场景C,并将一些信息粘贴到静态数据成员中。您的活动可以检查onResume()中的静态数据成员,以便在返回前台时获取有关广播的信息。

如果你在想"但是,如果我的流程在广播和其他活动之间终止怎么办?",那么根据本场景的开头一段,你的广播实际上是更新你的数据模型。

如果你在想"但是,我想更新一个正在后台工作的活动",那么有问题的活动就被破坏了。活动永远不应该在后台进行。这项工作应该委托给某种形式的服务,并且有一整套相关的场景用于向服务进行广播。

广播意图:

Intent intent = new Intent("com.yourcompany.testIntent");
intent.putExtra("value","test");
sendBroadcast(intent);

接收相同意图使用:

IntentFilter filter = new IntentFilter("com.yourcompany.testIntent");
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
              String value =  intent.getExtras().getString("value");
            }
        };
registerReceiver(receiver, filter);

在提出问题时可能不相关,但现在Android支持包中有LocalBroadcastManager。

与正常广播的工作方式几乎相同,但所有的"聊天"都是运行应用程序的本地内容。

优点:

  • 你知道你正在广播的数据不会离开你的应用程序,所以不需要担心泄露私人数据
  • 其他应用程序不可能将这些广播发送到您的应用程序,因此您不必担心它们会利用安全漏洞
  • 它比通过系统发送全球广播更有效

示例:

Intent i = new Intent("my.local.intent");
LocalBroadcastManager.getInstance(context).sendBroadcast(i);

并接收

receiver = new MyBroadcastReceiverToHandleLocalBroadcast();
IntentFilter i = new IntentFilter();
i.addAction("my.local.intent");
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, i);

最新更新