In this tutorial, we’ll discuss the changes in Broadcast Receiver since Android Oreo. We’ll see why the restrictions have been put on Background Operations in Android.
Androd Broadcast Receivers
Broadcast Receivers are like Antennas. Just like Antennas can be tuned to catch certain frequencies, broadcast receivers can be registered to certain intent actions. When that action event triggers, the BroadcastReceiver gets called.
Implicit vs Explicit BroadcastReceivers
Before we differentiate, let’s know the difference between Implicit and Explicit Intents.
Explicit Intents are used to call a particular component that you know of.
Implicit Intents are used when you don’t know the exact component to invoke.
Take the example of capturing a photo from camera or gallery. It’s an implicit intent, since calling the intent shows you a dialog of different applications to choose from. Same goes for email/browser intents (if they show you a dialog chooser).
Implicit Broadcast Receivers aren’t exclusive to your application.
Actions such as ACTION_BOOT_COMPLETED
or CONNECTIVITY_CHANGE
are categorised in implicit broadcast receivers. This is because when these events happen, all the applications registered with the event will get the information.
Explicit Broadcast Receivers are exclusive to your application. Only your application’s broadcast receiver will get triggered when the custom intent action you define, gets called.
Handling Android Oreo Broadcast Receivers
Now, broadcast receivers run in the background. Hence it drains the battery. Imagine every application has registered android.net.conn.CONNECTIVITY_CHANGE
in the receiver which is implicit.
Now, whenever the wifi/mobile internet connection toggles, all the applications, with the receiver would get triggered. Imagine what happens when your wifi router is unstable. It can cause battery issues.
AndroidManifest.xml
How to handle Implicit Receivers in Android Oreo?
To use Implicit Receivers in your application, you need to define them programmatically in your code, using registerReceiver()
.
Using registerReceiver()
we can programmatically register and unregisterReceiver()
during the lifecycle of the activity. This way implicit receivers would only be called when our activity/application is alive and not at other times.
Besides registering receivers programmatically, we can use JobSchedulers
too.
Several Implicit Broadcasts are exempted and can be declared in the Manifest:
Note: Beginning with Android Pie, The NETWORK_STATE_CHANGED_ACTION
broadcast doesn’t receive information about the user’s location or personally identifiable data.
In the next section, we’ll be creating an application which implements Broadcast Receivers keeping the Android Oreo limitations.
Project Structure
Code
The AndroidManifest.xml file looks like the following:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
package="com.journaldev.androidoreobroadcastreceiver">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<receiver android:name="com.journaldev.androidoreobroadcastreceiver.MyReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.journaldev.AN_INTENT" />
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
We’ve defined an intent filter with an action which is explicit.
Implicit ones will be defined in the code only:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<Button
android:id="@+id/btnExplicitBroadcast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Explicit Broadcast" />
</LinearLayout>
The code for the MainActivity.java class is given below:
package com.journaldev.androidoreobroadcastreceiver;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btnExplicitBroadcast;
MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnExplicitBroadcast = findViewById(R.id.btnExplicitBroadcast);
btnExplicitBroadcast.setOnClickListener(this);
myReceiver= new MyReceiver();
}
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(myReceiver, filter);
}
public void broadcastIntent() {
Intent intent = new Intent();
intent.setAction("com.journaldev.AN_INTENT");
intent.setComponent(new ComponentName(getPackageName(),"com.journaldev.androidoreobroadcastreceiver.MyReceiver"));
getApplicationContext().sendBroadcast(intent);
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(myReceiver);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnExplicitBroadcast:
broadcastIntent();
break;
}
}
}
On button click sendBroadcast()
is called to send the explicit broadcast.
Note: sendStickyBroadcasts()
were used to send broadcast intents that stayed around for other receivers to access them at a later point. The method was deprecated in API 21.
The code for the MyReceiver.java
BroadcastReceiver class is given below:
package com.journaldev.androidoreobroadcastreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("com.journaldev.AN_INTENT")) {
Toast.makeText(context, "Explicit Broadcast was triggered", Toast.LENGTH_SHORT).show();
}
if (("android.net.conn.CONNECTIVITY_CHANGE").equals(action)) {
Toast.makeText(context, "Implicit Broadcast was triggered using registerReceiver", Toast.LENGTH_SHORT).show();
}
}
}
The output of the above application in action is given below:
LocalBroadcastManager
A LocalBroadcastManager
is used to send or receive events locally within the current application only.
LocalBroadcastManager
does not listen to system-wide broadcasts and is more secure than BroadcastReceiver.
Plus it has a less overhead hence communication speed is faster.
It can be initialised as:
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
localBroadcastManager.sendBroadcast(intent);
LocalBroadcastManager would fail if you make events that are system wide.
<receiver android:name=".MyReciever"
android:permission="android.permission.SEND_SMS">
<intent-filter>
<action android:name="MY_ACTION"/>
</intent-filter>
</receiver>
sendBroadcast(new Intent("MY_ACTION"), Manifest.permission.SEND_SMS);
Set the android:exported
attribute to “false” in the receiver tag in the manifest restricts the application from receiving broadcasts from other applications.
This brings an end to this tutorial. You can download the project from the below link:
Anupam, Good day. i read regards to your broadcast receiver, I am currently developing to load content from either primary url. and will switch to secondary url if primary failed. can you advise me how can the local broadcast manager for oreo can help. my system is running on 8.
Hai, Broadcast receiver work only our app in the foreground, how can trigger a broadcast receiver after reboot in android oreo and pie can you help me.
I will make a new Android application. How to to auto launch it as soon as the mobile is plugged into charging?
If this is successfully done, then the application will be opened automatically when the charger is plugged to the mobile phone.
Is there any of the sample test code existing ? My requirement are app running in the truck driver cabin, when ever the drive start the vehicle mobile get charged as soon as app should launch.
Thanks In advance.
This is very simple code. But its not any advantage, because its not work after oreo versions after app closed.
I have been trying to do a simple SMS app to will toast a message when it is received. can you help?
Here is my receiver class
Please help me to make the app toast messages when they arrived
Thanks