您的位置:首页 > 移动开发 > Android开发

Android的广播使用

2015-11-17 11:38 423 查看
原文地址:http://www.it165.net/pro/html/201408/20532.html

广是一种广泛运用在应用程序之间传输信息的机制,android中的广播用于监听系统事件或应用程序事件!android中的广播包括普通广播、有序广播以及异步广播(粘性广播)!

广播又有常驻型广播和非常驻型广播,常驻型广播是在xml中进行注册的,当应用程序关闭后,如果有对应的广播发送过来,广播接收器还是能够被激活;非常驻型广播是在代码中进行注册的,当应用程序关闭,广播也就取消了,我们可以在Activity中的onCreate或者onResume方法中注册广播,然后在onDestory或者onPause方法中取消注册广播;

注意:如果是非常驻型广播,应用程序关闭后,必须取消注册广播,否则会抛出异常!!

普通广播的发送

普通广播的发送使用方式:

sendBroadcast(Intent intent):intent表示意图,所有匹配该广播的意图都能收到该广播信息

sendBroadcast(intent,String receiverPermission);intent与上面一样,receiverPermission表示权限,与之匹配权限的广播才能接收到相应的广播,如果为null,表示不经许可的要求!

一、使用sendBroadcast(Intent intent)发送广播

1)通过代码注册非常驻型广播:

view
sourceprint?

01.
//定义两个广播接收者


02.
BroadcastReceiver
receiver1=
new
BroadcastReceiver()
{


03.
@Override


04.
public
void
onReceive(Context
context,Intent intent) {


05.
System.out.println(
"receiver1
started!"
);


06.
}


07.
};


08.
BroadcastReceiver
receiver2=
new
BroadcastReceiver()
{


09.
@Override


10.
public
void
onReceive(Context
context,Intent intent) {


11.
System.out.println(
"receiver2
started!"
);


12.
}


13.
};


14.


15.
@Override


16.
protected
void
onCreate(Bundle
savedInstanceState) {


17.
super
.onCreate(savedInstanceState);


18.
//注册广播


19.
IntentFilter
filter=
new
IntentFilter();


20.
filter.addAction(
"com.xin.action.broadcast"
);


21.
registerReceiver(receiver1,
filter);


22.
registerReceiver(receiver2,
filter);


23.
}


24.


25.
@Override


26.
protected
void
onPause()
{


27.
super
.onPause();


28.
//取消注册广播


29.
unregisterReceiver(receiver1);


30.
unregisterReceiver(receiver2);


31.
}


代码注册属于非常驻型广播,我们需在Activity相应的生命周期中取消注册广播:unregisterReceiver

2)通过xml文件注册常驻型广播,此时的MyBroadcast1、MyBroadcast2为两个广播类:

view
sourceprint?

1.
public
class
MyBroadcast1
extends
BroadcastReceiver{


2.


3.
@Override


4.
public
void
onReceive(Context
context,Intent intent) {


5.
System.out.println(
"MyBroadcast1
started!"
);


6.
}


7.
}


view
sourceprint?

1.
public
class
MyBroadcast2
extends
BroadcastReceiver{


2.


3.
@Override


4.
public
void
onReceive(Context
context,Intent intent) {


5.
System.out.println(
"MyBroadcast2
started!"
);


6.
}


7.
}


AndroidManifest.xml中的application中添加:

view
sourceprint?

01.
<receiver
android:name=
".MyBroadcast1"
>


02.
<intent-filter>


03.
<action
android:name=
"com.xin.action.broadcast"
/>


04.
</intent-filter>


05.
</receiver>


06.
<receiver
android:name=
".MyBroadcast2"
>


07.
<intent-filter>


08.
<action
android:name=
"com.xin.action.broadcast"
/>


09.
</intent-filter>


10.
</receiver>


代码中的IntentFilter和xml文件中的intent-filter是一样的,都是Intent意图,表示Intent(String actionName)发送出去的广播能被哪些广播接收者所接收!

3)广播的发送:与之匹配的intent意图的广播将被激活

view
sourceprint?

1.
Intent
intent=
new
Intent(
"com.xin.action.broadcast"
);


2.
sendBroadcast(intent);


输出结果为:MyBroadcast1started,MyBroadcast2started!!

二、使用sendBroadcast(intent,String receiverPermission)发送广播

第二个参数的介绍如上面所示,指的是一个权限,我们需在AndroidManifest.xml中声明一个权限:

view
sourceprint?

1.
<permission
android:name=
"com.xin.permission"
android:protectionLevel=
"normal"
/>


里面还有很多的属性可供我们选择,大家可以去自己去了解一下;

