如何从一个应用程序向另一个应用程序发送广播

56

我有应用程序A和B。在应用程序A中,我想向应用程序B发送广播。 这是应用程序A的代码:

final Intent intent = new Intent();
intent.setAction("com.pkg.perform.Ruby");
intent.putExtra("KeyName", "code1id");
intent.setComponent(new ComponentName("com.pkg.AppB", "com.pkg.AppB.MainActivity"));
sendBroadcast(intent);

在应用程序B中的MainActivity中,我有一个名为MyBroadCastReceiver的类。

public class MainActivity extends Activity {
    private MyBroadcastReceiver MyReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Receive broadcast from External App
        IntentFilter intentFilter = new IntentFilter("com.pkg.perform.Ruby");
        MyReceiver = new MyBroadcastReceiver();
        if(intentFilter != null)
        {
            registerReceiver(MyReceiver, intentFilter);
        }
    }

    public class MyBroadcastReceiver extends BroadcastReceiver
    {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(MainActivity.this, "Data Received from External App", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(MyReceiver != null)
            unregisterReceiver(MyReceiver);
    }
}

我遇到了这个错误 - 接收器未注册


两个应用程序都在运行吗? - ρяσѕρєя K
尝试这个答案:https://dev59.com/SmHVa4cB1Zd3GeqPoJjw#9729172 - Muhammad Waleed
我已经阅读了那些链接。 - abh22ishek
2
应用程序B是在XML中声明广播接收器还是通过代码注册/删除它?如果是后者,那么很可能是因为应用程序B已经删除了接收器,因为其活动已被销毁。 - Kai
onCreate 中的代码看起来不正确,请重新检查并发布正确的代码。 - Rahul Tiwari
显示剩余6条评论
7个回答

73

首先,在应用程序B的清单文件中声明接收器,如下所示:

<receiver android:name=".MyBroadcastReceiver"
    android:enabled="true"
    android:exported="true">
        <intent-filter>
          <action android:name="com.pkg.perform.Ruby" />
        </intent-filter>
</receiver>

在发送广播时,要向Intent添加FLAG_INCLUDE_STOPPED_PACKAGES标志[src],因为当您从应用A广播到应用B时,应用B可能没有运行,这个标志确保广播传达到即使未运行的应用程序:

在发送Intent之前,向其添加FLAG_INCLUDE_STOPPED_PACKAGES标志,以指示该Intent将允许启动已停止应用程序的组件。

intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

在您的情况下,它将是这样的:

    final Intent intent=new Intent();
    intent.setAction("com.pkg.perform.Ruby");
    intent.putExtra("KeyName","code1id");
    intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
    intent.setComponent(  
        new ComponentName("com.pkg.AppB","com.pkg.AppB.MyBroadcastReceiver"));  
    sendBroadcast(intent);

3
根据文档所述,“FLAG_INCLUDE_STOPPED_PACKAGES”默认是隐式的。 - Louis CAD
10
只有当我将 new ComponentName("com.pkg.AppB","com.pkg.AppB.MainActivity")) 改为 new ComponentName("com.pkg.AppB","com.pkg.AppB.MyBroadcastReceiver")) 时,它才能生效。其中 MyBroadcastReceiver 是这个接收器的类名。 - 林果皞
是的,看起来我复制/粘贴出现了错误。我会检查一下,谢谢。 - dsharew
1
在像小米、金立这样的OEMS中:当应用程序从“最近使用”的列表中移除时,它们会被强制停止,因此所有的广播和服务都会被删除和销毁。除非用户再次打开该应用程序,否则它将无法重新启动。 - Sarthak Sharma
无法在Android 10上工作 - Hitesh Sahu
显示剩余2条评论

13
在应用程序A中:将广播发送到此处。
 final Intent i= new Intent();
 i.putExtra("data", "Some data");
 i.setAction("com.pkg.perform.Ruby");
 i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
 getApplicationContext().sendBroadcast(i);

在应用 B 的清单文件中

 <receiver  android:name=".MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.pkg.perform.Ruby" />
            </intent-filter>
        </receiver>
在App B的MainActivity中:在onCreate()方法中注册广播接收器,在onDestroy()方法中取消注册。
 public class MainActivity extends AppCompatActivity
 {
      private MyBroadcastReceiver MyReceiver;

       @Override
       protected void onCreate(Bundle savedInstanceState)
       {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            MyReceiver = new MyBroadcastReceiver();
            IntentFilter intentFilter = new IntentFilter("com.pkg.perform.Ruby");
            if(intentFilter != null)
            {
               registerReceiver(MyReceiver, intentFilter);
            }
       }

       @Override
       protected void onDestroy()
       {
           super.onDestroy();
           if(MyReceiver != null)
               unregisterReceiver(MyReceiver);
       }
  }

