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

Tho*_*son 47 android broadcastreceiver android-intent

所以我理解(我认为)关于广播意图和接收消息给他们.

所以现在,我的问题/我无法解决的问题是如何从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
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

我如何向活动发送消息?

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

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

汤姆

Squ*_*onk 71

EDITED更正了注册/取消注册BroadcastReceiver和删除清单声明的代码示例.

定义ReceiveMessagesActivity需要监听来自的消息的内部类Service.

然后,声明类变量,如...

ReceiveMessages myReceiver = null;
Boolean myReceiverIsRegistered = false;
Run Code Online (Sandbox Code Playgroud)

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

然后在onResume()......

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

......并onPause()......

if (myReceiverIsRegistered) {
    unregisterReceiver(myReceiver);
    myReceiverIsRegistered = false;
}
Run Code Online (Sandbox Code Playgroud)

Service创作和播出Intent......

Intent i = new Intent("com.mycompany.myapp.SOME_MESSAGE");
sendBroadcast(i);
Run Code Online (Sandbox Code Playgroud)

这就是它.使"动作"对您的包/应用程序来说是唯一的,即com.mycompany...在我的示例中.这有助于避免其他应用程序或系统组件可能尝试处理它的情况.


Com*_*are 68

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

场景A:仅活动

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

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

如果您希望前台活动处理广播,但如果该活动不在前台(例如,提高a Notification),并且广播是有序广播(例如,传入短信),则您希望发生其他事情,那么您会仍然使用Scenario A解决方案,但具有更高优先级IntentFilter(请参阅参考资料setPriority()).此外,你会注册一个BroadcastReceiver通过<receiver>在manifest元素,具有较低的优先级<intent-filter>为同一广播.在活动中BroadcastReceiver,调用abortBroadcast()以消耗事件并阻止它到达清单注册的事件BroadcastReceiver.

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

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

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

如果您的某些活动需要了解广播,并且它是否在前台并不重要,您需要重新考虑您的意思.通常情况下,这实际上意味着广播影响某种方式对你的数据模型,在这种情况下,你关注的应该不会是让活动的认识,而是更新数据模型,并使用已经存在的"让活动的了解数据模型改变"逻辑处理其余的.

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

如果您正在考虑"但是,如果我的进程在广播和前台的其他活动之间终止怎么办?"那么,根据此场景的开头段落,您的广播确实正在更新您的数据模型.

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

  • 这一切都非常有趣且非常有用.回答蜱给了MisterSquonk,因为他提供了代码并设法解决了我遇到的实际问题.然而,这是非常好的信息.谢谢. (5认同)

Ale*_*exA 19

广播意图:

Intent intent = new Intent("com.yourcompany.testIntent");
intent.putExtra("value","test");
sendBroadcast(intent);
Run Code Online (Sandbox Code Playgroud)

要获得相同的意图用途:

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);
Run Code Online (Sandbox Code Playgroud)


Kuf*_*ffs 8

在询问问题时可能不相关,但现在Android支持包中有LocalBroadcastManager.

与普通广播的工作方式几乎相同,但所有"聊天"都是其运行的应用程序的本地.

好处:

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

例:

Intent i = new Intent("my.local.intent");
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
Run Code Online (Sandbox Code Playgroud)

并接受

receiver = new MyBroadcastReceiverToHandleLocalBroadcast();

IntentFilter i = new IntentFilter();
i.addAction("my.local.intent");
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, i);
Run Code Online (Sandbox Code Playgroud)