然后我们的发送广播方和接收广播方都需要该权限定义:

发送广播方使用该权限:

view
sourceprint?

1.
<uses-permission
android:name=
"com.xin.permission"
/>


通过方法发送广播:sendBroadcast(intent,"com.xin.permission");其中第二个参数表示我们定义的权限name

接收方声明广播权限:

view
sourceprint?

1.
<receiver
android:name=
".MyBroadcast1"
android:permission=
"com.xin.permission"
>


2.
<intent-filter>


3.
<action
android:name=
"com.xin.action.broadcast"
/>


4.
</intent-filter>


5.
</receiver>


这样,使用带权限的广播就定义好了,我们在发送方和接收方都需要给权限进行定义,否则消息发送不过去!

注意,通过sendBroadcast(intent,"com.xin.permission");发送的广播,并不一定需要在receiver中添加android:permission才能接收到,测试发现,没有添加这个也能接收到:

view
sourceprint?

1.
<receiver
android:name=
".MyBroadcast2"
>


2.
<intent-filter>


3.
<action
android:name=
"com.xin.action.broadcast"
/>


4.
</intent-filter>


5.
</receiver>


有序广播的发送

顾名思义,有序广播就是广播的发送是按照顺序进行的,它根据优先级别的定义android:priority的高低来进行有序发送,一个接受完发给下一个接收,优先级越高,表示它接收到的广播级别高,android:priority的范围一般是在-1000到1000之间;

有序广播和普通广播之间的区别:

有序广播和无序广播的区别:我们发送完无序广播之后,我们不知道谁先接收谁后接收,更不要说当这个接收了之后不要再发给另外的了。而有序广播就可以做到这一点,它通过设置优先级可以决定广播接受者的顺序。

有序广播的发送方式:

sendOrderedBroadcast(intent,receiverPermission);

sendOrderedBroadcast(intent,receiverPermission,resultReceiver,

scheduler,initialCode,initialData,initialExtras)

意图,广播,所有匹配的这一意图将接收机接收广播。

receiverPermission 这是权限,一个接收器必须持以接收您的广播。如果为 null ,不经许可的要求。

resultReceiver 您自己 BroadcastReceiver 来当作最后的广播接收器。

调度自定义处理程序,用以安排 resultReceiver 回调 ; 如果为 null 将语境中的主线程举行。

initialCode 一种结果代码的初始值。通常为 Activity.RESULT_OK 。这个值是 -1 ;为其他 int 型 也可以,如 0,1,2;

initialData 一种结果数据的初始值。通常情况下为空 ,是 String 类型 ;

initialExtras 一种结果额外的初始值。通常情况下为空 ,是 Bundle;
有序广播需注意方面:

1, 该广播的级别有级别之分,级别数值是在 -1000 到 1000 之间 ,值越大 ,优先级越高;

2, 同级别接收是先后是随机的,再到级别低的收到广播;

3, 同级别接收是先后是随机的,如果先接收到的把广播截断了,同级别的例外的接收者是无法收到该广播的,截断广播的方式:abortBroadcast() ;

4 ,能截断广播的继续传播,高级别的广播收到该广播后,可以决定把该钟广播是否截断掉。

5 ,实验现象,在这个方法发来的广播中,代码注册方式中,收到广播先后次序为:注明优先级的、代码

代码演示:

下面给大家演示一下发送有序广播,并且通过Intent在广播之间传递数据,因为关于权限那块上面已经说了,所以在有序广播这里就不再描述了,通过sendOrderedBroadcast(intent,receiverPermission);方法发送有序广播,第二个参数就设置为null了:这里我们通过xml注册广播

1)定义广播

view
sourceprint?

01.
public
class
MyBroadcast2
extends
BroadcastReceiver{


02.
@Override


03.
public
void
onReceive(Context
context,Intent intent) {


04.
System.out.println(
"MyBroadcast2
started!"
);


05.
//接收sendOrderedBroadcast传递过来的Intent中的参数


06.
System.out.println(intent.getStringExtra(
"test"
));


07.
//添加另一个参数


08.
Bundle
bundle=
new
Bundle();


09.
bundle.putString(
"test2"
,
"我是从MyBroadcast2中存储的数据"
);


10.
//将其封装为Bundle对象,让下一个广播接收


11.
setResultExtras(bundle);


12.
}


13.
}


view
sourceprint?

01.
public
class
MyBroadcast1
extends
BroadcastReceiver{


02.


03.
@Override


04.
public
void
onReceive(Context
context,Intent intent) {


05.
System.out.println(
"MyBroadcast
started!"
);


06.
//接收sendOrderedBroadcast传递过来的Intent中的参数


07.
System.out.println(intent.getStringExtra(
"test"
));


08.
//得到从上一个广播中携带过来的另一个数据


09.
Bundle
bundle=getResultExtras(
true
);


10.
System.out.println(bundle.getString(
"test2"
));


11.
}


12.
}


