BroadcastReceiver基础总结
BroadcastReceiver是Android四大组件之一,主要负责接收系统或其他程序发出的广播,在开发中,通常用做事件驱动的起源,比如开机就要开启一个程序,有网络就要开始下载资源,安装或卸载包了,就要跟新UI等等。以下就对这个组件总结我自己的理解:
BroadcastReceiver的生命周期
BroadcastReceiver的生命周期很短,当系统或其他程序发出广播的时候,Android系统的包管理对象就会检查所有已安装的包中的配置文件有没有匹配的action,如果有,并且可以接收,那么就调用这个BroadcastReceiver,获取BroadcastReceiver对象,然后执行onReceiver(),这个时候BroadcastReceiver对象就没有了,被摧毁了,所有说BroadcastReceiver的生命周期是非常短的。切记,在onReveiver()中不能做比较耗时的操作,不然会弹出ANR对话框。如果真的要完成耗时的工作的话,可以交给Service去完成。另外,onReceiver()中也不能用子线程来操作,大家都知道,当父进程被杀死后,它的子进程也会被杀死,所以,这是很不安全的做法。
按活动模式来分类BroadcastReceiver
常驻型广播:不随Activity的生命周期而改变,即使Activity被摧毁了,这个BroadcastReceiver依然能够接受广播,一般在配置文件中定义。
非常驻型广播:随着Activity的生命周期而改变,在程序中定义。
到底用哪一种比较好,这里要看程序的需求。比如,需要捕捉开机事件就启动一个包,那么,这个最好是用常驻型广播。比如,系统设置的应用程序管理界面中,监听是否有包被安装,以便跟新UI,这里最好是使用非常驻型广播好。
按优先级来分类BroadcastReceiver
有序广播:接收广播的时候有优先级,优先级在receiver中的android:property属性中指定,数值越大优先级越高。其优先级范围是[-1000,1000],这里需要注意两点。第一,有序广播可以中断广播的继续传送,中断之后,排列在这个广播接收器之后的接收器就接收不到该广播了,只需要在这个广播接收器中的onReceiver()中使用abortBroadcast()方法。第二,接收者可以在接收过程中向即将收到广播的接收器传递数据,这里传递数据用Bundle。代码说明:
前面的接收者可以通过setResultExtras(Bundle)存放数据,下一个接收者可以通过
Bundle mBundle =getResultExtras(true) ;来接收数据。
普通广播:这些广播接收器在接收广播的时候是无序的,当然,谁也没有权利来中断这个广播,因为它不存在接收队列!
现在来看看代码,首先总结下注册广播的方法:
第一种方法:在配置文件中注册广播(接收apk包被安装了的广播)
首先定义一个类继承BroadcastReceiver,并且覆写onReceiver方法
package dxd.android.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals("android.intent.action.PACKAGE_ADDED")){
Log.e("MyReceiver","安装了包"+intent.getDataString());
}
}
}
然后,在配置文件AndroidManifest.xml文件中添加receiver节点
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dxd.android.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="9" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MyBroadcastReceiverActivity"
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=".MyReceiver">
<intent-filter >
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<data android:scheme="package" />
<!-- 有关apk包的操作,这句一定要加 -->
</intent-filter>
</receiver>
</application>
</manifest>
还有一个主Activity类就没有写出来了,在该类中就根本没有调用任何接收器的方法。
第二种:在程序中注册广播接收器,接收自己定义的广播
这种方式叫做动态广播。首先定义一个广播接收器
class ChatBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction() ;
Log.e("ChatBroadcastReceiver","------收到广播 , " + action);
if(action.equals("com.example.udpchat.friendchange")){//
Msg msg = intent.getParcelableExtra("msg");
if(null != msg){
mList.add(msg);
mAdapter.notifyDataSetChanged();
}
}
}
}
从代码中可以看出,该广播接收器是接收"com.example.udpchat.friendchange"这个广播,这个广播是自己定义的。
那么怎么发送广播呢,看代码:
Intent intent = new Intent("com.example.udpchat.friendchange");
context.sendBroadcast(intent);
现在剩下的事情,就是去注册监听广播
private ChatBroadcastReceiver mReceiver ;
mReceiver = new ChatBroadcastReceiver() ;
IntentFilter filter = new IntentFilter();
filter.addAction("com.example.udpchat.friendchange") ;
registerReceiver(mReceiver, filter) ;
这样就完了,可以看出,是不需要在manifest配置文件中去注册广播的。确实是这样的。
有权限的广播
有时发送者要求广播接收器需要有权限才能接收广播,那么这时该怎么定义呢,其实就只需要添加一个权限即可,这里跟之前发送广播的方法有点小小的不通。看代码
package dxd.android.test;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class DIYBroadcastReceiverActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button but = (Button)findViewById(R.id.but);
but.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(DIYBroadcastReceiverActivity.this ,DIYReceiver.class);
intent.setAction("dxd.android.test.START_ACTIVITY");
sendBroadcast(intent,"dxd.android.test.permission.receiver");// 这里发送广播的方式不一样
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
自己写的Receiver几乎跟之前的是一样的
public class DIYReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction() ;
Log.e("DIYReceiver", "action = " + action) ;
if(action.equals("dxd.android.test.START_ACTIVITY")){
Intent intentTo = new Intent(context,NextActivity.class) ;
intentTo.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 没有在activity中启动,必须加这句。
context.startActivity(intentTo) ;
}
}
}
主要看配置文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dxd.android.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="9" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".DIYBroadcastReceiverActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".NextActivity"></activity>
<receiver android:name=".DIYReceiver" >
<intent-filter>
<action android:name="dxd.android.test.START_ACTIVITY"/>
</intent-filter>
</receiver>
</application>
<permission android:name="dxd.android.test.permission.receiver"></permission>
<uses-permission android:name="dxd.android.test.permission.receiver"/>
</manifest>
综合判断起来,就是sendBroadcast(intent,permission),和在配置文件中增加了一个权限的声明,和添加这个权限!
到此为止,就只有粘性广播没有总结。之后搞清楚了才写。