AndroidQ 设置静音模式后按音量上键不能调节音量大小

2023-10-30 10:10

本文主要是介绍AndroidQ 设置静音模式后按音量上键不能调节音量大小,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

AndroidQ按音量键,默认会调出meida的音量,但是客户要求将默认调出ringer。改为默认ringer后,发现点击音量条上方的ringer_icon,设置为静音模式后,在按音量上键,不能调节音量大小了。

关于音量这块,framework中是与AudioService、AudioManager、AudioSystem相关,音量弹框的界面处理是在SystemUI下,有个volumn的文件夹。

要解此问题,很显然要从AudioService入手,因为音量的加减和AudioProfile模式都是在AudioServie处理好之后,将消息发给SystemUI,SystemUI去做界面上的更新。

AudioService中处理音量的关键方法adjustSuggestedStreamVolume–>adjustStreamVolume
adjustSuggestedStreamVolume根据名称可以猜到是Suggested,建议的音量调整。该方法主要是将传递进来的suggestedStreamType,通过etActiveStreamType方法计算出来真正要调整的音量类型。前面说的客户要求将默认的音量类型由media改为ringer关键就是在这个方法中处理的。
在这里插入图片描述
adjustSuggestedStreamVolume计算出来真正需要调整的音量类型后就调用adjustStreamVolume,流程转到adjustStreamVolume中。

这里先说一个AudioService中的内部类VolumeStreamState,每种音量类型(STREAM_VOICE_CALL、STREAM_RING、STREAM_MUSIC。。。)都会实例化一个VolumeStreamState对象,其中int mStreamType就是音量类型,还有一个SparseIntArray mIndexMap,这里有个device的概念,比如说STREAM_MUSIC类型,music可以通过麦克、耳机(有线、蓝牙耳机)等很多设备播放,这个SparseIntArray就是保存的该种音量类型在不同设备上的音量大小。

在这里插入图片描述
流程转到adjustStreamVolume中,首先该方法有一些条件判断,不满足的直接return。通过重重判断后来到第一个关键的地方:
在这里插入图片描述
计算步长,就是本次音量调整调多少,log看到是以10为步长的。比如15级的音量,通过音量键调大小是70、80、90等等这样的大小,step是以10来增加的。
再下来就进入了RingerMode的相关处理了
在这里插入图片描述
跟踪getUiSoundsStreamType的实现,就是STREAM_RING

/** @see AudioManager#getUiSoundsStreamType()  */public int getUiSoundsStreamType() {return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];}private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALLAudioSystem.STREAM_RING,            // STREAM_SYSTEMAudioSystem.STREAM_RING,            // STREAM_RINGAudioSystem.STREAM_MUSIC,           // STREAM_MUSICAudioSystem.STREAM_ALARM,           // STREAM_ALARMAudioSystem.STREAM_RING,            // STREAM_NOTIFICATIONAudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCOAudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCEDAudioSystem.STREAM_RING,            // STREAM_DTMFAudioSystem.STREAM_MUSIC,           // STREAM_TTSAudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY};

来看下checkForRingerModeChange的逻辑,该方法是case不同的mode,我们重点关注RINGER_MODE_SILENT。mIsSingleVolume为false,那就进到else if中
!mVolumePolicy.volumeUpToExitSilent =====》添加一个hint标志位
else ====》切换到振动模式(振动模式下增加音量就会切到normal模式,然后就可以正常调整音量了)
在这里插入图片描述
现在暂时将mVolumePolicy.volumeUpToExitSilent的来源忽略,继续跟踪adjustStreamVolume后面的逻辑。
在这里插入图片描述
checkForRingerModeChange的计算结果会影响adjustVolume的boolean值。
调整音量值的是在我们上面提到的内部类VolumeStreamState中,
在这里插入图片描述
adjustStreamVolume方法的最后一行是调用sendVolumeUpdate