2)在AndroidManifest.xml中声明广播:

view
sourceprint?

01.
<receiver
android:name=
".MyBroadcast1"
>


02.
<intent-filter
android:priority=
"900"
>


03.
<action
android:name=
"com.xin.action.broadcast"
/>


04.
</intent-filter>


05.
</receiver>


06.
<receiver
android:name=
".MyBroadcast2"
>


07.
<intent-filter
android:priority=
"1000"
>


08.
<action
android:name=
"com.xin.action.broadcast"
/>


09.
</intent-filter>


上面声明的广播中,MyBroadcast2比Mybroadcast1的优先级高!

3)发送有序广播

view
sourceprint?

1.
Intent
intent=
new
Intent(
"com.xin.action.broadcast"
);


2.
intent.putExtra(
"test"
,
"我是sendOrderedBroadcast发送过来的数据!"
);


3.
sendOrderedBroadcast(intent,
null
);


测试结果:



因为Mybroadcast2的优先级(1000)比Mybroadcast1(900)的高,所以广播通过sendOrderedBroadcast发送出去后,首先被Mybroadcast2接收,然后再Mybroadcast2中通过setResultExtras设置了另一些参数一起传到Mybroadcast1,然后Mybroadcast1接收到广播,也通过getResultExtras(true)接收从Mybroadcast2中携带过来的数据,所以出现上面的结果!

经测试发现,在使用sendBroadcast时候,如果在BroadcastReceiver中使用setResultExtras或者getResultExtras,程序会报错,因为它发送的不是有序广播!

注意:

1、如果是在代码中注册的,我们可以通过filter.setPriority(1000);来设置其优先级,这里就不举例说明了!

2、如果我们想让有序广播在一个BroadcastReceiver中接收后,不再往下一个广播执行,可以调用其abortBroadcast();中断广播的发送,后面的广播将接收不到!

粘性广播(异步广播)的发送

在网上专业名称各不一样,有人讲它是粘性广播,也有人说它是异步广播,先不讨论它的专业名词的问题了,先来让我们了解它有什么用,它与普通广播的区别就是当广播取消注册后,然后发送一个粘性广播,广播重新注册后仍然能接收到粘性广播发送过来的消息!

普通广播与粘性广播最大的区别:

我们知道,我们先注册广播,然后发送广播,那么无论是什么广播都能被接收到,那么如果我们先发送广播,后注册广播呢:

普通广播:未注册广播-->发送广播-->注册广播-->接收不到广播

粘性广播:未注册广播-->发送广播-->注册广播-->能接收到广播,并且能接收到多次发送广播的最后一条广播信息

这就是两者之间的区别,下面我们通过代码的方式给大家举一个例子,我们的广播是在代码中注册的非常驻型广播:

页面只包含三个测试按钮:



我们在注册广播的Activity中注册广播:RegisterActivity,在其生命周期的onPause方法中取消注册广播unregisterBr

view
sourceprint?

01.
//定义广播


02.
BroadcastReceiver
receiver=
new
BroadcastReceiver()
{


03.
@Override


04.
public
void
onReceive(Context
context,Intent intent) {


05.
String
action=intent.getAction();


06.
int
count=intent.getIntExtra(
"count"
,
0
);


07.
System.out.println(
"action="
+action+
",count="
+count);


08.
}


09.
};


10.


11.
//注册广播


12.
@Override


13.
protected
void
onCreate(Bundle
savedInstanceState) {


14.
super
.onCreate(savedInstanceState);


15.
setContentView(R.layout.register);


16.
IntentFilter
filter=
new
IntentFilter();


17.
//添加广播Action


18.
filter.addAction(
"com.xin.action.broadcast"
);


19.
filter.addAction(
"com.xin.action.sticky.broadcast"
);


20.
registerReceiver(receiver,
filter);


21.
}


22.


23.
//取消注册广播


24.
@Override


25.
protected
void
onPause()
{


26.
super
.onPause();


27.
System.out.println(
"RegisterBroadActivity
onPause!"
);


28.
unregisterReceiver(receiver);


29.
}


在MainActivity中发送广播:

view
sourceprint?

01.
//定义一个变量,来统计点击发送粘性广播的次数,然后测试粘性广播的接收是不是最后一条广播


02.
private
int
count;


03.
@Override


