Have you ever wondered what mechanism in Android used to listen for all the changes, the events of the system? System’s means of the operating system that is unrelated to the application.
Do you know why when you just turn on 3G or the Internet, facebook starts sending a bunch of notifications down to notifycation ? Exactly it uses Broadcast Receiver to do that for you.
That is why we will go to study today in this advanced android programming series, this article is quite good, so everyone remember to practice.
We will go and answer 4 questions: What? Why? When? How? again.
What is Broadcast Recieiver?
As one of the four major components in Android, the purpose is to listen to events, the system state is generated through the Intent so that developers can handle system events inside the application.
Broadcast Receiver can work even when the app is turned off, ie in the main background so it is often used with the service.
Why use Broadcast Receiver
It has many main uses, so depending on what the problem is, we will use it appropriately, but the highlight of the Broadcast Receiver is that it can run in the background as soon as the application is turned off.
When to use Broadcast Receiver
It is an application that needs to handle a certain job that depends on the system, only when the system issues an event or action that this work can be performed. Most of the time using Broadcast Receiver are: listen for network change events, listen to low battery events, listen to messages, incoming calls …
Another great use is to start the Service of the app in Broadcast Receiver.
How to use Broadcast Receiver
To subscribe to a listening event with Broadcast Receiver, we will have 2 most popular ways today, they are:
- Register in AndroidManifest.xml (Static)
- Register with Java code (Dynamic)
Either way, the handling of them is similar, but usually a way to be used more than that is the first way, used in AndroidMainifest, because when you set up here, the application there is no need to launch but can still listen to events and launch.
In general, depending on the requirements of the problem, we will have an appropriate way to use it, but when doing projects, we find that Broadcast is rarely used and if used, it will be used with Java code.
Method 1: Register in AndroidManifest.xml
This is how we declare Broadcast Receiver in Manifest and when you first launch the app it will subscribe to Broadcast and so it starts until you REMOVE the app. It still listens when you have turned off the app. Come on, this is the advantage of this registration.
We will create a class and extend from BroadcastReceiver to handle the events, I will describe a process as follows:
Now we are going to listen to an event when the Internet changes, which is when you turn on and off data (here it could be 3G, Wifi) it will say something like ” Network is turned ON / OF F ”.
OK, here’s the full declaration and processing.
Declared in AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tutorialspots.broadcast"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".NetworkChangeReceiver" > <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> </application> </manifest>
Above you notice in the 2 lines of code I added that is:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Since you want the app to listen for network state changes, you need to ask for permission to see the network state, or else the error will occur. Only network permissions so you do not need to declare the permission line, I added, but in any example we have not handled anything related to that permission.
Subscribe to a broadcast to listen for the network change event: NetworkChangeReceiver
<receiver android:name=".NetworkChangeReceiver" > <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver>
Here you see in the inter-filter it has 2 listening events that are android.net.conn.CONNECTIVITY_CHANGE
. You don’t get any notification when there is a change.
And NetworkChangeReceiver
is the name of the class you will initialize to receive the notification of registering the listening action above. Next you will create a Class named NetworkChangeReceiver.java
to get the results returned when there is a network change event.
Next, create class NetworkChangeReceiver.java
to get the results.
Of course when you listen to a change with Broadcast, of course it should return results somewhere, right? Here it will return the class you declared in AndroidManifest.xml
, like so:
Create a class that receives the broadcast listening results
NetworkChangeReceiver.java
package com.tutorialspots.broadcast; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Network is turned ON/OF", Toast.LENGTH_SHORT).show(); } }
You initialize a class with the name declared in AndroidManifest.xml
and then extend the BroadcastReceiver
class, the listening result will be returned to the onReceiver ()
method.
Means that every network change, it will creep into function onReceiver ()
, so you will be treated here, if you notice your can.Here by Toast alone and not do anything.
That’s it, how to declare a static BroadcastReceiver, now we will go to method 2.
Method 2: Register with Java code
This is how we will do the most out of those projects. Why? There will be instances where we will listen for door-to-door events in scope when the application we run and when the application ends, we stop the process as well.
For example, the act of listening to the network alone, for example, no app will ever listen like that in AndroidManifest because we only need to listen when the application is running, not even when the application is turned off. And this way you will not need to declare Broadcast in AndroidManifest anymore.
Here is a classic example of this broadcast receiver application:
Now I will go into listening to the device’s Network change event by the method 2.
Initiate the Broadcast class to listen
public class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Network is turned ON/OF", Toast.LENGTH_SHORT).show(); } }
The above class is similar to method 1, there is always nothing different, everyone, but in the 1s we have to declare this class in AndroidManifest
, in this case it is not, just initialize it and that’s it.
Next we will go to register the broadcast listening event with java code, because by AndroidManifest
, to register, we will declare as follows.
Listen for Network change events
NetworkChangeReceiver receiver = new NetworkChangeReceiver(); final IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"); registerReceiver(receiver, filter);
Above I initialize an IntentFilter and pass it an action, action above is exactly the same way. It is listening to the changing Internet of the device.
And below I call a ham called registerReceiver ()
and pass in the Class Broadcast and action we created earlier, the purpose is to register with the system as it logs listening to the device’s network change events, If there is a change, the result will be returned to the onReceiver ()
function of the NetworkChangeReceiver
class .
In fact, this way is different from registering in Manifest, everyone, instead of registering automatically, we will now register by code, this I will clarify in the video for you to understand more deeply.
Another point to note is that you have called the registerReceiver ()
function to register, then after exiting the application we should cancel it because why you wrote it. Lost registry, also known as leak / loss, will lead to a classic error like this:
Are you missing a call to unregisterReceiver()?
The cause and demo will be detailed by me in the video below, please watch it. To unsubscribe from the Broadcast Receiver you call the following function unregisterReceiver ()
, put it in onPause ()
or onStop ()
. In my opinion is better to put on onStop ()
for safety, this I have explained clearly in the video.
Full code of MainActivity is as follows:
MainActivity.java
package com.tutorialspots.broadcast; import android.content.IntentFilter; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.Button; public class MainActivity extends AppCompatActivity { private NetworkChangeReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); receiver = new NetworkChangeReceiver(); final IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"); registerReceiver(receiver, filter); } @Override protected void onStop() { super.onStop(); unregisterReceiver(receiver); } }
The result when we will be as follows:
Custom Broadcast Receiver
This is the part I added, the goal of this custom is to have me reimagined the Broadcast receiver’s mechanism so that you can understand more about this guy. That means now we create the actions themselves and proactively send, now if you are listening for those actions, it will definitely get it.
For example, now I want to send an action called “tutorialspots.com” and in AndroidMainifest.xml
we listen to the correct action “tutorialspots.com”, then see if we can receive it:
AndroidMainifest.xml
<receiver android:name=".NetworkChangeReceiver"> <intent-filter> <action android:name="tutorialspots.com" /> </intent-filter> </receiver>
And here is the code to create an action and send it using java code:
Intent intent = new Intent(); intent.setAction("tutorialspots.com); sendBroadcast(intent);
That is, you can see that all broadcast are sent through the intent, so in the onReceive ()
function we always get 1 itent.You can add many actions using the method setAction ()
of the intent. you call the sendBroadcast (intent)
method , at this time the system will automatically generate an intent with the action “tutorialspots.com” and because you are listening to this action in AndroidManifest
, it will receive.
When you turn on or off the network, it also works the same way, guys, this custom we also use very often to shoot data back and forth between screens, or that application.
Bonus 1: Network State Detector:
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo ni = manager.getActiveNetworkInfo(); boolean connected = false; if(ni != null && ni.getState() == NetworkInfo.State.CONNECTED) { connected = true; } else if(intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,Boolean.FALSE)) { connected = false; } Toast.makeText(context, "Network is turned "+(connected?"ON":"OFF"), Toast.LENGTH_SHORT).show();
Bonus 2: several system generated events defined as final static fields in the Intent
class.
Sr.No | Event Constant & Description |
---|---|
1 |
android.intent.action.BATTERY_CHANGED Sticky broadcast containing the charging state, level, and other information about the battery. |
2 |
android.intent.action.BATTERY_LOW Indicates low battery condition on the device. |
3 |
android.intent.action.BATTERY_OKAY Indicates the battery is now okay after being low. |
4 |
android.intent.action.BOOT_COMPLETED This is broadcast once, after the system has finished booting. |
5 |
android.intent.action.BUG_REPORT Show activity for reporting a bug. |
6 |
android.intent.action.CALL Perform a call to someone specified by the data. |
7 |
android.intent.action.CALL_BUTTON The user pressed the “call” button to go to the dialer or other appropriate UI for placing a call. |
8 |
android.intent.action.DATE_CHANGED The date has changed. |
9 |
android.intent.action.REBOOT Have the device reboot. |