四大组件之广播接收者BroadcastReceiver
参考:Android开发基础之广播接收者BroadcastReceiver
什么是广播接收者?
我们小时候都知道,听广播,收听广播!什么是收听广播呢?打开收音机,调频就可以收到对应的广播节目了。其实我们在Android开发中也有类似的概念,所以就称之为广播了。
广播包括发广播和广播接收者,这就类似于我们的广播发射塔和收音机。
因些,在Android开发中,我们主要研究的就是发广播和接收广播了。
监听电量变化状态(例子)
我们先从一个例子开始吧,后面我们从这个例子里头分析里面的各种知识点。
首先,我们创建一个Receiver类:
package com.sunofbeaches.broadcastreceiverdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* Created by TrillGates on 2018/3/15.
*/
public class BatteryStatusReceiver extends BroadcastReceiver {
private static final String TAG = "BatteryStatusReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action is == " + action);
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
Log.d(TAG, "电量改变了的广播...");
} else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
Log.d(TAG, "电池低电量广播...");
} else if (action.equals(Intent.ACTION_BATTERY_OKAY)) {
Log.d(TAG, "电池充电完成。...");
}
}
}
上面的代码呢,是继承自己一个广播接收者BroadcastReceiver,这就类似于这个就是我们的收音机了,我们收听的频道是什么呢?由这个Action定,在那里添加Action频道呢?
这就是第二步:
<uses-permission android:name="android.permission.BATTERY_STATS"/>
权限在那里添加呢?在AndroidManifest.xml配置文件里,如图所示:
第三步,我们在ManiActivity里注册一下:
package com.sunofbeaches.broadcastreceiverdemo;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private BatteryStatusReceiver mReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter();
//设置频道,也就是设置要监听的广播action.
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(Intent.ACTION_BATTERY_OKAY);
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
mReceiver = new BatteryStatusReceiver();
//注册广播
registerReceiver(mReceiver, intentFilter);
Log.d(TAG, "register receive..");
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消广播注册,释放资源
if (mReceiver != null) {
unregisterReceiver(mReceiver);
mReceiver = null;
Log.d(TAG, "unregister receive..");
}
}
}
上面这代码的意思就是我们需要注册一下这个广播接收者,有没有觉得它中回调有点类似呢?但是我们是有条件地接受广播。这其实就类似于我们的收音机需要设置一个频道,收到这个频道的相关广播。而我们广播则是设置action,接下来的话,我们就把这个应用跑起来看看能不能接收到广播。我们监听着Android手机的电量变化情况
运行:
我们把这个程序跑起来,然后通过模拟器去模拟电量的变化,然后就可以收到了电量改变的广播了…
要注意的地方:
我们的应用要跑在前台哦,因为我们是动态注册广播接收者。我们的Activity创建的时候,会注册,在onDestroy的时候会取消注册。所以我们要保持这个我们的这个应用活着(返回键可以退出程序,前提是没有复写onBackPress事件/onKeyEvent方法)才可以接收到广播。
至于什么是动态注册和静态注册,后面我们会讨论到 。大家先完成这个例子。
广播的分类
从发广播者上面分,可以分为系统广播和第三方广播。 从接收的顺序上分,可以分为有序广播和无序广播。 常见的系统发出的广播有那些呢:比如说系统的开机完成广播、Wifi状态改变的广播、SD卡挂载的广播、电量的改变广播…
广播的注册方式
广播有两种方式注册:静态注册和动态注册。
静态注册:
1、注册方式:在AndroidManifest里进行注册。
首先在Application节点里头,添加一个receiver节点。name则是我们的广播接收者。
比如说,我们监听开机广播,那么我们跟前面一样,创建一个收音机,也就是广播接收者:
package com.sunofbeaches.broadcastreceiverdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* Created by TrillGates on 2018/3/15.
*/
public class BootCompletedReceiver extends BroadcastReceiver {
public static final String TAG = "BootCompletedReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "actions -- >" + action);
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Log.d(TAG, "开机完成");
}
}
}
接着,这就是静态注册了,在AndroidMainfest.xml里的application节点里添加receiver节点,并且添加意图过滤的action:
<receiver android:name=".BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
并且需要添加权限:
OK,我们把程序跑起来,这个是静态注册,即使我们写的应用不在前台,也能接收到广播。这是静态注册的特点,我们后面会进行总结的。
这样子我们把机器重启一下,看能不能获取到开机完成的广播:
静态注册内部类广播要注意什么呢?
首先是静态注册,其次是内部广播接收者!
1、这个内部广播接收者需要声明为静态的;
2、这个内部的静态接收者必须是public的;
3、在receiver的name里是外部类的名字$内部类的名字
这就是静态注册方式啦!接下来,咱们再来一个动态注册,其实前面的话,我们已经进行了动态注册的例子了,就是我们开头那个。
动态注册:
动态注册的例子前面也有,这里的话,我们写别的例子吧!多写点例子,让同学们更熟悉广播的注册。注意,是广播的注册!!!后面我们才讲到广播的发送!
假设我们做一个地图软件 ,当我们知道屏幕锁定以后,那么就不去更新数据,如果是屏幕打开了,就去更新数据。为什么要这么做呢,一是省电,二是省流量,对吧!
怎么做呢?
首先,我们编写一个广播接收者:
我是在MainActivity这个类里头创建了这个广播接收者,一般来说,动态接收的广播多数情况下是内部类,这样子可以操作外部类。
private class ScreenStatusReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
//屏幕关闭
Log.d(TAG, "屏幕关闭...停止数据更新");
} else if (Intent.ACTION_SCREEN_ON.equals(action)) {
//屏幕打开
Log.d(TAG, "屏幕关闭...继续数据更新");
}
}
}
接着呢,就是注册广播了:
我在onCreate方法里进行注册:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册广播
//第一步,创建意图过滤器
IntentFilter intentFilter = new IntentFilter();
//第二步,添加要监听的广播action
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
//第三步,创建广播接收者,并且设置成成员变量,以便于取消注册,释放资源
mScreenStatusReceiver = new ScreenStatusReceiver();
//第四步,注册广播接收者
this.registerReceiver(mScreenStatusReceiver, intentFilter);
}
广播注册以后,要记得在不用的时候进行销毁,这个应用于对我们来说,就是在退出的时候,我们就不需要地广播进行监听了,所以我们直接在onDestroy的时候,去取消注册即可。
@Override
protected void onDestroy() {
super.onDestroy();
//取消广播注册
if (mScreenStatusReceiver != null) {
this.unregisterReceiver(mScreenStatusReceiver);
mScreenStatusReceiver = null;
}
}
好啦,以下是整个代码:
package com.sunofbeaches.broadcastdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ScreenStatusReceiver mScreenStatusReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册广播
//第一步,创建意图过滤器
IntentFilter intentFilter = new IntentFilter();
//第二步,添加要监听的广播action
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
//第三步,创建广播接收者,并且设置成成员变量,以便于取消注册,释放资源
if (mScreenStatusReceiver == null) {
mScreenStatusReceiver = new ScreenStatusReceiver();
}
//第四步,注册广播接收者
this.registerReceiver(mScreenStatusReceiver, intentFilter);
}
private class ScreenStatusReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
//屏幕关闭
Log.d(TAG, "屏幕关闭...停止数据更新");
} else if (Intent.ACTION_SCREEN_ON.equals(action)) {
//屏幕打开
Log.d(TAG, "屏幕关闭...继续数据更新");
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消广播注册
if (mScreenStatusReceiver != null) {
this.unregisterReceiver(mScreenStatusReceiver);
mScreenStatusReceiver = null;
}
}
}
接收这个广播不需要权限,大家怎么知道是否需要权限呢?比如说前面我们写的例子,监听开机广播。我们可以在android studio里敲出:Intent.ACTION_BOOT_COMPLETED,然后点击进去看看:
/**
* Broadcast Action: This is broadcast once, after the user has finished
* booting. It can be used to perform application-specific initialization,
* such as installing alarms. You must hold the
* {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission in
* order to receive this broadcast.
* <p>
* This broadcast is sent at boot by all devices (both with and without
* direct boot support). Upon receipt of this broadcast, the user is
* unlocked and both device-protected and credential-protected storage can
* accessed safely.
* <p>
* If you need to run while the user is still locked (before they've entered
* their lock pattern or PIN for the first time), you can listen for the
* {@link #ACTION_LOCKED_BOOT_COMPLETED} broadcast.
* <p class="note">
* This is a protected intent that can only be sent by the system.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
{@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission in order to receive this broadcast.
这句话的意思就是,你需要这个权限”android.permission.RECEIVE_BOOT_COMPLETED”
目的是为接收这个广播,否则你接收不到。
一般来说,在我们的action里会说明,如果以后,你自己写广播,在自己的action里也要说明一下需要什么权限了。
两种注册方式的区别
静态注册可以一直监听着,即使应用没有起来,也可以监听着,但是耗资源,长期监听着。
静态注册的广播优先级高于动态注册的广播。
动态注册的优点就是省资源,需要的时候才监听,不需要的时候需要取消注册。
不可以静态注册的广播
有些广播,只可以动态注册的。有那些呢?
android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.BATTERY_CHANGED
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.TIME_TICK
为什么不可以静态注册?
如果不是必须一直监听着的广播,如果一直监听着会消耗资源,所以静态注册会提高系统的效率。而动态注册的话需要释放资源取消注册,否则会报错的。这样子有利于提高系统的速度。
如何发送广播
前面的话我们都是接收系统发出来的广播,接下来我们自己也发广播。
假设你做一个应用,比较牛逼一点的,对吧!需要对多进行通知。做这类应用有两种情况:
第一种是做sdk开发的,也就是开发sdk给别人使用的。
第二种是应用内广播,其实就是通知。
PS:额外的知识,我们学习android的广播机制有什么用呢,其实就是用于通知。如果在应用内,我们常用的通知方式是回调和广播。这两者之前,回调的速度快,保障性高,而广播则简单,但是速度没有回调高。什么情况下使用广播呢?当有多个地方使用等待通知的时候,可以使用广播。原理上广播和回调差不多的,广播的原理就是使用Binder机制,把action注册到ActivityManagerService里头,然后广播的时候,就去里面寻找符合规则的,再调用onReceive这个方法。
另外一种情况就是跨进程通讯,后面我们会学习到AIDL,这里的话是广播。广播是可以跨应用通知的,比如我们接收到了系统的广播对吧!也可以进行权限的控制,谁可以接收到这样的广播。
好,回到我们的主题,怎么样发送广播呢?
我们先不讨论发送有序广播,我们就随随便便发个广播通知!
这个是我们的布局文件,就一个按钮,我们点击按钮的时候,就去发送广播。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="sendBroadcast"
android:text="发送广播"/>
</LinearLayout>
以下是Activity的内容,从代码看出我们是怎么发送广播的:
package com.sunofbeaches.broadcastdemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class SendBroadcastActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast);
}
public void sendBroadcast(View view) {
Intent intent = new Intent();
//action只能有一个,所以叫setAction而不是addActon。
//而广播接收者可以监听多个广播,所以是addAction
//action的命名一般是报名+动作名,这样子比较唯一
intent.setAction("com.sunofbeaches.broadcastdemo.SEND_BROADCAST_CLICK");
//也可以携带数据
intent.putExtra("Content", "这是我点击按钮发送的广播!");
sendBroadcast(intent);
}
}
然后呢,我们再写一个广播接收者来接收广播,这个接收者可以是在第三方应用,也可以在我们本应用,我们写一个静态注册来注册它。前面已经教过大这怎么编写广播接收者了,并且怎么注册。这里的话我们写一个内部类来接收。前面说到了,要注意的是,内部广播接收者类,需要是静态的,Public的,注册的时候,是外部类名$内部类名
package com.sunofbeaches.broadcastdemo;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class SendBroadcastActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast);
}
public void sendBroadcast(View view) {
Intent intent = new Intent();
//action只能有一个,所以叫setAction而不是addActon。
//而广播接收者可以监听多个广播,所以是addAction
//action的命名一般是报名+动作名,这样子比较唯一
intent.setAction("com.sunofbeaches.broadcastdemo.SEND_BROADCAST_CLICK");
//也可以携带数据
intent.putExtra("Content", "这是我点击按钮发送的广播!");
sendBroadcast(intent);
}
public static class InnerReceiver extends BroadcastReceiver{
private static final String TAG = "InnerReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "Inner receiver 接收到的actions... " + action);
if ("com.sunofbeaches.broadcastdemo.SEND_BROADCAST_CLICK".equals(action)) {
String content = intent.getStringExtra("Content");
Log.d(TAG, "content is == " + content);
}
}
}
}
静态注册的代码:
<receiver android:name=".SendBroadcastActivity$InnerReceiver">
<intent-filter>
<action android:name="com.sunofbeaches.broadcastdemo.SEND_BROADCAST_CLICK"/>
</intent-filter>
</receiver>
然后我们设置一下 这个Activity是主的Activity,也就是启动时候,它先启动。
再跑起这个程序:
这就是我们自定义的广播发送者和广播接收者啦!
有序广播
前面我们所讲到的都是无须广播,也就是发出去了,任何应用都可以接收到,只要有对应的Action就可以了。
有序广播:有序广播就类似于单位的通知,由上级一级一级往下传。特点是:
1、有序
2、可以终止往下传达
3、可以修改广播的内容
这样子类比过去,我们就更容易理解了,对吧!
无须广播就像上学时的学校广播,谁都可以听到;有序广播则像是校长的通知,一级一级往下传。里面的主任呀,级长呀,可以修改内容,甚至是中断往下传达!
以一个例子来说明吧:
假设学校收到一笔捐款,用于资助各年级各班的贫困学生。
于是:我们有一个广播发送者叫做xxx基金会,给每个贫困学生发送1000块钱的资助金。
布局跟前面一样,只有一个按钮:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:onClick="sendDonation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送捐助广播"/>
</LinearLayout>
然后呢,是Activity的代码,怎么样去发送有序广播!
package com.sunofbeaches.broadcastdemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class DonationBroadcastActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_donation);
}
public void sendDonation(View view) {
Intent intent = new Intent();
intent.setAction("com.sunofbeaches.broadcastdemo.DONATION");
Bundle bundle = new Bundle();
bundle.putInt("money", 1000 * 500);
sendOrderedBroadcast(intent, null, null, null, 1, "给每个贫困的学生资助1000元", bundle);
}
}
这里怎么简单怎么样,关于权限的问题后面我们再解释。先给大家解释一下,每个参数是什么意思先!
@Override
public void sendOrderedBroadcast(
Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
mBase.sendOrderedBroadcast(intent, receiverPermission,
resultReceiver, scheduler, initialCode,
initialData, initialExtras);
}
上面这个是原方法:
- 第一个参数,不用说了,我们发送广播就知道了,这个是意图对象,用于封装数据和设置过滤。
- 第二个参数是权限,权限我们后面会详细说到,虽然很少用到,但是你知道这个思想,有利于你以后自己钻研android的代码。
- 第三个参数是广播接收者,这个广播接收者是最终接收的广播接收者,用于检查数据是否有传达或者数据被修改。
- 第四个参数是一个自定义的Hanlder,用于处理结果接收者,也就是上面那个接收者的回调。
- 第五个参数是初始码,这个会作为结果码,通常是Activity.RESULT_OK,也就是-1。
- 第六个参数是用于传递数据的,这个数据在各个Receiver里获取到,通过getResultData方法获取。这个其实通常为null
- 第七个参数也是用于封装数据的,不同的是,这个用于封装数据集合,从上面的代码可以知道 ,我用来封装了一个钱的数据。
以下是原api的说明文档:
写完了发送者以后,我们就会去写一下接收者了。
三个接收者的代码如下,分别是学校接收者,年级接收者,班级接收者,贫困这生接收者!
package com.sunofbeaches.broadcastdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class SchoolReceiver extends BroadcastReceiver {
private static final String TAG = "SchoolReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Bundle resultExtras = getResultExtras(true);
int money = resultExtras.getInt("money");
//学校处理一下,分给5个年级
int perGrade = money / 5;
Log.d(TAG, "学校接收到捐款 " + money);
Bundle bundle = new Bundle();
bundle.putInt("money", perGrade);
setResultExtras(bundle);
}
}
年级广播接收者:
package com.sunofbeaches.broadcastdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class GradeReceiver extends BroadcastReceiver {
private static final String TAG = "GradeReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Bundle resultExtras = getResultExtras(true);
//假设每个年级有10个班
resultExtras.putInt("money", resultExtras.getInt("money") / 10);
Log.d(TAG, "年级收到捐款 " + resultExtras.getInt("money"));
}
}
班级接收者:
package com.sunofbeaches.broadcastdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class ClassReceiver extends BroadcastReceiver {
private static final String TAG = "ClassReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Bundle resultExtras = getResultExtras(true);
//假设每个班有10个贫困的孩子
int perStudent = resultExtras.getInt("money")/10;
Log.d(TAG, "班级收到捐款--> " + resultExtras.getInt("money"));
Bundle bundle = new Bundle();
bundle.putInt("money", perStudent);
setResultExtras(bundle);
}
}
贫困学生接收者:
package com.sunofbeaches.broadcastdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class PoorStudentReceiver extends BroadcastReceiver {
private static final String TAG = "PoorStudentReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Bundle resultExtras = getResultExtras(true);
int money = resultExtras.getInt("money");
Log.d(TAG, "接收到捐款 --> " + money);
Log.d(TAG, "感谢各位好心人士...");
}
}
广播也写好了,那么就是注册广播了:
在AndroidManifest.xml文件里头;
<receiver android:name=".SchoolReceiver">
<!--优先级是1000~-1000之间,超出了范围则会使用边界值-->
<intent-filter android:priority="1000">
<action android:name="com.sunofbeaches.broadcastdemo.DONATION"/>
</intent-filter>
</receiver>
<receiver android:name=".GradeReceiver">
<intent-filter android:priority="500">
<action android:name="com.sunofbeaches.broadcastdemo.DONATION"/>
</intent-filter>
</receiver>
<receiver android:name=".ClassReceiver">
<intent-filter android:priority="100">
<action android:name="com.sunofbeaches.broadcastdemo.DONATION"/>
</intent-filter>
</receiver>
<receiver android:name=".PoorStudentReceiver">
<intent-filter android:priority="-1000">
<action android:name="com.sunofbeaches.broadcastdemo.DONATION"/>
</intent-filter>
</receiver>
关于优先级的说明在注释里已经有了priority就是优先级的意思。
那我们就把程序跑起来吧,看谁先接收到广播:
好啦,从上面的例子,我们可以看到,广播是按优先级通知的,并且可以修改广播的内容。
也可以终止广播的传达,假设这笔捐款到了学校就不往下传了,怎么处理呢?
package com.sunofbeaches.broadcastdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* Created by TrillGates on 18/3/18.
* God bless my code!
*/
public class SchoolReceiver extends BroadcastReceiver {
private static final String TAG = "SchoolReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Bundle resultExtras = getResultExtras(true);
int money = resultExtras.getInt("money");
//学校处理一下,分给5个年级
int perGrade = money / 5;
Log.d(TAG, "学校接收到捐款 " + money);
Bundle bundle = new Bundle();
bundle.putInt("money", perGrade);
setResultExtras(bundle);
//终止广播往下传
abortBroadcast();
}
}
abortBroadcast(),我们加了这句代码,运行结果如下:
说明不会再往下传递了。
无序广播和有序广播的区别
学习了前面的内容,我们知道了有序广播和无序广播。那么这两者间有什么区别吗?
本质上是一样的,也就是说,无序广播是按注册顺序派发的,有序广播按优先级。我们知道一下特点就可以了。
有序广播的接收者可以终止/修改数据,而无须广播不可以。
广播的权限
前面我们有提到权限,但是我们一笔略过,到这里才对权限进行分析。广播的权限分为两部分,一部分是我可以接收谁的广播,一部分是谁可以给我发广播。这就是权限啦!
我发的广播谁可以接收到
如果要做到我发的广播,有权限的人才能接收到,那么需要这样做:
在AndroidManifest.xml中生命permission
<permission android:name="com.sunofbeaches.permission.DONATION"/>
发送广播的时候把permision加上,比如说:
public void sendDonation(View view) {
Intent intent = new Intent();
intent.setAction("com.sunofbeaches.broadcastdemo.DONATION");
Bundle bundle = new Bundle();
bundle.putInt("money", 1000 * 500);
sendOrderedBroadcast(intent, Manifest.permission.DONATION, null, null, 1, "给每个贫困的学生资助1000元", bundle);
}
Manifest.permission.DONATION这一句其实就是我们前面定义的权限,按Control点击可以跳过去。
第三步则是在需要接收的应用里头,添加权限,因为我们这里是同一个应用,所以在本应用添加就可以了:
<uses-permission android:name="com.sunofbeaches.permission.DONATION"/>
这样子就可以接收到广播了!
谁有权限给我发广播
谁有权限给我发广播,这个其实在receiver的节点里头,就有一个permission的属性
这个Permission声明就是用于控制谁有权限给我发广播的。
四大组件之广播接收者BroadcastReceiver的更多相关文章
- Android 四大组件之三(广播)
1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通 ...
- 广播接收者 BroadcastReceiver 示例-1
广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者.广播作为Android组件间的通信方式,可以使用的场景如下: 1 ...
- Android系统编程入门系列之广播接收者BroadcastReceiver实现进程间通信
在前边几篇关于Android系统两个重要组件的介绍中,界面Activity负责应用程序与用户的交互,服务Service负责应用程序内部线程间的交互或两个应用程序进程之间的数据交互.看上去这两大组件就能 ...
- Android四大组件之一“广播”
前言 Android四大组件重要性已经不言而喻了,今天谈谈的是Android中的广播机制.在我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就 ...
- Android - 广播接收者 - BroadcastReceiver
BroadcastReceiver 介绍: 广播是一种广泛运用的在应用程序之间传输信息的机制 .而 BroadcastReceiver 是对发送出来的广播 进行过滤接收并响应的一类组件 接受一种或者多 ...
- Android学习笔记_19_广播接收者 BroadcastReceiver及其应用_窃听短信_拦截外拨电话
一.广播接收者类型: 广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”. 普通广播是完全异步的,可以在同一时刻(逻辑上 ...
- 广播接收者 BroadcastReceiver 示例-2
BaseActivity /**所有Activity的基类*/ public class BaseActivity extends Activity { @Override prote ...
- Android中广播接收者BroadcastReceiver详解
1. 接收系统的广播步骤 (1) 新建一个类继承BroadcastReceiver 以监听sd卡状态的广播接收者为例 public class SdCardBroadcastReceiver ext ...
- Android四大组件应用系列——使用BroadcastReceiver和Service实现倒计时
一.问题描述 Service组件可以实现在后台执行一些耗时任务,甚至可以在程序退出的情况下,让Service在后台继续保持运行状态.Service分本地服务和远程服务,Local地服务附在主进程上的m ...
- 广播接收者BroadcastReceiver
BroadcastReceiver与activity,service有完整的生命周期不同,BroadcastReceiver本质上是一系统级别的监听器,专门负责监听各程序发出的broadcast.与程 ...
随机推荐
- Redis set数据类型命令使用及应用场景使用总结
转载请注明出处: 目录 1.sadd 集合添加元素 2.srem移除元素 3.smembers 获取key的所有元素 4.scard 获取key的个数 5.sismember 判断member元素是否 ...
- cookie设置失败
有个小项目,本地测试一帆风顺,昨天发布到云服务器后就出问题了 Java端设置的Cookie,浏览器访问不到 1-2022-2-11 设置cookie代码如下 /** * 添加Cookie * @par ...
- python进阶之路11 闭包函数 装饰器
函数名的多种用法 函数名其实绑定的也是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行 1.可以当作变量名赋值 def index():pass res = ...
- vulnhub靶场之HACKATHONCTF: 2
准备: 攻击机:虚拟机kali.本机win10. 靶机:HackathonCTF: 2,下载地址:https://download.vulnhub.com/hackathonctf/Hackathon ...
- 【Dubbo3终极特性】「流量治理体系」一文教你如何通过Dubbo-Admin实现动态进行流量隔离机制
背景信息 如果一个应用有多个版本在线上同时运行,部署在不同环境中,如日常环境和特殊环境,则 可以使用标签路由对不同环境中的不同版本进行流量隔离,将秒杀订单流量或不同渠道订单流量路由到特殊环境,将正常的 ...
- echarts图表配置
1.柱状图 option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] ...
- three.js一步一步来--如何用线画出一个面--网格板子
网格板子~~~ <template> <div style="width:1000px; height:800px"> <p>网格布局</ ...
- 分布式协议与算法-Paxos算法
1.Basic Paxos 假设我们要实现一个分布式集群,这个集群是由节点 A.B.C 组成,提供只读 KV 存储服务.你应该知道,创建只读变量的时候,必须要对它进行赋值,而且这个值后续没办法修改.因 ...
- io流概述-一切皆为字节
io流概述 什么是io 生活中,你肯定经历过这样的场景.当你编辑一个文本文件,忘记了ctrl+s,可能文件就白白编辑了当你电脑上插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里.那么数据都是在哪些设 ...
- JSP第八次作业
数据库test 中建个表 stu(stuid 主键 自动增长 ,用户名,密码,年龄) 1.设计一个注册页面,实现用户注册功能2.设计一个登陆页面,实现用户名密码登陆3.两个页面可以互相超链接 1 pa ...