1、什么是安卓的Broadcast?
安卓的四大组件之一,是一种广泛应用在应用程序之间传输信息的机制。
2、什么是安卓的BroadcastReceiver?
是对发送出来的广播进行过滤接收并响应的一类组件,它就是用来接收来自系统和应用中的广播。例如系统的广播有开机广播: 系统在开机时候会发送开机广播,程序接收到之后,能进行开机自启动。 网络状态改变广播: 3g变wifi、网络断开等。电量改变广播等等。。。
(1).同一app内部的同一组件内的消息通信(单个或多个线程之间);
(2).同一app内部的不同组件之间的消息通信(单个进程);
(3).同一app具有多个进程的不同组件之间的消息通信;
(4).不同app之间的组件之间消息通信;
(5).Android系统在特定情况下与App之间的消息通信。
3、Anroid为什么要这样设计?
大大减少开发工作量和开发周期。作为开发者,只需要掌握BroadcastReceiver
4、怎么理解Broadcast和BroadcastReceiver ?
Broadcast就像现实中的广播电台,他发广播信号来,然后我们用收音机来接收,然后处理,并且播放出声音, BroadcastReceiver就相当于那台收音机。
5、使用方法
发送:
把信息装入一个Intent对象(如:Action、Category),通过调相应的方法将Intent对象以广播的方式发送出去:
sendBroadcast();
sendOrederBroadcast();
sendStickyBroadcast();
接收:
当Intent发送之后,所有已经注册vedBroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceiver()方法。所以当我们定义一个BroadcastReceiver的时候,都需要实现onReceiver()方法。
注意:
BroadcastReceiver需要注册
静态注册
代码动态注册
6、注意!
BroadReceiver生命周期只有十秒左右,不能直接执行耗时操作,不然会出现ANR(应用程序无响应),也不能用子线程来做,因为每次广播来的时候都会创建一个Reveiver对象,并且调用onReceiver,执行完之后 ,对象会立刻被销毁,子线程也没了
要做耗时操作的话,应该通过发送Intent给Service,由Service来完成。
动态注册广播接受者的话要在Destory回调事件进行unregister
7、广播的分类
普通广播 (Normal broadcast)
- 所有监听该广播接受者都可以监听到该广播
- 同级别接收先后顺序是随机的(无序)
- 级别低的后收到广播
- 接收器不能截断广播的继续传播,也不能处理广播
- 同级别动态注册高于静态注册
有序广播 (Oredered broadcast)
- 按照接收者的优先顺序来接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大优先级越高,可以终止广播的继续传播,接受者可以修改intent的内容。
- 同级别接收顺序是随机的
- 级别低的后收到
- 能截断广播的继续传播,高级别的广播接收器接收广播后能决定时候截断。
- 能处理广播
- 同级别动态注册高于静态注册
异步广播 (粘滞性滞留广播) ps:已被弃用
- 不能处理结果给下一个接收者,无法终止广播。
- 一直存在
- 可以先发送广播,再注册接收器
- 需要在清单文件添加android.permission.BROADCAST_STICKY权限
动态注册(在代码中注册广播接收器)
registerReceiver(networkChangeReceiver,intentFilter);
实例
MainActivity.class:
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
//当网络发生变化时,系统发出的值就是 android.net.conn.CONNECTIVITY_CHANGE,也就是说我们的
//广播接收器想要监听什么广播
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//实例化一个广播接收器
networkChangeReceiver = new NetworkChangeReceiver();
//注册广播 第一个参数是我们要处理广播的广播接收器,第二个参数是意图过滤器
registerReceiver(networkChangeReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消注册
unregisterReceiver(networkChangeReceiver);
}
//一个广播接收器
class NetworkChangeReceiver extends BroadcastReceiver{
//每当网络状态发生变化时,onReceive()方法就会得到执行
@Override
public void onReceive(Context context, Intent intent) {
//网络连接服务类
ConnectivityManager connectivityManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
//获得网络连接实例
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo!=null&&networkInfo.isAvailable()){
Toast.makeText(context,"network is available",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"network is unavailable",Toast.LENGTH_SHORT).show();
}
}
}
}
静态注册(在AndroidManifest.xml中注册广播接受器)
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
enabled:表示是否启用这个播放器
exported:用于指示该服务是否能够被其他应用程序组件调用或跟它交互。
实例
MainActivity.class:
public class MainActivity extends AppCompatActivity {
public static TextView textMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textMessage = (TextView) findViewById(R.id.message);
}
}
MyBroadcastReceiver.class:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"收到一条短信",Toast.LENGTH_SHORT).show();
StringBuilder builder = new StringBuilder();
//pdus是一个object类型的数组,每一个object都是一个byte[]字节数组,每一项为一条短信。
Object[] pduses= (Object[])intent.getExtras().get("pdus");
for(Object pdus: pduses){
byte[] pdusmessage = (byte[])pdus;
SmsMessage sms = SmsMessage.createFromPdu(pdusmessage);
String mobile = sms.getOriginatingAddress();//发送短信的手机号码
String content = sms.getMessageBody(); //短信内容
Date date = new Date(sms.getTimestampMillis());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date); //得到发送时间
builder.append("号码: "+mobile+"\n内容: "+content+"\n时间: "+time+"\n");
}
MainActivity.textMessage.setText(builder.toString());
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ukulele.broadcasttest">
<uses-permission android:name="android.permission.RECEIVE_SMS" /><!--接收短信权限-->
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
</manifest>
Normal Broadcast 普通广播
sendBroadcast(intent);//发送广播
实例:
MainActivity.class:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.seond_broadcast);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcasttest.My_NORMAL_BROADCAST");
intent.putExtra("msg","普通广播");
sendBroadcast(intent);
}
});
}
}
MyNormalBroadcast.class:
public class MyNormalBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyNormalBroadcast ",intent.getStringExtra("msg"));
}
}
AndroidManifest.xml:
<receiver
android:name=".MyNormalBroadcast"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcasttest.My_NORMAL_BROADCAST"/>
</intent-filter>
</receiver>
intent-filter android:priority=”1000” 普通广播也可设置先后顺序
logcat:
MyNormalBroadcast : 普通广播
Oredered Broadcast 有序广播
sendOrderedBroadcast(intent, null);//发送广播
有序广播实例:
MainActivity.class:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.seond_broadcast);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcasttest.My_OREDERED_BROADCAST");
intent.putExtra("name","总统");
intent.putExtra("content","快去把事情办了");
sendOrderedBroadcast(intent,null);
}
});
}
}
MyOrederedBroadcast3.class:
public class MyOrederedBroadcast3 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
String content = intent.getStringExtra("content");
Log.d("MyOrederedBroadcast3","省长收到了"+name+"发过来的消息,消息内容是"+content);
Bundle bundle = new Bundle();
bundle.putString("name","省长");
bundle.putString("content","快去把事情办了");
setResultExtras(bundle);
//abortBroadcast(); 截断广播
}
}
MyOrederedBroadcast2.class:
public class MyOrederedBroadcast2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//true代表如果前面的接收器没有存放数据,则自动创建一个空的Bundle对象,false则表示如果前面的接收器如果没有存放任何数据则返回null。
Bundle bundle = getResultExtras(true);
String name = bundle.getString("name");
String content = bundle.getString("content");
Log.d("MyOrederedBroadcast2","市长收到了"+name+"发来的消息,消息内容是"+content);
bundle.putString("name","市长");
bundle.putString("content","快去把事情办了");
setResultExtras(bundle);
//abortBroadcast(); 截断广播
}
}
MyOrederedBroadcast.class:
public class MyOrederedBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(true);
String name = bundle.getString("name");
String content = bundle.getString("content");
Log.d("MyOrederedBroadcast","县长收到了"+name+"发来的消息,消息内容是"+content+
"。县长说:“好的市长,我这就去办”。");
}
}
AndroidManifest.xml:
<receiver
android:name=".MyOrederedBroadcast"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="100">
<action android:name="com.example.broadcasttest.My_OREDERED_BROADCAST"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyOrederedBroadcast2"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="200">
<action android:name="com.example.broadcasttest.My_OREDERED_BROADCAST"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyOrederedBroadcast3"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="300">
<action android:name="com.example.broadcasttest.My_OREDERED_BROADCAST"/>
</intent-filter>
</receiver>
<!--优先级的设定 MyReceiver3大于MyReceiver2,MyReceiver2大于MyReceiver,优先级的范围-1000~1000 -->
logcat:
MyOrederedBroadcast3: 省长收到了总统发过来的消息,消息内容是快去把事情办了
MyOrederedBroadcast2: 市长收到了省长发来的消息,消息内容是快去把事情办了
MyOrederedBroadcast: 县长收到了市长发来的消息,消息内容是快去把事情办了。县长说:“好的市长,我这就去办”。
Sticky Broadcast粘性广播
实例
MainActivity.class:
public class MainActivity extends AppCompatActivity {
private MyStickyBroadcast myStickyBroadcast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.seond_broadcast);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcasttest.My_STICKY_BROADCAST");
intent.putExtra("msg","粘性广播");
//先发送
sendStickyBroadcast(intent);
//后注册
IntentFilter intentFilter = new IntentFilter("com.example.broadcasttest.My_STICKY_BROADCAST");
myStickyBroadcast = new MyStickyBroadcast();
registerReceiver(myStickyBroadcast,intentFilter);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消注册
unregisterReceiver(myStickyBroadcast);
}
class MyStickyBroadcast extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyStickyBroadcast",intent.getStringExtra("msg"));
}
}
}
logcat:
MyStickyBroadcast: 粘性广播
AndroidManifest.xml:
<!--异步广播必须添加一条权限-->
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
本地广播
前面我们发出的全局广播可以被其他应用程序接收到,同样我们也可以接受来自于其他应用程序的广播。这样就容易引起安全问题,比如我们发出的关键性数据可能被其他应用程序截获,或者接收到其他应用程序向我们发送的各种垃圾广播。
为了解决广播的安全问题,Android引用了一套本地广播机制,使用这套机制发出的广播只能够在应用程序的内部进行传递。
实例
MainActivity.class:
public class MainActivity extends AppCompatActivity {
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//本地广播管理器
localBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter("com.example.broadcasttest.My_LOCAL_RECEIVER");
localReceiver = new LocalReceiver();
//使用本地广播管理器对广播接收器进行注册
localBroadcastManager.registerReceiver(localReceiver,intentFilter);
Button button = (Button) findViewById(R.id.seond_broadcast);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcasttest.My_LOCAL_RECEIVER");
intent.putExtra("msg","本地广播");
localBroadcastManager.sendBroadcast(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
//本地广播接收器
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("LocalReceiver",intent.getStringExtra("msg"));
}
}
}