广播是一种广泛运用的在应用程序之间传输信息的机制 。而 BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件;
来自普通应用程序,如一个应用程序通知其他应用程序某些数据已经下载完毕。
BroadcastReceiver 自身并不实现图形用户界面,但是当它收到某个通知后, BroadcastReceiver 可以启动 Activity 作为响应,或者通过 NotificationMananger 提醒用户,或者启动 Service 等等。
广播一般有两种分类方式
第一种 普通广播和有序广播
标准广播(Normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。
有序广播(Ordered broadcasts)则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断(abortBroadcast())正在传递的广播,这样后面的广播接收器就无法收到广播消息了。
第二种 全局广播和本地广播
全局广播 发出的广播可以被其他任何的任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播,当携带数据的时候会存在安全性问题。
本地广播 只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播,比较安全,主要通过LocalBroadcastManager来管理和发送。
与其他四大组件类似,广播接收者也是通过继承系统的BroadcastReceiver类并重写某些生命周期方法(主要是onReceive)来创建,并且需要在manifest配置文件中进行配置。
但是这里有广播接收者的特性,那就是它可以通过代码的方式进行动态的注册而非一定在manifest中进行注册。动态注册的方式往往是利用内部类的方式来实现。但是像开机启动只能通过静态的方式进行注册。
就像在上面介绍的一样,广播的发送也有两种方式即发送普通广播sendBroadcast和发送有序广播sendOrderedBroadCast。
1.发送有序广播
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; 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); } }
<receiver android:name=".FirstReceiver"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.MY_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name=".SecondReceiver"> <intent-filter android:priority="999"> <action android:name="android.intent.action.MY_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name=".ThirdReceiver"> <intent-filter android:priority="998"> <action android:name="android.intent.action.MY_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
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"); }
<permission android:protectionLevel="normal" android:name="scott.permission.MY_BROADCAST_PERMISSION" />然后使用:
<uses-permission android:name="scott.permission.MY_BROADCAST_PERMISSION" />更多关于权限的说明可以参考 这里
2.开机启动服务
我们经常会有这样的应用场合,比如消息推送服务,需要实现开机启动的功能。要实现这个功能,我们就可以订阅系统“启动完成”这条广播,接收到这条广播后我们就可以启动自己的服务了。我们来看一下BootCompleteReceiver和MsgPushService的具体实现:
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class BootCompleteReceiver extends BroadcastReceiver { private static final String TAG = "BootCompleteReceiver"; @Override public void onReceive(Context context, Intent intent) { Intent service = new Intent(context, MsgPushService.class); context.startService(service); Log.i(TAG, "Boot Complete. Starting MsgPushService..."); } }
import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MsgPushService extends Service { private static final String TAG = "MsgPushService"; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate called."); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand called."); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent arg0) { return null; } }
<!-- 开机广播接受者 --> <receiver android:name=".BootCompleteReceiver"> <intent-filter> <!-- 注册开机广播地址--> <action android:name="android.intent.action.BOOT_COMPLETED"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <!-- 消息推送服务 --> <service android:name=".MsgPushService"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.util.Log; import android.widget.Toast; public class NetworkStateReceiver extends BroadcastReceiver { private static final String TAG = "NetworkStateReceiver"; @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "network state changed."); if (!isNetworkAvailable(context)) { Toast.makeText(context, "network disconnected!", 0).show(); } } /** * 网络是否可用 * * @param context * @return */ public static boolean isNetworkAvailable(Context context) { ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo[] info = mgr.getAllNetworkInfo(); if (info != null) { for (int i = 0; i < info.length; i++) { if (info[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } } return false; } }
<receiver android:name=".NetworkStateReceiver"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
package com.scott.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.BatteryManager; import android.util.Log; public class BatteryChangedReceiver extends BroadcastReceiver { private static final String TAG = "BatteryChangedReceiver"; @Override public void onReceive(Context context, Intent intent) { int currLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); //当前电量 int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1); //总电量 int percent = currLevel * 100 / total; Log.i(TAG, "battery: " + percent + "%"); } }
<receiver android:name=".BatteryChangedReceiver"> <intent-filter> <action android:name="android.intent.action.BATTERY_CHANGED"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
Intent batteryIntent = getApplicationContext().registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); int currLevel = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); int total = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1); int percent = currLevel * 100 / total; Log.i("battery", "battery: " + percent + "%");
参考文献:
http://blog.csdn.net/liuhe688/article/details/6955668
官方文档
《第一行代码Android》