04.
public
void
onClick(View
v) {


05.
Intent
intent=
null
;


06.
switch
(v.getId()){


07.
case
R.id.btn_send1:
//发出广播sendBroadcast


08.
intent=
new
Intent(
"com.xin.action.broadcast"
);


09.
sendBroadcast(intent);


10.
break
;


11.
case
R.id.btn_send2:
//发出粘性广播sendStickyBroadcast


12.
count++;


13.
intent=
new
Intent(
"com.xin.action.sticky.broadcast"
);


14.
intent.putExtra(
"count"
,
count);


15.
sendStickyBroadcast(intent);


16.
break
;


17.
case
R.id.register:
//启动注册广播页面


18.
intent=
new
Intent(MainActivity.
this
,RegisterBroadActivity.
class
);


19.
startActivity(intent);


20.
break
;


21.
}


22.
}


23.


24.
@Override


25.
protected
void
onResume()
{


26.
super
.onResume();


27.
count=
0
;


28.
System.out.println(
"MainActivity
onResume!"
);


29.
}


注意,发送粘性广播,我们需要在AndroidManifest.xml中添加能够发送粘性广播的权限,否则会报错:

view
sourceprint?

1.
<uses-permission
android:name=
"android.permission.BROADCAST_STICKY"
/>


测试及结论:

当我们点击发送sendBroadcast按钮3次--点击注册按钮,控制台无输出结果

当我们点击发送sendStickyBroadcast按钮4次--点击注册按钮,控制台输出结果:action=com.xin.action.sticky.broadcast,count=4

这就是普通广播和粘性广播的区别

sendBroadcast发送出去的广播,如果没有广播进行注册,那么该广告也就接收不到了,当重新注册广播后,也接收不到

sendStickyBroadcast发送出去的广播,如果没有广播进行注册,那么该广告此时也就接收不到了,当重新注册广播后,会接收到,并且会接受sendStickyBroadcast发出去的最后一条广播,所以上面的输出结果中点击发送stickybroadcast 4次,count变为4,那么当重新注册广播后,控制台会输出结果count=4;

sendStickyBroadcast发出的最后一个Intent会被保留,下次当Recevier处于活跃的 时候,又会接受到它。

当我们需要移除掉粘性广播的时候,调用方法:removeStickyBroadcast(intent);即可清除掉粘性广播

还有一个发送广播的方式:sendStickyOrderedBroadcast (),测试在这个方法发来的广播,代码注册方式中,收到广播先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没有优先级,代码注册收到为最先。

上面给大家介绍了广播操作中的几种方式:

发送广播:sendBroadcast(Intent intent)、sendBroadcast(Intent intent,String receiverPermission);

发送有序广播:sendOrderedBroadcast(Intent intent,String receiverPermission);

发送粘性广播:sendStickyBroadcast(Intent intent);

还有一种方式:sendStickyOrderedBroadcast();(未研究,不知道用的多不多)

在Android的广播操作中,我们还应该知道:

1、无论对于有序广播还是无序广播,广播接收器默认都是运行在主线程中的(main线程,即UI线程)。可以通过在程序中使用registerReceiver(receiver,filter,broadcastPermission,scheduler)方法中的最后一个参数指定要运行的广播接收器的线程。也可以在Manifest.xml文件中设置(Intent-filter标签中设置android:process)。

2、我们在代码中注册广播registerBroadcast十次,那么广播发送过来的时候会接收十次,注销广播只需一次!

3、每次广播到来时 ,会重新创建 BroadcastReceiver 对象 ,并且调用 onReceive() 方法 ,执行完以后 ,该对象即被销毁 . 当 onReceive() 方法在 10 秒内没有执行完毕, Android 会认为该程序无响应 . 所以在BroadcastReceiver 里不能做一些比较耗时的操作 ,否侧会弹出 ANR(Application NoResponse) 的对话框,如果需要完成一项比较耗时的工作 ,应该通过发送 Intent 给 Service,由 Service
来完成 . 这里不能使用子线程来解决 ,因为 BroadcastReceiver 的生命周期很短 ,子线程可能还没有结束BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 ,此时 BroadcastReceiver 的所在进程很容易在系统需要内存时被优先杀死 ,因为它属于空进程 ( 没有任何活动组件的进程 ). 如果它的宿主进程被杀死 ,那么正在工作的子线程也会被杀死 . 所以采用子线程来解决是不可靠的 .

4、耗时的操作应该通过广播启动service来执行操作

view
sourceprint?

1.
BroadcastReceiver
receiver=
new
BroadcastReceiver()
{


2.
@Override


3.
public
void
onReceive(Context
context,Intent intent) {


4.
Intent
intent=
new
Intent(context,TestService.
class
);


5.
startService(intent);


6.
}


7.
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: