##1. 广播接收者概念
1. 分类
1. 无序广播
1. 无论广播接收者的优先级是什么,所有的广播接收者都能收到这个广播,而且这个个广播不能被拦截。
2. 有序广播
1. 根据广播接收者的优先级去优先接收,可以被拦截。
2. 广播的注册分两种注册方式
1. 在AndroidManifest.xml中的注册,叫静态注册
2. 在Activity中通过代码注册,叫动态注册
3. 广播接收者的优先级
1. google推荐的范围是[-1000,+1000]
2. 谁优先级高,谁优先接收到广播
3. 默认的广播接收者的优先级是0
##2. 案例-IP拨号器(*)
1. 步骤
1. 定义MyBroadCastReceiver extends BroadCastReceiver
2. 覆写onReceive(Context context)方法,添加业务逻辑
3. 注册广播
1. 分类
1. 无序广播
1. 无论广播接收者的优先级是什么,所有的广播接收者都能收到这个广播,而且这个个广播不能被拦截。
2. 有序广播
1. 根据广播接收者的优先级去优先接收,可以被拦截。
2. 广播的注册分两种注册方式
1. 在AndroidManifest.xml中的注册,叫静态注册
2. 在Activity中通过代码注册,叫动态注册
3. 广播接收者的优先级
1. google推荐的范围是[-1000,+1000]
2. 谁优先级高,谁优先接收到广播
3. 默认的广播接收者的优先级是0
##2. 案例-IP拨号器(*)
1. 步骤
1. 定义MyBroadCastReceiver extends BroadCastReceiver
2. 覆写onReceive(Context context)方法,添加业务逻辑
3. 注册广播
<receiver android:name="com.example.ipcaller.MyBroadCastReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
2. 添加权限
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
##3. 案例-监听手机网络状态(****)
权限:
<
uses-permission
android:name
=
"android.permission.ACCESS_NETWORK_STATE"
/>
1. 获取网络状态
private String getNetstate() {
//获取系统提供的连接管理器
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//获取当前可用(活动)的网络,如果没有任何可用的网络,则返回null
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetworkInfo==null) {
return "没有可用的网络";
}else{
//获取一下,当前是什么网络类型WIFI MOBILE
String typeName = activeNetworkInfo.getTypeName();
//如果是MOBILE ,会返回具体的类型
String subtypeName = activeNetworkInfo.getSubtypeName();
return "typeName="+typeName+"\nsubTypeName="+subtypeName;
}
}
2. 如何动态注册广播
1. 在Activity定义内部类继承BroadCastReceiver
2. 在Activity的onCreate方法中注册广播
1. 在Activity定义内部类继承BroadCastReceiver
2. 在Activity的onCreate方法中注册广播
myNetStateReceiver = new MyNetStateReceiver();
IntentFilter filter = new IntentFilter();
//给filter添加Action
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//注册接收网络状态改变的广播接收者
registerReceiver(myNetStateReceiver, filter);
3. 当Activity销毁的时候,一定记得取消注册
protected void onDestroy() {
super.onDestroy();
//取消接收网络状态改变的广播接者
if (myNetStateReceiver!=null) {
unregisterReceiver(myNetStateReceiver);
myNetStateReceiver =null;
}
}
##4. 案例-监听开机启动(*)
1. 添加权限
1. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
##5. 案例-监听屏幕的关闭和打开(*)
##6. 案例-短信黑名单
1. 配置优先级为最大
<receiver android:name="com.example.blacksms.BlackNumReceiver">
<intent-filter
android:priority="1000"
>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
2. 添加的权限
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
3. 拦截有序广播
abortBroadcast();
##7. 发送自定义广播(**)
1. 发送无序广播
1. 发送无序广播
//发送无序广播
sendBroadcast(intent);
2. 发送有序广播
sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String resultData = getResultData();
Log.d("tag", "我是最终广播接收者:收到的数据是:"+resultData);
}
},null , 0, "每人1w元", null);
##8.最佳案例 强制下线(****)
案例需求分析:定义一个登录界面(LoginActivity),当用户名和密码验证成功时,跳到第二个界面(MainActivity),点击MainActivity中的强制下线按钮,然后弹出一个对话框提示信息
,对话框不可取消和返回,当我们点击对话框的确定按钮,返回到登录界面。
这里我们需要自定义一个广播接收者,当我们点击MainActivity中的强制下线按钮,发出一个强制下线的广播,然后我们的广播接收者就会收到广播执行onReceive方法。我们就可以在onReceive方法中
做弹出对话框强制下线的逻辑。
强制下线逻辑:
案例需求分析:定义一个登录界面(LoginActivity),当用户名和密码验证成功时,跳到第二个界面(MainActivity),点击MainActivity中的强制下线按钮,然后弹出一个对话框提示信息
,对话框不可取消和返回,当我们点击对话框的确定按钮,返回到登录界面。
这里我们需要自定义一个广播接收者,当我们点击MainActivity中的强制下线按钮,发出一个强制下线的广播,然后我们的广播接收者就会收到广播执行onReceive方法。我们就可以在onReceive方法中
做弹出对话框强制下线的逻辑。
强制下线逻辑:
public class ForceOffLineReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
AlertDialog.Builder builder = new Builder(context);
builder.setTitle("警告");
builder.setMessage("您的帐号已经在别处登录,请重新登录");
builder.setCancelable(true);
builder.setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCollector.removeAll(); // 销毁所有活动
Intent intent = new Intent();
//在广播中执行Intent必须setFlags
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(context, LoginActivity.class);
context.startActivity(intent);
}
});
AlertDialog alertDialog = builder.create();
//需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}
注意:由于我们在 ForceOfflineReceiver 里弹出了一个系统级别的对话框,因此必须要声明 android.permission.SYSTEM_ALERT_WINDOW 权限。
<
uses-permission
android:name
=
"android.permission.SYSTEM_ALERT_WINDOW"
/>
##9 常见异常
1. 动态(在Activity中)注册广播,但是当Activity销毁的时候,忘记反注册
1. 动态(在Activity中)注册广播,但是当Activity销毁的时候,忘记反注册
11-24 03:23:06.442: E/ActivityThread(2637): Activity com.example.listennetstate.MainActivity has leaked IntentReceiver com.example.listennetstate.MainActivity$MyNetStateReceiver@b646d548 that was originally registered here. Are you missing a call to unregisterReceiver()?
2. 在非Activity中(BroadCastReceiver中)启动Activity异常
11-24 03:54:00.367: E/AndroidRuntime(1454): java.lang.RuntimeException: Unable to start receiver com.example.bootStart.MyBoorStartReceiver: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
Intent mainIntent = new Intent(context, MainActivity.class);
//给Intent添加一个FLAG_ACTIVITY_NEW_TASK 告诉系统去为我们的Activity创建一个任务栈
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mainIntent);