【第22期】观点:IT 行业加班,到底有没有价值?

RingerMode 设置和勿扰模式关系

原创 2016年08月30日 17:07:15

问题引入,在项目中,Android6.0项目中,客户要求去掉勿扰模式,当时我们只是去掉了勿扰模式的界面显示部分,即在SystemUI 的VolumeDialog.java类当中去掉了勿扰模式显示的部分和设置中界面显示部分。而实际的功能并为做修改。这样做之后又出现了新问题。

android5.1以后,在按音量下键时,将音量调到0之后,在继续按音量下键,会将情景模式调到勿扰模式,无法直接调到静音模式。我们在界面修改,在铃声到0后震动模式后,再次点击音量下键时,在更新界面处显示静音图标,以为这样可以规避问题满足客户需求,结果发现,当选择震动模式后,点击音量下到静音,这样没有问题。但是在设置中,先选择震动模式,然后关闭静音时震动,则应该到静音模式,实际上按音量下键调出volumeDialog时,显示的还是震动图标,而此时状态栏中显示的确实是静音图标?如果我们直接从正常的铃音模式切换到静音模式,那么图标都显示正常的。why?为什么这么神奇?为了解决上面问题,到代码中查找原因:

 

首先先说一下,AudioManager.java这个类,这个类提供了许多对第三方应用或系统应用调用的方法,如设置音量大小的方法,设置铃声铃声模式的方法。同时,该类也定义了铃音模式的三种类型:

public static final int RINGER_MODE_SILENT = 0;

public static final int RINGER_MODE_VIBRATE = 1;

public static final int RINGER_MODE_NORMAL = 2;

 

此处务必记住, AudioManager中定义的铃声类型(RingerMode)只有以上三种,并没有勿扰模式。所以说,勿扰模式是属于情景模式,但是不属于铃声模式的范畴。

 

其次, AudioManager.java这个类还定义了设置和获取铃声模式的public方法,getRingerMode(),setRingerMode(int)


进入到setRingerMode(int)发现,调用的是AudioService.java的setRingerModeExternal(),

继续调用到AudioService.java的setRingerMode(ringerMode, caller, true /*external*/)。

而设置铃声模式主要的实现就是在AudioService.java的setRingerMode()中,此处第三个参数传入的是true,setRingerMode的方法如下


在setRingerMode中前面的判断先不关注,直接看try语句里面的部分,当调用AudioManager的setRingerMode方法后,传入的参数external 是true,那么会进入到try语句中的上半部分。即调用setRingerModeExt(),


这个方法先判断传入的ringerMode值是否和mRingerModeExternal相等,若不同的话,直接将传入的ringerMode值赋给了mRingerModeExternal,然后发送RINGER_MODE_CHANGED_ACTION广播。

接下来setRingerMode()方法会去检查是否要去更新mRingerModeInternal这个变量的值。



而此时ringerMode又是从mRingerModeDelegate.onSetRingerModeExternal中从新更新了依次。Ringermodedelegate类是一个接口,而ZenModeHelper.java的RingerModeDelegate内部类实现了该接口,接下来看RingerModeDelegate类的onSetRingerModeExternal方法,现在才到了今天想分享的关键地方,也是引起项目出现问题的地方。

先看onSetRingerModeExternal实现


这个方法参数有点多,先解释下:

ringerModeOld  本次还未设置之前的ringerMode值,对应与Audioservice中的mRingerModeExternal的值

ringerModeNew  本次即将要设置的ringerMode值,该值是从第三方应用或系统应用,如设置,systemUI下来栏中图标传过来的值。

caller 调用者,那个应用来调的(分析该问题,可不关注)

ringerModeInternal 当前AudioService中mRingerMode的值,

policy 可不关注

 

搞清楚这些参数意思之后,再来分析代码,

boolean isChange 是判断当前ringerMode(mRingerModeExternal)值和即将要设置的ringerMode值是否相等,

isVibrate 是当前ringerModeInternal(对应与AudioService的mRingerMode值)是否是震动模式

 

然后判断即将要设置的ringerMode是那种类型,震动或者normal模式时,直接关闭勿扰模式,返回ringerModeInternalOut,也就是ringerModeNew,当ringerMode是静音模式时,判断isChange是否为true,true则进入勿扰,然后更新ringerModeInternalOut,再返回ringerModeInternalOut,而出现问题的地方是这里。先说流程,后面在分析问题。

 

返回之后又回到了AudioService的setRingerMode方法,再判断返回的ringerMode和当前的ringerModeInternal是否相等,若不相等,则调用setRingerModeInt()方法,



ringerModeInternal是否相等,若不相等,则调用setRingerModeInt()方法,

 

该方法即去同步设置mRingMode的值,然后发送INTERNAL_RINGER_MODE_CHANGED_ACTION广播。可见AudioService中的mRingerMode和mRingerModeExternal是否需要同步起作用的还是在Ringermodedelegate中。

 

现在来分析出现问题的原因,问题是:在设置或者systemUI中先打开静音模式开关,在打开静音时震动开关,此时是震动模式,然后关闭静音时震动开关,此时状态栏中显示的是静音模式,按音量下键,查看volumeDialog发现,是震动图标。这个问题的原因还是要看onSetRingerModeExternal方法。

这种情况下,onSetRingerModeExternal的几个参数相当与:

ringerModeOld  是震动模式

ringerModeNew  是静音模式

ringerModeInternal  震动模式

isChange true

isVibrate true  

这样的话按照代码流程,ringerModeInternalOut最终赋的值还是AudioManager.RINGER_MODE_VIBRATE,那么进入AudioService中会将mRingterMode的值设置成AudioManager.RINGER_MODE_VIBRATE,但是此时mRingerModeExternal的值是AudioManager.RINGER_MODE_SILENT,而设置中和systemUI状态栏使用的是mRingerModeExternal,所以显示的是静音,而且状态栏和设置中监听的广播也是RINGER_MODE_CHANGED_ACTION,即mRingerModeExternal改变后发出的广播。而VolumeDialog.java中用到的是mRingterMode(这个可到该类中去看,是通过AudioManager.getRingerModeInternal()获取的),当然显示的是震动图标了。

 

另一个问题,为什么我先设置成normal模式,再设置成静音模式时,都显示正常呢?

这种情况下,因为我们先设置了normal模式,那么onSetRingerModeExternal的参数相当与:

ringerModeOld  正常模式

ringerModeNew  静音模式

ringerModeInternal  正常模式

isChange true

isVibrate false

 

 此时依然会将情景模式切换到勿扰,但因为现在isVibrate是false,所以返回的ringerModeInternalOut是AudioManager.RINGER_MODE_SILENT,然后AudioService中同样会将mRingerMode设置成AudioManager.RINGER_MODE_SILENT,所以此时mRingerMode和mRingerModeExternal相同,都是AudioManager.RINGER_MODE_SILENT,所以这时候无论在systemUI,Settings还是VolumeDialog.java都显示静音。

 

到此,该问题的原因已经清晰~~~














版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Android M Zen mode(勿扰)分析

应用需要申请android.permission.ACCESS_NOTIFICATION_POLICY才可以操作Zen mode 在Settings下,用户可以设置哪些应用能控制Zen mode。

Android N适配小结

今天看完郭神关于M版本运行权限的视频,突然想到何不把最近项目中关于N版本适配的内容总结一下,和大家分享。

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

Android Audio系统之RingerMode

田海立@CSDN2012-04-11本文介绍Android系统中Audio里的RingerMode。从使用的角度,只要关注第一节AudioManager中对于RingerMode的接口;后面章节讲解了...
  • thl789
  • thl789
  • 2012-04-11 19:03
  • 11656

android之声音管理器AudioManager的使用

Android声音管理AudioManager使用手机都有声音模式,声音、静音还有震动,甚至震动加声音兼备,这些都是手机的基本功能。在Android手机中,我们同样可以通过Android的SDK提供的...

程序员如何提高工作效率?我是这样做的

当前,互联网从业者的压力越来越大,对程序员来说尤甚。很多程序员都是朝九晚九,但我发现大多数时候都是工作效率的问题。每隔两分钟看一会儿手机,有人发微信给你,有人打电话给你,有人朋友圈留言…。每次拿起手机...

iOS 时间戳 详解

http://www.2cto.com/kf/201407/315706.html 应用中设置一般会存在这样的设置,如夜间勿扰模式,从8:00-23:00,此时如何判断当前时间是否在该时...

OTA升级总结

android OTA升级

微信这些好用的功能你都用过吗?

微信中还有这些好用的功能

首次开机接收来电后短信无声

故障现场 这里的首次开机也包括恢复出厂设置后的第一次开机。出现故障后,配合机发送一条短信过来,一直没有提示音。打开AudioHW的PCM DUMP之后发现写下去的音频流为全0数据,查看dumpsys...

自控力太差?学编程的时候总是网上乱逛?你应该看看这个!

现在自学编程中,但发现在电脑前编程的时候,遇到不懂的问题,必然要Google的,然后打开Safari开始搜索。 以昨晚亲身体会为例,开始我是在Xcode中编程的时候,想学一下如何掌握Google...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)