1 为什么需要广播接收者(BroadcastReceiver)
【1】有什么样的人员听广播?老人 出租车司机 等等
【2】想听广播必须得有:电台 收音机
【3】Android系统内部已经定义好了电台,已经定义好了一些广播事件,比如:外拨电话、短信到来、SD卡状态、电池电量等等
【4】使用BroadcastReceiver去接收系统已经定义好的这些事件
【5】定义广播接收者的目的是为了方便开发者进行开发
补充:javame(针对移动开发) javase(java基础) javaee(web开发)
2 案例:IP拨号器(17951)
【1】定义广播接收者继承BroadcastReceiver
public class OutGoingCallReceiver extendsBroadcastReceiver {//☆☆☆☆第一步[1]
//当进行外拨电话的时候调用
@Override
publicvoid onReceive(Context content, Intent intent) {
//[1]获取当前拨打的电话号码
StringcurrentNumber = getResultData();
//[2]在当前的号码前面加上17951
//[2.1]判断当前拨打的号码是否是长途
if(currentNumber.startsWith("0")) {
setResultData("17951"+currentNumber);
}
}
}
【2】在清单文件中配置
<receiver android:name="com.itheima.ipdail.OutGoingCallReceiver">
<intent-filter >
<action
android:name="android.intent.action.NEW_OUTGOING_CALL"//☆☆☆第三步[3]
/>
</intent-filter>
</receiver>
【3】实现相应的逻辑
//点击按钮 保存用户输入的ip号码
public void click(View v){
//[1]获取用户输入的ip号码
String ipnumber = et_ipnumber.getText().toString().trim();
//[2]把当前ipnumber存起来 存到sp中
SharedPreferences sp = getSharedPreferences("config", 0);
//[3]获取sp的编辑器
sp.edit().putString("ipnumber", ipnumber).commit();
//[4]保存成功
Toast.makeText(getApplicationContext(), "保存成功", 1).show();
}
【4】记得加上权限:PROCERSS_OUTGOING_CALLS
[1] 定义广播接受者并且继承BroadcastReceiver
publicclass SdcardStateReceiver extends BroadcastReceiver {
//当SD卡状态发生改变的时候执行
@Override
publicvoid onReceive(Context context, Intent intent) {
//[1]获取到当前广播的时间类型
Stringaction = intent.getAction();
if("android.intent.action.MEDIA_MOUNTED".equals(action)) {
System.out.println("说明SD卡挂载上来了...");
}elseif ("android.intent.action.MEDIA_UNMOUNTED".equals(action)) {
System.out.println("说明SD卡卸载了....");
}
}
}
[2] 在清单文件中配置一下
<receiver
android:name="com.itheima.sdcardstate.SdcardStateReceiver"
>
<intent-filter >
<actionandroid:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
<!-- 小细节这里需要配置一个data 约束类型叫file 因为 sd里面存的数据类型是file文件-->
<!-- action里面的事件很多,到底哪些事件要配置data呢,总共只有两个 -->
<dataandroid:scheme="file"/>
</intent-filter>
</receiver>
4 案例:卸载安装
[1] 定义广播接受者
publicclass AppStateReceiver extends BroadcastReceiver {
//当有新的应用被安装 或者有应用被卸载了这个方法调用
@Override
publicvoid onReceive(Context context, Intent intent) {
//获取当前广播的时间类型
Stringaction = intent.getAction();
if("android.intent.action.PACKAGE_INSTALL".equals(action)) {
System.out.println("应用安装了11111");
}elseif ("android.intent.action.PACKAGE_ADDED".equals(action)) {
System.out.println("应用安装了22222");
}elseif ("android.intent.action.PACKAGE_REMOVED".equals(action)) {
System.out.println("应用卸载了!!"+intent.getData());
}
}
}
[2] 配置清单文件
<receiver
android:name="com.itheima.appstate.AppStateReceiver">
<intent-filter >
<actionandroid:name="android.intent.action.PACKAGE_INSTALL"/>(一般不用install,用的是add)
<actionandroid:name="android.intent.action.PACKAGE_REMOVED"/>
<actionandroid:name="android.intent.action.PACKAGE_ADDED"/>
<!--想让action生效 还需要配置一个data -->
<data android:scheme="package"/>
</intent-filter>
</receiver>
5 案例:开机启动
09-05 03:08:50.684: E/AndroidRuntime(1735):java.lang.RuntimeException: Unable to start receivercom.itheima.bootreceiver.BootReceiver: android.util.AndroidRuntimeException:Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASKflag. Is this really what you want?
注意:不能直接在广播接收者中activity
[1] 定义广播接收者
publicclass BootReceiver extends BroadcastReceiver {
//当手机重新启动的时候调用
//记得加上权限 RECEIVE_BOOT_COMPLETED
@Override
publicvoid onReceive(Context context, Intent intent) {
//在这个方法中开启activity
Intentintent2 = new Intent(context, MainActivity.class);
//☆☆☆☆☆注意 不能在广播接收者里面直接开启activity
//需要添加一个标记添加一个任务栈的标记
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//开启activity
context.startActivity(intent2);
}
}
[2] 配置清单文件
<receiver
android:name="com.itheima.bootreceiver.BootReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
[3] 记得加上权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
6 有序广播和无序广播
自定义广播分为:
(1) 有序广播:类似中央发送红头文件 按照优先级进行接收
特点:[1]有序广播可以被终止
[2]有序广播的数据可以被修改
[3]sendOrderBroadcast()
(2) 无序广播:比如新闻联播每天晚上7点准时开播
特点:[1]无序广播不可以被终止
[2]数据不可以被修改
[3]sendBroadcast(Intent intent);
7 特殊广播接收者操作特别频繁的广播事件 比如:屏幕的锁屏和解锁 电池电量的变化 这种事件在清单文件中注册(配置)是无效的,必须动态的注册
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//动态的注册特殊广播接受者
screenReceiver = new ScreenReceiver();
/*<receiverandroid:name="com.itheima.screen.ScreenReceiver">
<intent-filter >
<actionandroid:name="android.intent.action.SCREEN_ON"/>
<actionandroid:name="android.intent.action.SCREEN_OFF"/>
</intent-filter>
</receiver>*/
//创建IntentFilter对象
IntentFilter filter = new IntentFilter();
//添加要注册的action
filter.addAction("android.intent.action.SCREEN_ON");
filter.addAction("android.intent.action.SCREEN_OFF");
//动态注册广播接受者
registerReceiver(screenReceiver, filter);
}
注册广播接收者的2种方式:
1、 动态注册通过代码方式注册
2、 在清单文件通过receiver tag节点静态发布
09-0507:46:08.745: E/ActivityThread(2344): Activity com.itheima.screen.MainActivityhas leaked IntentReceiver com.itheima.screen.ScreenReceiver@b2c14508 that wasoriginally registered here. Are you missing a call to unregisterReceiver()?
protected void onDestroy() {
//当activity 销毁的时候要取消注册广播接受者
unregisterReceiver(screenReceiver);
super.onDestroy();
}