PhoneBroadcastReceiver与Suspension Window的使用心得

前言

前段时间接到一个需求,监听用户拨打电话行为,与后台服务器建立Socket连接,用以在用户通话过程中,弹出悬浮窗的功能。第一想法当然是使用BroadcastReceiver,通过TelephonyManager监听用户的通话状态,由此进入了不断踩坑阶段。。。
在这里插入图片描述

1、打电话过程中的状态变化

PhoneState共有3中状态
TelephonyManager.CALL_STATE_IDLE: 电话空闲/挂断
TelephonyManager.CALL_STATE_RINGING: 来电响铃
TelephonyManager.CALL_STATE_OFFHOOK: 摘机/接通

针对用户拨打电话,手机一开始的状态是TelephonyManager.CALL_STATE_IDLE,拨打电话时变成TelephonyManager.CALL_STATE_OFFHOOK,挂断电话时再次触发TelephonyManager.CALL_STATE_IDLE。

先上一段代码

TelephonyManager mTelMgr = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);

mTelMgr.listen(new PhoneStateListener() {
                    @Override
                    public void onCallStateChanged(int state, String incomingNumber) {
                        super.onCallStateChanged(state, incomingNumber);
                        switch (state) {
                            case TelephonyManager.CALL_STATE_IDLE: 
                                
                                break;
                            case TelephonyManager.CALL_STATE_RINGING: 
                                
                                break;
                            case TelephonyManager.CALL_STATE_OFFHOOK:
                             
                                break;
                        }
                    }
                }, PhoneStateListener.LISTEN_CALL_STATE);

上面代码是标准的通话状态Listener。根据业务需求,在TelephonyManager.CALL_STATE_OFFHOOK状态时建立Socket连接,在TelephonyManager.CALL_STATE_IDLE时断开连接。
理想很丰满,现实很骨感~
在这里插入图片描述
运行代码时发现,PhoneState的TelephonyManager.CALL_STATE_IDLE与TelephonyManager.CALL_STATE_OFFHOOK都会触发多次,TelephonyManager.CALL_STATE_IDLE还好,只是断开操作,多次断开也不会有啥问题,但是TelephonyManager.CALL_STATE_OFFHOOK下的初始化操作会进行多次,这就不能忍了。
既然TelephonyManager.CALL_STATE_OFFHOOK状态会多次触发,那我就记下次数,只有第一次的时候初始化就行了,嗯,就这样办!
在这里插入图片描述
初始化一个int类型的phoneCount=1, 当触发TelephonyManager.CALL_STATE_OFFHOOK时先进行初始化,然后phoneCount++,这样理论上只会初始化一次了。添加打印日志后,运行代码。
拨打一通电话,发现初始化只会进行一次了。问题解决了么~~哈哈哈!我真是个小天才。怀着有点小得意的心情,再多试两次吧,重要的事情试3遍。第二通电话就给了我一个晴天霹雳,初始化日志竟然出现了两次,两次,两次!!!

在这里插入图片描述
这是啥情况,怎么使用次数标识还会触发两次???一次失败当然不死心,之前phoneCount使用的普通变量,使用static会不会好些?替换后运行,发现还是偶尔会出现初始化多次的情况。不停运行打印日志,然而也没有找到问题所在~
在这里插入图片描述
没办法了,只能去请教小组里的老司机组长。聊了一会需求后,组长问我:“你为啥不保存通话状态的上一个状态呢,比对上一个状态与当前状态是否相同,相同则return,不同再处理业务逻辑”。
在这里插入图片描述
卧槽,卧槽,卧槽!!!为啥我就没想到,为啥?为啥?为啥?不愧是老司机~
改进后的代码

private static int mLastState = TelephonyManager.CALL_STATE_IDLE;

TelephonyManager mTelMgr = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);

mTelMgr.listen(new PhoneStateListener() {
                    @Override
                    public void onCallStateChanged(int state, String incomingNumber) {
                        super.onCallStateChanged(state, incomingNumber);
                        if (state == mLastState) {
                            return;
                        } else {
                            mLastState = state;
                        }
                        switch (state) {
                            case TelephonyManager.CALL_STATE_IDLE: 
                                
                                break;
                            case TelephonyManager.CALL_STATE_RINGING: 
                                
                                break;
                            case TelephonyManager.CALL_STATE_OFFHOOK:
                             
                                break;
                        }
                    }
                }, PhoneStateListener.LISTEN_CALL_STATE);

运行代码,卧槽,真的完美解决了触发多次状态的情况!!!
在这里插入图片描述
电话状态的坑总算是告一段落了~

2、Suspension Window注意事项

a、悬浮窗必须加载在主线程
b、必须有悬浮窗权限才能addView
c、removeView之前需要判断是否添加过view
个人是用的是GitHub上的一个悬浮窗授权库,传送门:FloatWindow. 再次感谢这个库的作者,帮我省了很多适配机型的问题。

以上就是PhoneBroadcastReceiver与Suspension Window的使用小心得,有不对的地方敬请指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值