简体   繁体   中英

How to Send BroadCast from one app to another app

I have App A and App B. In App AI want to send broadcast to App B. This is the code for App 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);

And in App B - In MainActivity , I have MyBroadCastReceiver Class.

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

I am getting the error - Receiver is not registered .

First thing first declare the receiver in app B in the manifest file like this:

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

when sending the broadcast add FLAG_INCLUDE_STOPPED_PACKAGES flag to the intent [src] because when you broadcast from app A to app B , app B might not be running, this flag insures that the broadcast reachs out even apps not running:

FLAG_INCLUDE_STOPPED_PACKAGES flag is added to the intent before it is sent to indicate that the intent is to be allowed to start a component of a stopped application.

intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

In your case it will be like this:

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

In App A: Send the broadcast here.

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

In App B manifest

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

In App B MainActivity: register the receiver oncreate(), and unregister 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);
       }
  }

In App B BroadcastReceiver

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

There may be two cases :

  1. Your appB is not running, hence the activity is not instantiated, and so the receiver is not registered.
  2. Your activity is destroyed, means that you have unregistered your receiver that you registered via registerReceiver() in onCreate()

Solution :

Register your broadcast receiver in manifest.

Inside manifest of appB :

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

And comment out the line in appA

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

Write the logic in MyBroadcastReceiver to display relevant data/launch new activity

MyReceiver is class not object. Create

myReceiver = new MyReceiver(); 

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

registerReceiver(myReceiver,intentFilter);

If this helps some one and it works for me

In App A in activity or in a content provider-

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

In App B in the manifest

      <receiver
        android:name=".DbaseChanged"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="Updated" />
        </intent-filter>
      </receiver>

In App B Broadcast receiver class-

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

            }

            }
       }

I needed to call setPackage("package_name") to ensure explicitness when I registered the broadcast receiver in the Manifest. I was then able to receive the data even if the app was closed completely.

// 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>

I didn't need to add intent.setPackage(package_name) when registering the receiver via an activity, but this also meant that I couldn't get the data if the activity was destroyed (app closed, app in background for long period)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM