【问题标题】:Using a broadcast intent/broadcast receiver to send messages from a service to an activity使用广播意图/广播接收器将消息从服​​务发送到活动
【发布时间】:2011-11-08 17:52:27
【问题描述】:

所以我了解(我认为)广播意图和接收消息给他们。

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

如何向活动发送消息?

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

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

汤姆

【问题讨论】:

  • 抱歉“发送消息”=“在我的活动中使用参数运行函数”。

标签: android android-intent broadcastreceiver


【解决方案1】:

已编辑更正了注册/注销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...,如我的示例所示。这有助于避免其他应用或系统组件可能会尝试处理它。

【讨论】:

  • “这会阻止其他应用程序或系统组件处理它。” - 并不真地。 setPackage() 以这种方式运行,尽管这对 Intent 来说相对较新。否则,任何人都可以监听自定义操作,因为它们只是字符串。有一点隐蔽的安全性,使用自定义操作字符串在很大程度上消除了意外跨应用聊天。
  • @CommonsWare:“有一些隐蔽的安全性,使用自定义操作字符串在很大程度上消除了意外的跨应用聊天” - 对不起,我理解你在那里说的所有话,但你的句子使没有意义。也许我应该说“......可能有助于防止......”。同样在您的回答中,您说“无意冒犯,但您的问题仍然含糊不清。”....如果您遵循 Thomas 的原始问题,这可能会有所帮助。我做到了,而且我对托马斯正在寻找的东西有了基本的了解。不是说我是对的,但我花时间关注了一些话题。
  • “如果您关注 Thomas 的原始问题可能会有所帮助”——如果 Thomas 想让人们阅读原始问题,Thomas 会链接到它。
  • 这正是我想要的,谢谢 MisterSqonk。只是为了澄清问题-我的最后一个问题有点晦涩,我想从上一个问题的新问题开始重新开始,但我认为链接到我的最后一个问题只会使事情变得混乱。非常感谢 MisterSquonk,因为您已经成功地理解了跨线程。 :)
  • @Thomas:很高兴能提供帮助 - 我很感激你不想链接回来,但我有时会查看其他线程,只是为了了解人们正在寻找什么。祝你好运。 :)
【解决方案2】:

无意冒犯,但您的问题仍然含糊不清。因此,我将概述一大堆场景,并希望其中一个能够真正解决您认为遇到的任何问题。

场景 A:只有 Activity

​​>

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

场景 B:Activity If In Foreground, Else Other;有序广播

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

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

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

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

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

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

如果您在想“但是,如果我的进程在广播和其他进入前台的活动之间终止怎么办?”那么您的广播确实正在更新您的数据模型,根据这个场景的开头段落。

如果您正在考虑“但是,我想更新正在后台工作的活动”,那么相关活动已损坏。活动不应该在后台进行。这项工作应该委托给某种形式的服务,并且有一整套相关的场景用于向服务广播。

【讨论】:

  • 这一切都非常有趣且非常有用。答案打勾去了 MisterSquonk,因为他提供了代码并设法解决了我遇到的实际问题。然而,这是非常好的信息。谢谢。
【解决方案3】:

广播意图:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多