首先,我们要知道广播接受者 (BroadcastReceiver)就要了解android的广播机制。广播是一种广泛运用的在应用程序之间传输信息的机制 。而BroadcastReceiver是对发送出来的广播进行过滤接收并响应的一类组件。
BroadcastReceiver 自身并不实现图形用户界面,但是当它收到某个通知后,BroadcastReceiver可以启动Activity 作为响应,或者通过NotificationMananger提醒用户,或者启动Service 等等。就像我们手机里的短息,电话的接受都会产生一个广播;
一、接受广播的两种方式:
1.常驻型广播
如果你在xml文件中注册广播,这也被称为静态注册;这样如果你的应用关闭时,你的广播接受也同样能接受到。这种方式可以理解为通过清单文件注册的广播是交给操作系统去处理的。
下面是以短信接受的广播为例:
<receiver android:name="com.example.smsreceiver.SMSReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
2.非常驻型广播
比如在 Activity 中的 onCreate 或者 onResume 中注册广播接收者,在 onDestory 中注销广播接收者。这样你的广播接收者就一个非常驻型的了,这种注册方式也叫动态注册。这样如果你的应用关闭了,自然你的广播接受就不能就收到广播;
IntentFilter intentFilter=new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
receiver = new SMSReceiver();
MainActivity.this.registerReceiver(receiver, intentFilter)
还有一个小细节给大家提下,如果你是静态注册广播。在android 2.3之前是只要apk装上技能接受广播。而在4.0之后apk必须运行一次才能接受到广播;
二、给大家看下广播接受的具体使用,我们以短信接受为例:
先写个MainActivity 用来可视化广播的接受;
我又写了3个SMSReceiver,后面会给大家解释分别有什么用处:
首先,写个自己的广播接受者去继承BroadcastReceiver。
package com.example.smsreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context ,"收到短信了", 0).show();
//拦截广播
//abortBroadcast();
/*Bundle resultExtras = getResultExtras(true);
resultExtras.putString("a", "aa");
setResultExtras(resultExtras);*/
}
}
在DDMS的Emulator contr上给虚拟机发送短信:
上图的5556为虚拟机号码,Message则为短信内容;
点击send;虚拟机就看到短信来了。
三、广播又可分为以下三种:
普通广播 (Normal broadcasts)
发送一个广播,所以监听该广播的广播接收者都可以监听到改广播。
异步广播 , 当处理完之后的Intent ,依然存在,这时候registerReceiver(BroadcastReceiver, IntentFilter) 还能收到他的值,直到你把它去掉 , 不能将处理结果传给下一个接收者 , 无法终止广播 .
有序广播 (Ordered broadcasts)
1.有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。拦截广播的方法:abortBroadcast();
这里有个优先级问题:如果优先值等都一样一般动态注册比静态注册优先级高,越早注册优先级越高;
<receiver android:name="com.example.smsreceiver.SMSReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<receiver android:name="com.example.smsreceiver.SMSReceiver2" >
<intent-filter android:priority="1" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
这样SMSReceiver比SMSReceiver2的优先级就会高 。其中android:priority="1000"则是给其设置了优先级;这个属性的范围在-1000到1000,数值越大,优先级越高。
如果在SMSReceiver中不拦截广播则 MainActivity中会先土司“收到短信”随后也会土司"2收到短信了":
package com.example.smsreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class SMSReceiver2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context ,"2收到短信了", 0).show();
}
}
直接给大家贴出SMSReceiver2接受到的Toast:
四、自定义广播
发送自定义广播,并对接收者设置权限,有权限的接收者(在xml中申明权限)才会收到广播
接收者可以设置权限,只有发送方有此权限接收者才会收到此广播
android:permission="com.fc.permission1"指定发送者需要的权限
sendBroadcast(intent,"com.fc.pms08") //发送广播并指定接收者需要的权限
指定某个广播一定而且最后被resultReceiver接收
sendOrderedBroadcast(intent, null, resultReceiver, scheduler, initialCode, initialData, initialExtras);
sendStickyBroadcast(intent);
具体实现:首先新建一个广播发送的工程BroadcasSender。
其MainActivity中有个 发送Button。代码如下:
package com.example.broadcastsender;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn1 = (Button) findViewById(R.id.button1);
btn1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent=new Intent();
intent.setAction("com.fc.08");
MainActivity.this.sendBroadcast(intent,"com.fc.pms08");//指定接收者需要的权限
}
});
}
布局XML中就一个Button ,这里就不贴出了。
在BroadcasSender的注册文件中必须自定义权限并使用
这里要指定发送者的权限:
<permission android:name="com.fc.permission1"></permission>
<uses-permission android:name="com.fc.permission1"/>
在SMSReceiver的SMSReceiver3中:
package com.example.smsreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class SMSReceiver3 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context ,"收到自定义广播", 0).show();
}
}
在SMSReceiver的清单文件必须给自定义的广播接受者权限
<permission android:name="com.fc.pms08"></permission>
<uses-permission android:name="com.fc.pms08" />。
其具体为:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smsreceiver"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<permission android:name="com.fc.pms08"></permission>
<uses-permission android:name="com.fc.pms08" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.smsreceiver.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="com.example.smsreceiver.SMSReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<receiver android:name="com.example.smsreceiver.SMSReceiver2" >
<intent-filter android:priority="1" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<receiver
android:name="com.example.smsreceiver.SMSReceiver3"
android:permission="com.fc.permission1" >
<intent-filter>
<action android:name="com.fc.08" />
</intent-filter>
</receiver>
</application>
</manifest>
还有个小细节:
Receiver的生命周期只有10秒左右,过长可能会被系统回收,但能继续向下发送广播(如果是有序广播)
这样就实现了自定义的广播。本人只是刚学了点BroadcastReceiver,所以整理下自己的理解,希望大家在我不足的地方指点。学无止境嘛!