How to Send BroadCast from one app to another app

I have App A and App B. In App A I 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.


Solution 1:

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

Solution 2:

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

Solution 3:

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