// UI update and Broadcast Intentprotected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags, int device){streamType = mStreamVolumeAlias[streamType];if (streamType == AudioSystem.STREAM_MUSIC) {flags = updateFlagsForTvPlatform(flags);if ((device & mFullVolumeDevices) != 0) {flags &= ~AudioManager.FLAG_SHOW_UI;}}mVolumeController.postVolumeChanged(streamType, flags);}public void postVolumeChanged(int streamType, int flags) {if (mController == null)return;try {mController.volumeChanged(streamType, flags);} catch (RemoteException e) {Log.w(TAG, "Error calling volumeChanged", e);}}

这里的volumeChanged就是向SystemUI去通知音量变化了,SystemUI收到该通知就会读取系统音量:
frameworks\base\packages\SystemUI\src\com\android\systemui\volume\VolumeDialogControllerImpl.java代码:
在这里插入图片描述
在这里插入图片描述
这里的getAudioManagerStreamVolume,最后就是调用AudioService的getLastAudibleStreamVolume,即上面提到的VolumeStreamType中put的值

/** Get last audible volume before stream was muted. */public int getLastAudibleStreamVolume(int streamType) {ensureValidStreamType(streamType);int device = getDeviceForStream(streamType);return (mStreamStates[streamType].getIndex(device) + 5) / 10;}

到此是音量调整从AudioService到SystemUI中的逻辑。
对于我们这个问题,静音模式下不能调节音量的问题,我们回到前面忽略的关键判断:checkForRingerModeChange方法中的mVolumePolicy.volumeUpToExitSilent,从名称上就好理解,音量上键退出静音模式,追踪mVolumePolicy的赋值

@Overridepublic void setVolumePolicy(VolumePolicy policy) {enforceVolumeController("set volume policy");if (policy != null && !policy.equals(mVolumePolicy)) {mVolumePolicy = policy;if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);}}

public方法,显然是被外界调用的,framework/base下搜索,竟然是在SystemUI下的VolumeDialogComponent.java中调用
看下该类是如果实例化VolumePolicy对象的:
在这里插入图片描述
果然DEFAULT_VOLUME_UP_TO_EXIT_SILENT配置的是false,改为true就可以在静音模式下按音量上面,先切换到振动模式,再按音量上键,进入normal模式,就可以正常调节音量了。

这篇关于AndroidQ 设置静音模式后按音量上键不能调节音量大小的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/307179

相关文章

SQL Server 查询数据库及数据文件大小的方法

《SQLServer查询数据库及数据文件大小的方法》文章介绍了查询数据库大小的SQL方法及存储过程实现,涵盖当前数据库、所有数据库的总大小及文件明细,本文结合实例代码给大家介绍的非常详细,感兴趣的... 目录1. 直接使用SQL1.1 查询当前数据库大小1.2 查询所有数据库的大小1.3 查询每个数据库的详

MySQL设置密码复杂度策略的完整步骤(附代码示例)

《MySQL设置密码复杂度策略的完整步骤(附代码示例)》MySQL密码策略还可能包括密码复杂度的检查,如是否要求密码包含大写字母、小写字母、数字和特殊字符等,:本文主要介绍MySQL设置密码复杂度... 目录前言1. 使用 validate_password 插件1.1 启用 validate_passwo

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

小白也能轻松上手! 路由器设置优化指南

《小白也能轻松上手!路由器设置优化指南》在日常生活中,我们常常会遇到WiFi网速慢的问题,这主要受到三个方面的影响,首要原因是WiFi产品的配置优化不合理,其次是硬件性能的不足,以及宽带线路本身的质... 在数字化时代,网络已成为生活必需品,追剧、游戏、办公、学习都离不开稳定高速的网络。但很多人面对新路由器

linux hostname设置全过程

《linuxhostname设置全过程》:本文主要介绍linuxhostname设置全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录查询hostname设置步骤其它相关点hostid/etc/hostsEDChina编程A工具license破解注意事项总结以RHE

Python设置Cookie永不超时的详细指南

《Python设置Cookie永不超时的详细指南》Cookie是一种存储在用户浏览器中的小型数据片段,用于记录用户的登录状态、偏好设置等信息,下面小编就来和大家详细讲讲Python如何设置Cookie... 目录一、Cookie的作用与重要性二、Cookie过期的原因三、实现Cookie永不超时的方法(一)

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操