Android基础(九) BroadcastReceiver 广播接收者
1.什么是BoradcastReceiver
Android手机在一些事件发生的时候会发送广播信息,如:开机成功、收到短信、拨打电话、SD卡状态改变、电池状态改变等。
2.定义广播接收者
定义一个类继承BoradcastReceiver,并且重写onReceive()方法。
在清单文件中声明<receiver>节点,定义name属性、定义<intent-filter>和<action>指定要接收的广播类型。
<receiver>标签中可以定义一个permission属性,要求发送者必须持有指定的权限,否则不接收发送过来的广播信息。
以下为注册了一个广播接收者,用于接收开机成功的广播:
public class BootReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { System.out.println("收到开机成功的广播!"); } }
清单文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxx.receiver" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <receiver android:name=".BootReceiver"> <intent-filter > <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> </application> </manifest>
3.广播的类型
无序广播:
所有的接收者都可以接受到该广播,不能中断,不能使用结果数据。
无序广播使用sendBroadcast()方法发送。
在发送时,可以指定接收者权限,也可以不指定权限。如果指定了权限,则接收者必须持有该权限才能接收到该广播。
在接收时,也可以指定发送者的权限,如果发送者没有该权限,则不接收发送者发送的广播。
自定义权限:
<permission android:name="com.xxx.permission.BROADCAST" />
在使用自定义权限时,示例如下:
<uses-permission android:name="com.xxx.permission.BROADCAST" />
有序广播:
可以被多个广播接收者逐个接收,可以中断,可以使用结果数据。
用sendOrderedBroadcast()方法发送。
在发送时和无序广播一样可以指定接收者的权限。
在发送有序广播时,可以指定一些结果数据,这些数据会被传递到接收者中,每个接收者都可以接受这些数据并且做出修改。
有序广播可以被接收者使用abortBroadcast()方法中断,中断以后,后面的接收者就无法接收到该广播。
有序广播可以自定义一个接收者用来在广播序列的最后一个接收广播,这样就可以获得所有接收者修改之后的结果数据。
接收者可以在<intent-filter>中定义android:priority定义优先级,数字越大优先级越高。
示例:
BroadcastSender
public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void normal(View view) { // sendBroadcast(new // Intent("com.xxx.action.Test"));//创建广播的意图对象,指定广播的动作,发送无序广播 sendBroadcast(new Intent("com.xxx.action.Test"), "com.xxx.permission.BROADCAST");// 发送无序广播,并且指定接受者权限 } public void ordered(View view) { Bundle bundle = new Bundle(); bundle.putString("name", "张三"); bundle.putInt("age", 18); sendOrderedBroadcast(new Intent("com.xxx.action.Test"), null, new HisReceiver(),// 第三个参数指定接收者用来在广播序列的最后一个接收广播,可以得到所有接收者修改之后的数据 new Handler(), 100, "aaa", bundle); } }
public class HisReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { System.out.println("HisReceiver收到广播!"); System.out.println("ResultCode:"+getResultCode()); System.out.println("ResultData:"+getResultData()); System.out.println("ResultExtras::"+getResultExtras(true).getString("name")+":"+getResultExtras(true).getInt("age")); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxx.sender" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <permission android:name="com.xxx.permission.BROADCAST" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".HisReceiver"> <intent-filter> <action android:name="com.xxx.action.Test"/> </intent-filter> </receiver> </application> </manifest>
MyReceiver
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { System.out.println("MyReceiver收到广播!"); //获取数据结果 System.out.println("ResultCode:"+getResultCode()); System.out.println("ResultData:"+getResultData()); System.out.println("ResultExtras:"+getResultExtras(true).getString("name")+":"+getResultExtras(true).getInt("age")); //修改数据结果 Bundle bundle = new Bundle(); bundle.putString("name", "李四"); bundle.putInt("age", 20); setResult(200, "bbb", bundle); //中断广播 abortBroadcast(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxx.myreceiver" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <uses-permission android:name="com.xxx.permission.BROADCAST"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <receiver android:name=".MyReceiver"> <intent-filter android:priority="4"> <action android:name="com.xxx.action.Test"/> </intent-filter> </receiver> </application> </manifest>
YourReceiver
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; public class YourReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { System.out.println("YourReceiver收到广播!"); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxx.yourreceiver" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <uses-permission android:name="com.xxx.permission.BROADCAST" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <receiver android:name=".YourReceiver"> <intent-filter android:priority="3"> <action android:name="com.xxx.action.Test"/> </intent-filter> </receiver> </application> </manifest>
4.生命周期
广播接收者的生命周期非常短暂:在接收到广播时创建,onReceiver()方法结束后就销毁。
广播接收者onReceive()方法运行超过6秒就会产生ANR异常,所以不要在主线程中进行耗时操作。
而如果在onReceive()方法中开启子线程进行操作,不会出现ANR异常,但是由于生命周期结束,很容易就被杀死。
ANR异常
1.什么是ANR异常
Application Not Response
用户在界面上做了一个操作,如果超过6秒钟程序仍然未能做出响应,系统就会抛出ANR异常。
2.怎么避免ANR异常
比较耗时的操作(例如:连接网络、加载大量数据等),不要在主线程中进行开做,开启新的线程进行处理。如果子线程中需要操作主线程创建的视图内容,则需要使用Handler进行处理。