前面的话
广播接收者(BroadcastReceiver)是什么??什么时候才会用到呢?
当你的手机出现如下情况: 电量不足,sd卡被移除,电话外拨,短信到了等等…
你的手机往往会在第一时间就弹窗给你提醒,这些贴心的功能就是靠BroadcastReceiver实现的!!
定义的个人理解
广播(Broadcast):
广而告之!具有全局性,涵盖整一个安卓的操作环境,即一个安卓设备.
接收者(Receiver)
被动的去接收数据. 只要安卓系统中有数据到来需要接受,它就会默默的完成它的使命.
广播接收者特点:
1.即使应用程序进程不存在,当广播事件到来的时候,广播接收者进程会自动启动,响应广播事件
2.Android4.0以后,将应用强行停止后,应用会被冻结,直到再次手工开启应用才能继续响应广播事件.
如何创建广播接收者
创建步骤:
1.创建一个类继承BroadcastReceiver(买个收音机)
*重写onReceive()方法
2.配置清单文件.在application节点下定义<receiver>节点(装电池)
*<receiver android:name="包名称+类名称"><receiver/>
3.在步骤2定义的<reciever>节点下配置<intent-filter>节点. 在<intent-filter>节点内定义<action>和<date>节点(调频道)
*<intent-filter>
<action android:name="android.intent.action.XXX"><action/>
<data android:scheme="包名"><data/>
<intent-filter/>
4.在onReceive()方法里编写逻辑(步骤1)
<小案例一:应用程序安装和卸载>
1.配置清单文件:
<!--直接获取系统的广播事件-->
<receiver android:name="com.heima.un_install.InstallReceiver">
<intent-filter >
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
2.写个类继承BroadcastReceiver,接受系统广播数据:
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if ("android.intent.action.PACKAGE_ADDED".equals(action)) {
System.out.println("有应用程序被安装了:"+intent.getData().toString());
}else if ("android.intent.action.PACKAGE_REMOVED".equals(action)) {
System.out.println("有应用程序被卸载了:"+intent.getData().toString());
}
}
<小案例二:IP拨号器>
需求:利用系统拨号器拨打电话时自动添加前缀:17951
1.配置清单文件和呼叫电话的权限
<!--配置receiver-->
<receiver android:name="com.heima.ipcall.IPcallReceiver">
<intent-filter >
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
<!--添加呼叫电话的权限-->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
2.写一个Actiity,获取电话号码,存到sp里
public class MainActivity extends Activity {
private EditText et_ipnumber;
private SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//关系控件
et_ipnumber=(EditText) findViewById(R.id.et_ipnumber);
//创建一个SharedPreferences
sp=getSharedPreferences("config", 0);
//回显设置的IP前缀到页面上
et_ipnumber.setText(sp.getString("ipNum", ""));
}
//按钮点击事件
public void save(View view){
//获取输入的IP前缀
String ipNum=et_ipnumber.getText().toString().trim();
sp=getSharedPreferences("config", 0);
Editor editor = sp.edit();
//存到sp里
editor.putString("ipNum", ipNum);
editor.commit();
Toast.makeText(MainActivity.this, "设置成功",0).show();
}
}
MainActivity的布局文件:
<!--使用线性布局,垂直分布-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请设置您的IP号码" />
<EditText
android:id="@+id/et_ipnumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="内容留空表示取消ip拨号"
/>
<Button
android:onClick="save"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="保存"
/>
3.写一个广播接收者类继承BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {
//获取存到config.xml文件里的数据
SharedPreferences sp=context.getSharedPreferences("config", 0);
String ipNum = sp.getString("ipNum", "");
String num=getResultData();
//设置拨打的电话号码
if (num.startsWith("0")) {
setResultData(ipNum+num);
}
}
小结:
以上是一般的广播事件,可以通过清单文件注册广播事件,即静态注册. 同时也可以在java代码里面动态注册. 一般使用静态注册.
特殊的广播接收者
一些操作比较频繁的事件,比如锁屏解锁和电量变化,这些事件会发送特定的广播.这列广播在清单文件里配置不会生效,只能在Java代码中进行注册.即动态注册
锁屏广播接收者核心代码:
在MainActivity.java里
的onCreate()方法里面写:
receiver=new ScreenStatusReceiver();
IntentFilter filter=new IntentFilter();
//屏幕关闭的action
filter.addAction("android.intent.action.SCREEN_OFF");
//屏幕点亮的action
filter.addAction("android.intent.action.SCREEN_ON");
//注册广播接收者
registerReceiver(receiver,filter);
在MainActivity.java的onDestory()方法里写:
//取消注册广播接收者(必须!!否则会报错)
unregisterReceiver(receiver);
receiver=null;
自定义类继承BroadcastReceiver:
在onReceive()方法里面写:
if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
Log.d("tag","监听到屏幕点亮了");
}else if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
Log.d("tag","监听到屏幕关闭了");
}
注:
1.监听锁屏和解锁不需要额外的权限, 因此可以直接运行.
2.为了避免IntentReceiver的泄露.必须在MainActivity的onDestory方法中或者其他地方(必须保证Activity被销毁之前)将接收者给反注册掉.
广播事件的发送类型
发送有序广播:
*广播消息按照一定的顺序传达. 高优先级接收者先得到消息,低优先级后得到. 如果优先级相同,则按
照清单文件配置的顺序依次减弱优先级.*高优先级可以拦截或者修改广播消息.
*有序广播使用context.sendOrderedBroadcast()方法来发送,使用abordBroadcast()方法拦截
实例: 短信窃听拦截
分析:窃听短信是利用有序广播的优先级和终止来实现的.
1.配置清单文件,设置接收短信的权限,设置设置广播接收者的优先级
<receiver android:name="com.heima.msglisten.SMSListenerReceiver">
<!--优先级设置为最高1000-->
<intent-filter android:priority="1000" >
<!--设置接收数据类型-->
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<!--配置接收短信的权限-->
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
2.写一个广播接收者类,解析PDU格式短信内容,并终止(拦截)有序广播
public class SMSListenerReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("短信来啦啊~~~~");
//解析PDU格式的短信信息
Object[] objs = (Object[]) intent.getExtras().get("pdus");
for (Object obj:objs) {
SmsMessage smsMessage=SmsMessage.createFromPdu((byte[]) obj);
String body = smsMessage.getMessageBody();
String sender = smsMessage.getOriginatingAddress();
System.out.println("body:"+body+"\nsender:"+sender);
//终止发短信的有序广播
if (isOrderedBroadcast()) {
abortBroadcast();
}
}
}
}
3.利用空的Activity开启广播接收者
发送无序广播:
*广播消息接受没有优先级顺序,多个接收者同时接收广播消息.
*效率高. 不能拦截,不能修改
*无序广播使用context.sendBroadcast()方法来发送
实例: 自定义无序广播
1.创建一个Android项目,在MainActivity里面写发送的广播内容
Intent intent=new Intent();
//设置意图action
intent.setAction("com.yashiro.ccav");
//绑定数据
intent.putExtra("data","我是无序广播的数据");
//发送无序广播
sendBroadcast(intent);
2.创建一个广播接收者接收广播.
public class MyReceiver extends BroadcastReceiver{
@override
public void onReceive(Context context,Intent intent){
System.out.println("哈哈哈,我们接收到了自定义的广播消息");
System.out.println("消息原文:"+intent.getStringExtra("data"));
}
}
3.在清单文件中进行注册操作
<receiver android:name="com.yashiro.MyReceiver">
<intent-filter>
<action android:name="com.yashiro.ccav"/>
<intent-filter/>
<receiver/>
小结:
BroadcastReceiver 就是一个贴心的小伙伴,不管它有没有睡着,只要有事件在召唤他它随时会醒来完成它的使命!!!!
未完待续….
接下来会继续更新其他两种组件的特点, 不喜勿喷