【问题标题】:How to send a custom broadcast action to receivers in manifest?如何在清单中向接收者发送自定义广播操作?
【发布时间】:2020-10-13 14:02:32
【问题描述】:

MyReceiver.java

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.i("MyReceiver", "MyAction received!");
    }
}

AndroidManifest.xmlapplication 标签下)

<receiver android:name=".MyReceiver">
    <intent-filter>
        <action android:name="MyAction" />
    </intent-filter>
</receiver>

MainActivity.Java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sendBroadcast(new Intent("MyAction"));
    }
}

MyReceiver.onReceive 方法永远不会被触发。 我错过了什么吗?

【问题讨论】:

  • 您无法在 Android 8.0+ 的清单中为大多数 Intent 操作注册接收器。您在哪个版本的 Android 上进行测试?另外,如果MainActivityMyReceiver 在同一个应用程序中,对于进程内消息有更好的选择,例如LocalBroadcastManager、greenrobot 的 EventBus、基于 RxJava 的事件总线等。
  • 我使用的是 Android 8。是的,它们在同一个应用程序中。即使有很多图书馆,我也想知道BroadcastReceiver 是如何工作的。此外,我不想以编程方式声明我的接收器,因为MyReceiver 将在其intent-filter 标记中包含一些系统操作。我真的希望它在清单中声明(只要可能)。
  • Android 打破这个功能很痛苦。我的用例是这样的——我有一个有多种风格的应用程序。有些风格需要知道应用程序何时更新,以便他们可以相应地更新他们的数据库。更新应用程序版本的代码希望将更新广播到可能会或可能不会在清单中注册的接收器,具体取决于风味。 Rx & eventbus 将不起作用,因为代码必须已经在运行才能注册侦听器。 BR 的美妙之处在于能够通过在清单中静态注册代码来调用代码。

标签: android broadcastreceiver android-manifest android-broadcast


【解决方案1】:

我使用的是 Android 8。

那你得用一个显式的Intent,用来标识接收者,比如:

sendBroadcast(new Intent(this, MyReceiver.class).setAction("MyAction"));

请参阅 Android 8 版本文档中的 Broacast limitations

【讨论】:

  • 不可能只使用action?如果我有多个接收器要触发。为什么Android限制了它的广播系统?它在其文档中的什么地方谈到了它?
  • @Yairopro:“不可能只使用动作?” -- 在 Android 8.0+ 上,是的,至少对于您还打算用于其他广播的接收器而言。请参阅the documentation 了解更多信息。
  • @ChRoNoN:Android 中只有少数 IPC 机制。如果您需要在应用程序内跨进程边界进行对话,则可以向特定接收者“广播”。这不是一个特别常见的需求,对于进程内使用,我在对该问题的评论中概述了许多其他选项。
  • @ChRoNoN 动作,顾名思义,告诉接收者它应该做什么。
  • @AJW:我不知道你指的是哪个JsonObject。将对象转换为 JSON 字符串是相当常见的。我倾向于使用 Moshi,它被 in the very first section of the README 覆盖。获得 JSON 字符串后,您可以将其作为查询参数放在 URL 上,就像任何其他字符串或数字一样。
【解决方案2】:

在 Android 8 版本中

  • 我们需要提供显式类来处理,即 setcomponent 参数和操作

例子:

  private void triggerBroadCast(String firstFavApp, String secondFavApp) {
        Intent intent = new Intent("FavAppsUpdated");
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
        intent.putExtra("FIRST_FAV_APP", firstFavApp);
        intent.putExtra("SECOND_FAV_APP", secondFavApp);
        intent.setComponent(new
                ComponentName("com.android.systemui",
                "com.android.systemui.statusbar.phone.FavAppsChanged"));

        Log.i(TAG, "Trigger Fav Apps" + firstFavApp + " " + secondFavApp);
        favouriteContract.getAppContext().sendBroadcast(intent);
    }

Android 8 以下

  • 只有动作就足够接收广播了

   void broadCastParkingStates(Context context) {
        Intent intent = new Intent("ReverseCameraStates");
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
        intent.putExtra("PARKING_GUIDE", ReverseCameraPreference.getParkingGuide(context));
        intent.putExtra("PARKING_SENSOR", ReverseCameraPreference.getParkingSensor(context));
        intent.putExtra("TRAJECTORY", ReverseCameraPreference.getTrajectory(context));
        Log.i("BootCompletedReceiver", "Sending Reverse Camera settings states BaordCast");
        Log.i("BootCompletedReceiver", "States Parking:Sensor:Trajectory="
                + intent.getExtras().getBoolean("PARKING_GUIDE")
                + ":" + intent.getExtras().getBoolean("PARKING_SENSOR")
                + ":" + intent.getExtras().getBoolean("TRAJECTORY")
        );
        context.sendBroadcast(intent);
    }

【讨论】:

  • 您的解决方案是否适用于使用同一应用程序的两个用户?我想看看是否有办法为用户 A 设置一个明确的意图,通过两者的默认 SMS 应用程序向用户 B 的应用程序中的 BroadcastReceiver 发送带有数据的 Intent?我能够使用需要 RECEIVE_SMS 权限的隐式意图进行设置,但现在该权限需要 Google Play 商店管理员的批准。
  • 刚刚检查过它也在应用程序内部工作谢谢
【解决方案3】:

如果您有多个接收者,您可以仅使用清单中定义的自定义操作向所有接收者发送广播,您需要在发送广播时添加以下标志

注意:我在Android 10上使用过adb测试,可以在应用中添加

FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000

adb shell am broadcast -a MyAction -f 0x01000000

【讨论】:

  • -f 标志让我能够在 Android 10 上进行测试
【解决方案4】:

在 Kotlin 中:

val intent = Intent(this, MyBroadCastReceiver::class.java)
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.action = "my.custom.broadcast"
sendBroadcast(intent)

【讨论】:

    【解决方案5】:

    修改MainActivity的代码如下:

    Intent intent = new Intent(this, MyReceiver.class);
    intent.setAction("MyAction");
    sendBroadcast(intent);
    

    【讨论】:

    • 此代码与 CommonsWare 的答案相同(仅分成 3 行)。请避免重复答案。
    【解决方案6】:

    字符串本身无所谓,只需要处处相同且唯一,我用的是常量的全限定名。

    <receiver android:name="com.mypackage.receivers.MyBroadcastReceiver">
        <intent-filter>
            <action android:name="com.mypackage.receivers.MyBroadcastReceiver.ACTION_CUSTOM"/>
        </intent-filter>
    </receiver>
    

    接收者:

    package com.mypackage.receivers;
    
    public class MyBroadcastReceiver extends BroadcastReceiver {
        public static final String ACTION_CUSTOM = "com.mypackage.receivers.MyBroadcastReceiver.ACTION_CUSTOM";
    @Override
        public void onReceive(Context context, Intent intent) {
          if (ACTION_CUSTOM.equals(intent.getAction())) {
                // do custom action
            }
        }
    }
    

    广播意图:

    sendBroadcast(new Intent(MyBroadcastReceiver.ACTION_CUSTOM));
    

    【讨论】:

    • 在 Android 8 上,您似乎无法再这样做了。
    • 确实,他们改成了奥利奥。
    猜你喜欢
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    • 2013-05-22
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多