一、广播定义
1.Broadcast(广播)
它是一种广泛运用于应用程序之间传输信息的机制。
2.BroadcastReceiver(广播接收器)
它是对发送出来的广播进行过滤接收并响应的一类组件,用来接收来自系统和应用程序中的广播。
3.用途:业务逻辑在BroadcastReceiver中的onReceive()方法中实现,一般用来启动一个Activity、Service或者标题通知
- 当开机完成后,系统会发出一条广播;
- 当网络状态发生变化时,系统会发出一条广播;
- 当电池电量发生改变时,系统会发出一条广播;
- 等等
4.使用方法:
- 发送:将信息装入一个Intent对象intent(如Action、Category),然后调用如下方法之一发送广播:
sendBroadcast(intent)和sendOrderBroadcast(intent, null)
- 接收:当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent匹配,若匹配则调用BroadcastReceiver的onReceive()方法,该方法需要在定义BroadcastReceiver对象时去复写。
5.注意
- BroadcastReceiver生命周期大概只有10秒,不能在其中执行耗时操作
- 不能使用子线程,因为子线程可能还未执行完,BroadcastReceiver生命周期已经结束,那么子线程也会被杀
死
- 可以在BroadcastReceiver的onReceive()方法中通过发送Intent给Service,由Service来完成耗时操作
6.注册方式:
- 动态注册:在java代码中完成注册,一般在Activity的onCreate()中调用registerReceiver(mReceiver,mIntentFilter)注册广播接收器,在onDestroy()中调用unregusterReceiver(mReceiver)来注销广播。动态注册的广播接收器只能在程序启动后,才能接收广播,因为它在onCreate(0方法中注册的。典型的不能接收开机广播,因为刚开机
时,该程序还未启动,才
能接收广播;
- 静态注册:在AndroidManifest.xml中完成注册,添加<receiver />标签。静态注册的广播接收器不需要运行该程序也会收到相应的广播。可以在<intent-filter>标签中添加优先级来优先监听有序广播。
7.广播的种类:
- 普通广播:异步、无序、所有BroadcastReceiver都可以监听;调用sendBroadcast(intent)发送标准广播
- 有序广播:同步、按照接收者的优先级顺序接收广播、可以被前面的BroadcastReceiver截断,或被篡改后继
续传递给下一个接收器;调用sendOrderedBroadcast(intent, null)来发送有序广播。接收广播方法,不 区分有序还是标准广播。
8.广播接收器的作用域
- 系统广播:可以用来接收本程序或者其它应用程序(系统)的广播,包括普通广播和有序广播
- 本地广播:只能够接收来自本程序内部发出的广播,避免出现关键性数据泄露,造成安全性问题。只能动态注 册,需要用到LocalBroadcastManager来管理本地广播。
发送本地广播:
l
ocalBroadcastManager.sendBroadcast(intent);
注册本地广
播:
localBroadcastManager.registerReceiver(localReceiver,intentFilter)
;
注销本地广播:l
ocalBroadcastManager.unregisterReceiver(localReceiver)
二、参考代码
本文定义了三个BroadcastReceiver,分别是如下:
1.静态注册的MyBroadcastReceiver,用来测试发送携带数据的普通/有序广播,并且能够接收到广播取出数据;
2.静态注册的BootCompleteReceiver,用来测试接收手机开机时系统发出的开机广播;
3.动态注册的NetworkStateChangeReceiver,用来测试当手机出现网络状态变化时,判断当前网络可用或不可用。
MyBroadcastReceiver
package com.steven.dynamicbroadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
/**
* Created by Steven on 2016/9/19.
*/
//静态注册的一个自定义广播,监听发送的标准广播:MY_BROADCAST
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String s = intent.getStringExtra("test");
Toast.makeText(context, "I receive a MyBroadcastReceiver,传递过来的数据是:" + s, Toast.LENGTH_SHORT).show();
Log.d("Steven", "收到自定义广播的数据是:" + s);
}
}
BootCompleteReceiver
package com.steven.dynamicbroadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
/**
* Created by Steven on 2016/9/19.
*/
//静态注册的一个系统的监听开机广播,在程序未运行起来的时候也能监听
//An (non-static) inner class cannot be instantiated by Android via the AndroidManifest.xml
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("steven", "**** BootCompleteReceiver ****");
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}
MainActivity
package com.steven.dynamicbroadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkStateChangeReceiver receiver;
private Button btn_send_broadcast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_send_broadcast = (Button) findViewById(R.id.btn_send_broadcast);
//2. 生成一个BroadcastReceiver
receiver = new NetworkStateChangeReceiver();
//3. 生成IntentFilter对象,并添加action,指定要监听的广播类型:网络状态变化
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//4 .注册一个广播
registerReceiver(receiver, intentFilter);
//发送一个自定义标准/有序广播MY_BROADCAST
btn_send_broadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.steven.dynamicbroadcasttest.MY_BROADCAST");
intent.putExtra("test", "MY_BROADCAST"); //intent此时可以携带数据一起发送
//sendBroadcast(intent); //发送标准广播
sendOrderedBroadcast(intent, null); //发送有序广播
}
});
}
//5. 动态定义的广播,一定要在退出程序时,注销广播
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
// 1.动态定义一个BroadcastReceiver,复写onReceive()抽象方法,实现收到广播的具体逻辑业务:网络变化时判断可用还是不可用
public class NetworkStateChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//Toast.makeText(context, "Network State Changed", Toast.LENGTH_SHORT).show();
//通过Activity中的getSystemService()方法获得一个用于管理网络连接的ConnectivityManager实例
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//通过调用它的getActiveNetworkInfo(),获得NetworkInfo实例
NetworkInfo info = manager.getActiveNetworkInfo();
//网络可用状态下
if (info != null && info.isAvailable()) {
Toast.makeText(context, "Network is available", Toast.LENGTH_SHORT).show();
//网络不可用
} else {
Toast.makeText(context, "Network is not available", Toast.LENGTH_SHORT).show();
}
}
}
}
AndroidManifest.xml:静态注册的广播接收器需要在该文件注册,同时监听开机广播和网络状态需要注册系统权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.steven.dynamicbroadcasttest" >
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiver">
<intent-filter android:priority="100">
<action android:name="com.steven.dynamicbroadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
</application>
</manifest>