在应用程序 B 中的广播接收器

public class MyBroadcastReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        String data = intent.getStringExtra("data");
        Log.i("BR" ,"Data received:  " + data);
    }
}

3
如果你在MainActivity中监听接收器,那么在清单文件中声明它就没有意义了。 - android developer
1
不需要将其放在清单中。顺便说一句,我发现当广播接收器应该在清单中注册时,它并没有触发。 - Someone Somewhere
如果SDK版本是OREO或更高版本,则需要重新注册活动。隐式广播不再允许在清单中注册。 - steven

3

可能有两种情况:

  1. 您的appB未运行,因此活动未实例化,因此接收器未注册。
  2. 您的活动已被销毁,这意味着您已经取消注册通过onCreate()注册的接收器。

解决方案:

在清单文件中注册广播接收器。

在appB的清单文件中:

<receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="com.pkg.perform.Ruby" />
    </intent-filter>
</receiver>

在appA中注释掉该行代码

intent.setComponent(new ComponentName("com.pkg.AppB","com.pkg.AppB.MainActivity"));

编写MyBroadcastReceiver中的逻辑以显示相关数据/启动新活动


Activity B 运行良好,没有任何问题。 - abh22ishek
你尝试过使用清单注册的接收器并注释掉setComponent部分吗? - abhishesh
好的,现在它可以工作了。我忘记注释设置组件语句了。这是个愚蠢的错误。 - abh22ishek
有人能帮我完成最后一步吗?我在应用程序B中收到了内容,现在我想将它与一些额外的内容发送回应用程序A。 - AMIT

1

MyReceiver 是一个类而不是对象。创建

myReceiver = new MyReceiver(); 

and put...........

registerReceiver(myReceiver,intentFilter);

你已经更正了这一行代码吗? if(MyReceiver!= null) unregisterReceiver(MyReceiver); 应更改为 unregisterReceiver(myReceiver); 在OnDestroy函数中。 - d.k.
请提供关于您答案的更多信息,以便其他用户将来也可以使用它。 - Jordumus

0
如果这对某人有帮助并且对我有效,
在应用程序A中的活动或内容提供者中-
  Intent intent = new Intent("Updated");
  intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
  intent.setComponent (new
  ComponentName "com.exam.appA",
  "com.exam.appA.DbaseChanged"));
  getContext().sendBroadcast(intent);

在清单文件中的应用程序B中。
      <receiver
        android:name=".DbaseChanged"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="Updated" />
        </intent-filter>
      </receiver>

在应用程序B中的广播接收器类-

    public class DbaseChanged extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent
     intent)   {

           String act = intent.getAction();
           if(act != null && act.equals("Updated")  )
            {
                Toast.makeText(context, act ,
              Toast.LENGTH_SHORT).show();

            }

            }
       }

我的应用程序A是一个一直处于活动状态的服务。只有当应用程序B处于活动状态时,才需要对广播做出响应。 - Jro

0

我需要调用setPackage("package_name")来确保在清单文件中注册广播接收器时的显式性。这样,即使应用程序完全关闭,我也能够接收数据。

// sending app sends broadcast
Intent intent = new Intent(ACTION_RECOMMEND);
intent.putExtra(LISTEN_RECOMMENDATION, "Triggered - Jhene Aiko");
intent.putExtra(WATCH_RECOMMENDATION, "Goblin - Kim Go-eun");
intent.setPackage("com.example.package.receiverapp");
sendBroadcast(intent);


//receiving app manifest registers receiver
<receiver
   android:name=".ManifestRegisteredBroadcastReceiver"
   android:exported="true">
   <intent-filter>
       <action android:name="com.random.action.RECOMMEND" />
   </intent-filter>
</receiver>

在通过活动注册接收器时,我不需要添加intent.setPackage(package_name),但这也意味着如果活动被销毁(应用程序关闭、长时间后应用程序在后台运行),我将无法获取数据。

0
使用此功能,您可以向任何应用程序进行广播(我也为系统应用程序制作了此功能),如果您喜欢,可以添加任何权限。
例如:将以下代码按钮放置在应用程序A中。
    Intent intentT = new Intent();
    intentT.setAction("com.android.example.A");
    intentT.putExtra("state", "1");
    sendBroadcast(intentT);
    

创建一个类在应用程序B内。
public class test extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals("com.android.example.A")) {
          //Do whatever you want}}}

在应用程序b的AndroidManifest.xml内部

    <receiver android:name=".test"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.android.example.A" />
        </intent-filter>
    </receiver>

谢谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接