安卓基础:广播接收者


##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. 注册广播
        
   <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"/>

##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方法中注册广播

    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. 发送无序广播
 
  //发送无序广播
        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方法中
做弹出对话框强制下线的逻辑。
强制下线逻辑:
       
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销毁的时候,忘记反注册

    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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值