大家好,我是你的好朋友思创斯。今天说一说android广播的作用_android广播原理,希望您对编程的造诣更进一步.
broadcastreceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播。
在android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。
android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现在只需等待广播告知自己就可以了,大大减少了开发的工作量和开发周期。而作为应用开发者,就需要数练掌握android系统提供的一个开发利器,那就是broadcastreceiver。下面我们就对broadcastreceiver逐一地分析和演练,了解和掌握它的各种功能和用法。
首先,我们来演示一下创建一个broadcastreceiver,并让这个broadcastreceiver能够根据我们的需要来运行。要创建自己的broadcastreceiver对象,我们需要继承android.content.broadcastreceiver,并实现其onreceive方法。下面我们就创建一个名为myreceiver广播接收者:
public class myreceiver extends broadcastreceiver {
private static final string tag = “myreceiver”;
@override
public void onreceive(context context, intent intent) {
string msg = intent.getstringextra(“msg”);
log.i(tag, msg);
}
}
在onreceive方法内,我们可以获取随广播而来的intent中的数据,这非常重要,就像无线电一样,包含很多有用的信息。
在创建完我们的broadcastreceiver之后,还不能够使它进入工作状态,我们需要为它注册一个指定的广播地址。没有注册广播地址的broadcastreceiver就像一个缺少选台按钮的收音机,虽然功能俱备,但也无法收到电台的信号。下面我们就来介绍一下如何为broadcastreceiver注册广播地址。
broadcastreceiver的注册方式分为两种:
1.静态注册
静态注册是在androidmanifest.xml文件中配置的,我们就来为myreceiver注册一个广播地址:
配置了以上信息之后,只要是android.intent.action.my_broadcast这个地址的广播,myreceiver都能够接收的到。注意,这种方式的注册是常驻型的,也就是说当应用关闭后,如果有广播信息传来,myreceiver也会被系统调用而自动运行。
2.动态注册
动态注册需要在代码中动态的指定广播地址并注册,通常我们是在activity或service注册一个广播,下面我们就来看一下注册的代码:
myreceiver receiver = new myreceiver();
intentfilter filter = new intentfilter();
filter.addaction(“android.intent.action.my_broadcast”);
registerreceiver(receiver, filter);
注意,registerreceiver是android.content.contextwrapper类中的方法,activity和service都继承了contextwrapper,所以可以直接调用。在实际应用中,我们在activity或service中注册了一个broadcastreceiver,当这个activity或service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在特定的地方执行解除注册操作:
@override
protected void ondestroy() {
super.ondestroy();
unregisterreceiver(receiver);
}
执行这样行代码就可以解决问题了。注意,这种注册方式与静态注册相反,不是常驻型的,也就是说广播会跟随程序的生命周期。
我们可以根据以上任意一种方法完成注册,当注册完成之后,这个接收者就可以正常工作了。我们可以用以下方式向其发送一条广播:
public void send(view view) {
intent intent = new intent(“android.intent.action.my_broadcast”);
intent.putextra(“msg”, “hello receiver.”);
sendbroadcast(intent);
}
注意,sendbroadcast也是android.content.contextwrapper类中的方法,它可以将一个指定地址和参数信息的intent对象以广播的形式发送出去。
上面的例子只是一个接收者来接收广播,如果有多个接收者都注册了相同的广播地址,又会是什么情况呢,能同时接收到同一条广播吗,相互之间会不会有干扰呢?这就涉及到普通广播和有序广播的概念了。
1.普通广播(无序广播)
普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。
为了验证以上论断,我们新建三个broadcastreceiver,演示一下这个过程,firstreceiver、secondreceiver和thirdreceiver的代码如下:
public class firstreceiver extends broadcastreceiver {
private static final string tag = “normalbroadcast”;
@override
public void onreceive(context context, intent intent) {
string msg = intent.getstringextra(“msg”);
log.i(tag, “firstreceiver: ” msg);
}
}
public class secondreceiver extends broadcastreceiver {
private static final string tag = “normalbroadcast”;
@override
public void onreceive(context context, intent intent) {
string msg = intent.getstringextra(“msg”);
log.i(tag, “secondreceiver: ” msg);
}
}
public class thirdreceiver extends broadcastreceiver {
private static final string tag = “normalbroadcast”;
@override
public void onreceive(context context, intent intent) {
string msg = intent.getstringextra(“msg”);
log.i(tag, “thirdreceiver: ” msg);
}
}
然后再次点击发送按钮,发送一条广播,控制台打印如下:
0_13209098830cao.gif
看来这三个接收者都接收到这条广播了,我们稍微修改一下三个接收者,在onreceive方法的最后一行添加以下代码,试图终止广播:
abortbroadcast();
2.有序广播
有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。
为了演示有序广播的流程,我们修改一下上面三个接收者的代码,如下:
public class firstreceiver extends broadcastreceiver {
private static final string tag = “orderedbroadcast”;
@override
public void onreceive(context context, intent intent) {
string msg = intent.getstringextra(“msg”);
log.i(tag, “firstreceiver: ” msg);
bundle bundle = new bundle();
bundle.putstring(“msg”, msg “@firstreceiver”);
setresultextras(bundle);
}
}
public class secondreceiver extends broadcastreceiver {
private static final string tag = “orderedbroadcast”;
@override
public void onreceive(context context, intent intent) {
string msg = getresultextras(true).getstring(“msg”);
log.i(tag, “secondreceiver: ” msg);
bundle bundle = new bundle();
bundle.putstring(“msg”, msg “@secondreceiver”);
setresultextras(bundle);
}
}
public class thirdreceiver extends broadcastreceiver {
private static final string tag = “orderedbroadcast”;
@override
public void onreceive(context context, intent intent) {
string msg = getresultextras(true).getstring(“msg”);
log.i(tag, “thirdreceiver: ” msg);
}
}
我们注意到,在firstreceiver和secondreceiver中最后都使用了setresultextras方法将一个bundle对象设置为结果集对象,传递到下一个接收者那里,这样以来,优先级低的接收者可以用getresultextras获取到最新的经过处理的信息集合。
代码改完之后,我们需要为三个接收者注册广播地址,我们修改一下androidmainfest.xml文件:
我们看到,现在这三个接收者的多了一个android:priority属性,并且依次减小。这个属性的范围在-1000到1000,数值越大,优先级越高。
现在,我们需要修改一下发送广播的代码,如下:
public void send(view view) {
intent intent = new intent(“android.intent.action.my_broadcast”);
intent.putextra(“msg”, “hello receiver.”);
sendorderedbroadcast(intent, “scott.permission.my_broadcast_permission”);
}
注意,使用sendorderedbroadcast方法发送有序广播时,需要一个权限参数,如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递,这样的软件就必须声明接收短信的权限。
所以我们在androidmainfest.xml中定义一个权限:
android:name=”scott.permission.my_broadcast_permission” />
然后声明使用了此权限:
然后我们点击发送按钮发送一条广播,控制台打印如下:
0_1320913997fkkj.gif
我们看到接收是按照顺序的,第一个和第二个都在结果集中加入了自己的标记,并且向优先级低的接收者传递下去。
既然是顺序传递,试着终止这种传递,看一看效果如何,我们修改firstreceiver的代码,在onreceive的最后一行添加以下代码:
abortbroadcast();
然后再次运行程序,控制台打印如下:
0_1320914377loyl.gif
3.粘性广播
发送粘性广播使用sendstickybroadcast()字面意思是发送粘性的广播,使用这个api需要权限android.manifest.permission.broadcast_sticky,粘性广播的特点是intent会一直保留到广播事件结束,而这种广播也没有所谓的10秒限制,10秒限制是指普通的广播如果onreceive方法执行时间太长,超过10秒的时候系统会将这个广播置为可以干掉的candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不执行。
4.本地广播
本地广播是在应用进程内进行的广播,相对于普通广播有如下优点:
1.效率比普通广播高,普通广播是依靠binder实现的,本地广播是handler实现的。
2.比普通广播安全,普通广播全局都可以接受,本地广播只有应用进程内才可以接收到。
下面是本地广播的实现:
public class mainactivity extends actionbaractivity {
private button button;
private textview text;
private myreceiver receiver;
private intentfilter filter;
private context context;
private static final string my_broadcast_tag = “com.example.localbroadcasttest”;
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
context = getapplicationcontext();
receiver = new myreceiver();
filter = new intentfilter();
filter.addaction(my_broadcast_tag);
button = (button) findviewbyid(r.id.button);
text = (textview) findviewbyid(r.id.text);
button.setonclicklistener(new view.onclicklistener() {
@override
public void onclick(view view) {
intent intent = new intent();
intent.setaction(my_broadcast_tag);
intent.putextra(“message”, “hello~”);
localbroadcastmanager.getinstance(context).sendbroadcast(intent);
}
});
}
@override
protected void onresume() {
super.onresume();
localbroadcastmanager.getinstance(context).registerreceiver(receiver, filter);
}
@override
protected void onpause() {
super.onpause();
localbroadcastmanager.getinstance(context).unregisterreceiver(receiver);
}
class myreceiver extends broadcastreceiver {
@override
public void onreceive(context arg0, intent arg1) {
string message = arg1.getstringextra(“message”);
text.settext(“接受到广播:\ntext = ” message);
}
}
}
在最后在说一下广播接受者的生命周期以及一下细节部分:
1.广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onreceive()方法结束之后销毁。
2.广播接收者中不要做一些耗时的工作,否则会弹出application no response错误对话框。
3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉。
4.耗时的较长的工作最好放在服务中完成。
文章由思创斯整理,转载请注明出处:https://ispacesoft.com/141160.html