56

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.

MaxPlankton
  • 1,158
  • 14
  • 28
abh22ishek
  • 2,631
  • 4
  • 27
  • 47

7 Answers7

72

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);
Neo
  • 3,546
  • 1
  • 24
  • 31
dsharew
  • 10,377
  • 6
  • 49
  • 75
  • 3
    As the doc says, `FLAG_INCLUDE_STOPPED_PACKAGES` is implicit by default – Louis CAD May 09 '16 at 21:17
  • It doesn't work if application is removed from background in Xiaomi – Kanchan Chowdhury Jan 25 '17 at 10:57
  • 10
    It only work if I changed `new ComponentName("com.pkg.AppB","com.pkg.AppB.MainActivity"));` to `new ComponentName("com.pkg.AppB","com.pkg.AppB.MyBroadcastReceiver"));`, which `MyBroadcastReceiver` is the class name of this receiver. – 林果皞 May 08 '17 at 11:26
  • yeah it seems I have a copy/paste error. I will check it thanks though – dsharew May 08 '17 at 11:52
  • 1
    @Kanchan Chowdhury In OEMS like Xiomi, Gionee: Apps are forced stopped when removed from recent, so by doing that all the broadcasts and services are removed and destroyed. It won't get up until the user opens the app again. – Sarthak Sharma Jun 13 '19 at 07:47
  • Not Working on Android 10 – Hitesh Sahu Nov 11 '19 at 14:20
  • It's not working if receiver app has build flavor implemented – N J Mar 30 '23 at 07:45
13

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);
    }
}
Flot2011
  • 4,601
  • 3
  • 44
  • 61
  • 3
    If you listen to the receiver in MainActivity, there is no point in having it in the manifest. – android developer Jun 06 '19 at 11:51
  • 1
    There's no need to put it in the manifest. P.S. I found that the broadcastReceiver didn't trigger when it was supposed to be registered in the manifest. – Someone Somewhere Jun 24 '19 at 10:36
  • You need to register in activity again if SDK version is OREO or above. Implicit broadcast is not allowed to register in manifest any more. – steven Aug 29 '19 at 10:56
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

abhishesh
  • 3,246
  • 18
  • 20
1

MyReceiver is class not object. Create

myReceiver = new MyReceiver(); 

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

registerReceiver(myReceiver,intentFilter);
D.J
  • 1,439
  • 1
  • 12
  • 23
d.k.
  • 415
  • 4
  • 16
  • have you corrected this line if(MyReceiver!= null) unregisterReceiver(MyReceiver); to unregisterReceiver(myReceiver); In OnDestroy – d.k. Nov 03 '15 at 07:00
  • Please give some more information about your answer, so other users can use it in the future as well. – Jordumus Nov 07 '17 at 14:35
0

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

            }

            }
       }
Jro
  • 466
  • 2
  • 6
  • 14
  • My app A is a service which is always active. App B only need to response to the broadcast if it is active only. – Jro Oct 15 '20 at 04:56
0

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)

bibangamba
  • 1,463
  • 1
  • 19
  • 23
0

using this you can make a broadcast to any app (I made this for the system app also) if you like u can add any permission.

ex: put the below code button inside app A

    Intent intentT = new Intent();
    intentT.setAction("com.android.example.A");
    intentT.putExtra("state", "1");
    sendBroadcast(intentT);
    

Create a class inside app 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}}}

inside app 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>

Thank you.

zpvk
  • 124
  • 1
  • 10