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

时间:2011-09-01 21:05:37

标签: android android-intent broadcastreceiver

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

所以现在,我的问题/我无法解决的问题是如何从接收器的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
       }
   }
}

我如何向活动发送消息?

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

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

汤姆

4 个答案:

答案 0 :(得分:70)

已编辑更正了注册/取消注册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;
}

...并在onPause() ...

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

Service创建并广播Intent ...

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

就是这样。让“操作”对您的包/应用程序来说是唯一的,即com.mycompany...,如我的示例所示。这有助于避免其他应用程序或系统组件可能尝试处理它的情况。

答案 1 :(得分:68)

没有冒犯,但你的问题仍然模糊不清。所以,我将概述一堆乱七八糟的情景,并希望其中一个实际上能够解决你认为的任何问题。

场景A:仅活动

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

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

如果您希望前台活动处理广播,但如果该活动不在前台(例如,引发Notification),您希望发生其他事情,并且广播是有序广播(例如, ,传入短信),然后您仍然会使用方案A解决方案,但具有更高优先级IntentFilter(请参阅setPriority())。此外,您将通过清单中的BroadcastReceiver元素注册<receiver>,同一广播的优先级较低<intent-filter>。在活动的BroadcastReceiver中,请致电abortBroadcast()以使用该活动并阻止其访问您的清单注册BroadcastReceiver

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

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

情景D:无论前景如何的活动

如果您的某些活动需要了解广播,并且它是否在前台并不重要,您需要重新考虑您的意思。通常,这实际上意味着广播会以某种方式影响您的数据模型,在这种情况下,您应该让活动知道,而是更新您的数据模型,并使用您已经 - 现有的“让活动了解数据模型的变化”逻辑处理其余部分。

但是,如果您确信这不是数据模型的一部分,则可以实施方案B或方案C,并在静态数据成员中添加一些信息。您的活动可以检查onResume()中的静态数据成员,以便在广播返回到前台时获取有关广播的信息。

如果您正在考虑“但是,如果我的广告和其他活动在前台之间终止了会怎么样?”,那么您的广播确实 更新您的数据模型,打开这个场景的段落。

如果您正在考虑“但是,我想要更新正在后台工作的活动”,那么相关活动就会被破坏。活动永远不应该在后台工作。应该将这项工作委托给某种形式的服务,并且有一整套相关的场景来获得广播服务。

答案 2 :(得分:17)

播放意图:

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);

答案 3 :(得分:7)

在提出问题时可能不相关,但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);