All of my articles are collected in this article, and will be updated in time: Knowledge is long, the road of the walker will end in no words (My Programming Road)
Zero, preface,
1. Knowledge points of this article
1). BroadcastReceiver ` static ` use 2) BroadcastReceiver ` dynamic ` using 3) BroadcastReceiver ` orderly ` radio 4) BroadcastReceiver and ` system ` behavior is the combination of 5). Small example: Use BroadcastReceiver to update music player progress barCopy the code
2. BroadcastReceiver overview
The BroadcastReceiver is a simple class that inherits Object directly from the BroadcastReceiver. It has no interface and no family background
[] Package name: Android.content Number of dependent classes :9 Number of internal classes/interfaces: 1 number of source lines: 653 Number of source lines (except comments):260 Number of attributes :2 number of methods :36 Number of public methods :36Copy the code
The BroadcastReceiver is used statically
Static usage is to configure intent filters in androidManifest.xml to match information about intents, as described in the previous article, but not explained here
Write a class that inherits from BroadcastReceiver
/ * * * the author: packer jet fierce < br > < br > * time: 2019/1/21/021:16:53 < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: ToastBroadcastReceiver */ Class BroadcastReceiverBroadcastReceiver() {override fun onReceive(context: context, Intent: intent) {toast.makeText (context, intent);"Toly", Toast.LENGTH_SHORT).show()
}
}
---->[app/src/main/AndroidManifest.xml]------------------
<receiver android:name=".receiver.receiver.ToastBroadcastReceiver">
<intent-filter>
<action android:name="www.toly1994.com.br.toast"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
Copy the code
2. Test the Activity
---->[BrActivity#onCreate]------------------
id_btn_send.setOnClickListener {
val intent = Intent("www.toly1994.com.br.toast")
sendBroadcast(intent)
}
Copy the code
3. Static broadcast on Android8.0+
To be effective, an intent must specify the component to be broadcast
---->[BrActivity#onCreate]------------------
id_btn_send.setOnClickListener {
val intent = Intent("www.toly1994.com.br.toast")
intent.component = ComponentName(
"com.toly1994.tolyservice",// Project package name"com.toly1994.tolyservice.receiver.receiver.ToastBroadcastReceiver"SendBroadcast (intent)}Copy the code
4. Obtain data from static broadcasts
The onReceive callback for the broadcast receiver contains intent: Intent
---->[BrActivity#onCreate]------------------
id_btn_send.setOnClickListener {
val intent = Intent("www.toly1994.com.br.toast"Intent.putextra (intent.putextra) intent.putextra (intent.putextra)"toast_data", id_et_txt.text.toString())
intent.component = ComponentName(
"com.toly1994.tolyservice",// Project package name"com.toly1994.tolyservice.receiver.receiver.ToastBroadcastReceiver"/ / radio receiver full class name) sendBroadcast (intent)} -- -- -- - > [ToastBroadcastReceiver] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / when receiving the method called * * * * / override fun onReceive(context: Context, intent: Intent) { val data = intent.getStringExtra("toast_data") //data? :"NO MSG"If data is null, take"NO MSG"Toast.makeText(context, data? :"NO MSG", Toast.LENGTH_SHORT).show()
}
Copy the code
5. What’s the use of BroadcastReceiver?
It seems that onReceive is a very low coupling function for BroadcastReceiver. All it needs is an intent and context. SendBroadcast to trigger onReceive. To illustrate what’s interesting about it, let’s create a new app:Anotherapp
Can be found in another app can normal use of the radio It’s interesting, I wrote A class in A project, it can be triggered in B project This is the place where the static radio badly, is also the first time I contact cross-process communication (decoupling to a certain state, suggesting that the world with me, but I will be ubiquitous, manual funny)
2. The BroadcastReceiver is used dynamically
If the BroadcastReceiver is not registered, it will not be BroadcastReceiver. If the BroadcastReceiver is registered, it will not be BroadcastReceiver. If the BroadcastReceiver is not registered, it will not be BroadcastReceiver.
1. Register to broadcast and send messages
/** * Register for radio */ Private funregister() {val filter = IntentFilter();"www.toly1994.com.br.toast2"MReceiver = Toast2BroadcastReceiver()// Create Toast2BroadcastReceiver registerReceiver(mReceiver, Filter)// register} /** * send broadcast */ private funsendMsg() {
val intent = Intent()
intent.action = "www.toly1994.com.br.toast2"
intent.putExtra("toast_data", id_et_txt.text.toString())
sendBroadcast(intent)
}
Copy the code
2. Cancel the broadcast
What do you say, I don’t log off? If an exception is not registered, the source code kindly reminds you to unregisterReceiver
The 2019-01-22 14:10:50. 940, 4892-4892 / com. Toly1994. Tolyservice E/ActivityThread: Activity com.toly1994.tolyservice.receiver.BrActivity has leaked IntentReceiver com.toly1994.tolyservice.receiver.receiver.Toast2BroadcastReceiver@32500e2 that was originally registered here. Are you missing a call to unregisterReceiver()? at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1333)
at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:1114)
at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1405)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1378)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1366)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:603)
at com.toly1994.tolyservice.receiver.BrActivity.onCreate(BrActivity.kt:27)
Copy the code
/** * Log off */ private fununRegister() {
unregisterReceiver(mReceiver);
}
override fun onDestroy() {super.ondestroy () unRegister()// unRegister the broadcast}Copy the code
3. The difference between static and dynamic broadcasting
You might say: a class of 200 + lines, and all that stuff…
Dynamic registration radio | - advantage: free registration and cancellation of control, there is a lot of flexibility. | - disadvantage: only after registration can play a role, if not be cancelled after the Activity onDestroy, abnormal transactions - so dynamic registration broadcast live the longest time is approximately equal to the length of the Activity lifecycle Static registration radio | - advantage: Not bound by whether the program starts, always use | - disadvantage: advantage is also a disadvantage, is unable to cancel, when can beCopy the code
3. BroadcastReceiver broadcast in order
Here’s a scene: The Boy says, The value of a stone is 1 yuan and then he gives it to the sculptor, and he passes the expected value of 1,000 yuan to the sculptor and then the sculptor gives the stone to the gemologist, and he passes the expected value of 10 dollars to the gemologist and then the gemologist gives the stone to the collector, And the expected value of 100W yuan passed to the collector collector to the city of their own gem value of 100W
1. Broadcast in order (in order of registration if no order is specified)
1.1: Four broadcast receivers
/ * * * the author: packer jet fierce < br > < br > * time: 2019/1/21/021:16:53 < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: Boy */ class BoyBReceiver:BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context,
Boy:"$resultData",//[1] get the result and show totoast.LENGTH_LONG). Show () // abortBroadcast(); //[2] Terminate broadcast resultData ="Worth 1000 yuan"//[3] Transfer data -- to the next broadcast}} /** *BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Sculptor:$resultData", //[1] get the result and show totoast.LENGTH_LONG). Show () // abortBroadcast(); //[2] Terminate broadcast resultData ="Worth $10W"//[3] Pass data -- to the next broadcast}} /** *BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Gemologist:$resultData", Toast.LENGTH_LONG).show() // abortBroadcast(); //[2] Terminate broadcast resultData =(b) value of $100W//[3] Transfer data -- to the next broadcast}} /** *BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context,
"Collector:$resultData"// Get the result and show toast.length_long).show()}}Copy the code
1.2. Dynamically register and send ordered broadcasts
/** * Register for radio */ Private funregister() {val filter = IntentFilter();"www.toly1994.com.br.toast2")// Add intent boyReceiver = BoyBReceiver() graverReceiver = GraverBReceiver() rubyManReceiver = RubyManBReceiver() RegisterReceiver (boyReceiver, filter) registerReceiver(graverReceiver, filter) // Register registerReceiver(rubyManReceiver, filter)// Register} /** * send ordered broadcast */ private funsendOrder() {
val intent = Intent()
intent.action = "www.toly1994.com.br.toast2"
val collectorBReceiver = CollectorBReceiver()
sendOrderedBroadcast(
intent, null,
collectorBReceiver, null, 1,
"Value 1 dollar", null)} /** * Cancel the broadcast */ private fununRegister() {
unregisterReceiver(boyReceiver)
unregisterReceiver(graverReceiver)
unregisterReceiver(rubyManReceiver)
}
Copy the code
2. Stop broadcasting in mid-stream
*/ Class GraverBReceiver:BroadcastReceiver() {override fun onReceive(context: context, Intent: intent) {toast.makeText (context, intent);"Sculptor:$resultData", //[1] Get the result and show totoast.LENGTH_LONG). Show () abortBroadcast(); //[2] Terminate broadcast resultData ="Worth $10W"//[3] pass data to the next broadcast}}Copy the code
3. Customize the broadcast sequence
/** * Register for radio */ Private funregister() {boyReceiver = BoyBReceiver() val boyFilter = IntentFilter();"www.toly1994.com.br.toast2"GraverReceiver = GraverBReceiver() val graverFilter = IntentFilter()// Create IntentFilter graverFilter.addAction("www.toly1994.com.br.toast2"RubyManReceiver = RubyManBReceiver() val rubyManFilter = IntentFilter()// Create IntentFilter rubymanFilter.addAction ("www.toly1994.com.br.toast2"Rubymanfilter. priority = 21// registerReceiver(boyReceiver, // Register registerReceiver(graverReceiver, graverFilter)// Register registerReceiver(rubyManReceiver, rubyManFilter)// Register}Copy the code
The static registration is configured similarly in androidManifest.xml. The sendOrderedBroadcast method is called as a BroadcastReceiver, which is the last BroadcastReceiver to be called.
4. Combination of broadcasting and system behavior
The following uses dynamic registrations, and many system-level behavior static registrations are invalid
1. Unlock the screen
/ * * * the author: packer jet fierce < br > < br > * time: 2019/1/22/022: behold < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: */ Class ScreenBReceiver:BroadcastReceiver() { override fun onReceive(context: Context, intent: Val action = Intent.action //[2] Specifies the type of event currently broadcastif ("android.intent.action.SCREEN_OFF" == action) {
Log.e(TAG, "Screen is locked.")}else if ("android.intent.action.SCREEN_ON" == action) {
Log.e(TAG, "Screen unlocked.")
}
}
companion object {
private const val TAG = "ScreenBReceiver"}} - > [ScreenBrActivity usage] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / * * * dynamic to registration screen unlock and lock screen broadcast * / private funregister() {// [1] Dynamically deregister screen unlock and lock broadcast mScreenReceiver = ScreenBReceiver() // [2] Create an Intent-filter object val filter = IntentFilter() // [3] Add the action filter.addAction("android.intent.action.SCREEN_OFF")
filter.addAction("android.intent.action.SCREEN_ON") // [4] registerReceiver(mScreenReceiver, filter)}Copy the code
2. Monitor SMS broadcasts
Note permissions:
/ * * * the author: packer jet fierce < br > < br > * time: 2019/1/22/022: behold < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: */ class SMSBReceiver:BroadcastReceiver() {// Override fun onReceive(context: context, intent: intent); Intent.extras (intent.extras) {//[1] intent.extras (intent.extras) {//[1] intent.extras (intent.extras); .get("pdus") as Array<*>
val format = intent.getStringExtra("format")
for (pdu inObjects) {//[2] Obtain the smsmessage instance val smsmessage =if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SmsMessage.createFromPdu(pdu as ByteArray, format)
} else{smsmessage.createFrompdu (pdu as ByteArray)} //[3] Obtain the content of the SMS. Val body = smsmessage.messageBody val date = The time/Date (smsMessage timestampMillis)/val format = SimpleDateFormat ("yyyy-MM-dd HH:mm:ss", Locale. / / CHINA) [4] to get the sender val. Address = smsMessage originatingAddress val receiveTime = format. The format (date) the e ("SMSBReceiver"."body:$body---$address---$receiveTime")}}} - > [SMSBrActivity usage] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / dynamic registration message broadcast receiver * * * * / private funregister() {val smsFilter = IntentFilter() smsfilter.addAction ();"android.provider.Telephony.SMS_RECEIVED")
mSmsReceiver = SMSBReceiver()
registerReceiver(mSmsReceiver, smsFilter)
}
Copy the code
3. Monitor the power change broadcast
Here we pass in a Textview that shows the power
/ * * * the author: packer jet fierce < br > < br > * time: 2019/1/22/022: behold < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: */ Class BatteryBReceiver(private val mTV:TextView) :BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent.extra_level = intent.getinTextra (batteryManager.extra_Level, Total = Intent.getintextra (batteryManager.extra_scale, 1) Val percent = currLevel * 100 / total log.e ()"BatteryBReceiver"."battery: $percent%")
mTV.setTextColor(randomRGB())
mTV.text = "battery: $percent%"} /** * returns a random color ** @return*/ fun randomRGB(): Int { val random = Random() val r = 30 + random.nextInt(200) val g = 30 + random.nextInt(200) val b = 30 + random.nextInt(200)returnColor RGB (r, g, and b)}} - > [BatteryBrActivity usage] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / dynamic power radio receiver * * * * / private funregister() {
val filter = IntentFilter()
filter.addAction(Intent.ACTION_BATTERY_CHANGED)
mBatteryChangeReceiver = BatteryBReceiver(id_tv_info)
registerReceiver(mBatteryChangeReceiver, filter)
}
Copy the code
4. Broadcast monitoring when app installation/uninstallation changes
/ * * * the author: packer jet fierce < br > < br > * time: 2019/1/22/022: behold < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: */ class AppBReceiver:BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
val uri = intent.data
if (action == "android.intent.action.PACKAGE_ADDED") {
Log.e("AppBReceiver", uri.toString() + "Installed.")}else if (action == "android.intent.action.PACKAGE_REPLACED") {
Log.e("AppBReceiver", uri.toString() + "It's updated.")}else if (action == "android.intent.action.PACKAGE_REMOVED") {
Log.e("AppBReceiver", uri.toString() + "Uninstalled.")}}} - > [AppBrActivity usage] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / * * * to dynamically register app install/uninstall the change radio listening * / private funregister() {
val filter = IntentFilter()
filter.addAction("android.intent.action.PACKAGE_ADDED")
filter.addAction("android.intent.action.PACKAGE_REPLACED")
filter.addAction("android.intent.action.PACKAGE_REMOVED")
filter.addDataScheme("package") mAppReceiver = AppBReceiver() registerReceiver(mAppReceiver, filter)} Add the static, can / / note that found in the test, only add static configuration is invalid < receiver android: name =".receiver.receiver.AppBReceiver">
<intent-filter >
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
Copy the code
There are also some system behavior patterns that are similar, just look up the corresponding action when needed
Use radio to update music progress bar
[-service -] = BroadcastReceiver = BroadcastReceiver = BroadcastReceiver = BroadcastReceiver = BroadcastReceiver = BroadcastReceiver = BroadcastReceiver = BroadcastReceiver
-- -- -- - > [constant class] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the public class Cons {/ / radio data update progress - public static final String DATA_MUSIC_POSITION ="data_music_position"; --Action public static final String ACTION_UPDATE ="action_update";
}
---->[MusicPlayerWithBrStub]-----------------------------
mTimer.schedule(new TimerTask() {
@Override
public void run() {
if(mPlayer.isPlaying()) { int pos = mPlayer.getCurrentPosition(); int duration = mPlayer.getDuration(); > Intent Intent = new Intent(cons.action_update); ---> int progress = (int) (pos * 100.f / duration); ---> intent.putExtra(Cons.DATA_MUSIC_POSITION, progress); ---> mContext.sendBroadcast(intent); }, 0, 1000); ---->[MusicActivity#registerReceiver]-----------------------------| - here I create a new class, you can directly on the Activity build an inner class, Public Class UpdateReceiver extends BroadcastReceiver {@nullable Private ProgressView ProgressView; public UpdateReceiver(@Nullable ProgressView progressView) { this.progressView = progressView; } @Override public void onReceive(Context context, Intent intent) {if (Cons.ACTION_UPDATE.equals(intent.getAction())) {
int progress = intent.getIntExtra(Cons.DATA_MUSIC_POSITION, 0);
if(progressView ! = null) { ---> progressView.setProgress(progress); }}}} /** * Sign up for radio */ ---->[MusicActivity#registerReceiver]-----------------------------
private fun registerReceiver() { mReceiver = UpdateReceiver(id_pv_pre) val filter = IntentFilter() filter.addAction(Cons.ACTION_UPDATE) RegisterReceiver (mReceiver, filter)// register} ---->[MusicActivity#onDestroy]-----------------------------
override fun onDestroy() {super.ondestroy () unregisterReceiver(mReceiver)// unregisterReceiver mmusicPlayer.release ()}Copy the code
> BroadcastReceiver > BroadcastReceiver > BroadcastReceiver > BroadcastReceiver > BroadcastReceiver Let’s start later!