首页 > 其他分享 >系统音量条

系统音量条

时间:2024-06-02 15:11:25浏览次数:6  
标签:调用 响铃 image 系统 音量 方法 通道

系统音量条

1、音量键处理

image-20200718161014564

image-20200718161014564

如上,对于一般场景下,按音量上/下键,其事件传递到焦点窗口的根节点布局时(一般的Activity根节点布局都是DecorView)会走到DecorView的dispatchKeyEvent方法中,这里主要有两个分支,一个是Window.Callback类型的cb处理事件(这里如果Activity有处理音量键事件并返回true,则具体音量事件逻辑看应用自身逻辑,如果对应Activity在处理音量键逻辑中什么都不做,那音量键相当于也没有什么实际效果,也不会弹出系统音量条),还有一个分支则是PhoneWindow中调用onKeyDown和onKeyUp处理事件,这里也是一般的按音量键弹出音量条所走的逻辑

image-20200718163848255

image-20200718163848255

image-20200718164021778

image-20200718164021778

如上所示,在PhoneWindow的onKeyDown和onKeyUp方法中,对于音量上/下键事件的处理是调用MediaSessionManager的dispatchVolumeKeyEventAsSystemService方法,MediaSessionManager的服务端是MediaSessionService,MediaSessionManager的前面的方法调用都会调用到其服务端MediaSessionService中,在一般显示系统音量条过程中,MediaSessionService中的主要作用是构建调用AudioService调节音量的方法(包括调节的通道、调节的粒度和flags构建等),然后在AudioService中才是真正调节音量的主要代码,在音量调节中如果音量有改变,则会发送”android.media.VOLUME_CHANGED_ACTION”的广播通知音量变更,在音量调节后会调用sendVolumeUpdate方法去告知SystemUI音量变更

image-20200718172628942

image-20200718172628942

这里调用了VolumeController的postVolumeChanged,其中VolumeController是AudioService的静态内部类

image-20200718202148663

image-20200718202148663

VolumeController的postVolumeChanged方法即调用了其mController变量的volumeChanged方法,这里mController变量是调用VolumeController的setController方法进行设置的

image-20200718202306217

image-20200718202306217

在AudioService的setVolumeController方法中会调用VolumeController的setController方法

image-20200718202420757

image-20200718202420757

在AudioManager中也有setVolumeController,其会调用到AudioService的setVolumeController方法,而在SystemUI中有调用该方法,其设置的VolumeController是VolumeDialogControllerImpl的内部类VC的对象

所以上述音量变更后通知SystemUI既是调用了VolumeDialogControllerImpl的内部类VC的volumeChanged方法回调

2、系统音量条显示逻辑

image-20200724224905501

image-20200724224905501

2.1、音量条显示逻辑

在前面AudioService中音量变更后回调到SystemUI的VolumeDialogControllerImpl.VC的volumeChanged时,即会触发显示系统音量条的逻辑(注意,这里有传入两个参数,streamType和flags),然后会调用到VolumeDialogControllerImpl的onVolumeChangedW方法中

image-20200724201644934

image-20200724201644934

这里会根据flags和当前场景、一些定制来判断是否显示系统音量条,其中flags相关主要是需要包含AudioManager.FLAG_SHOW_UI,如果判断需要显示,则最后会调用到VolumeDialogImpl.java中的onShowRequested方法中去显示系统音量条

image-20200724202243363

image-20200724202243363

onShowRequested方法中会调用showH方法去显示系统音量条

image-20200724202433129

image-20200724202433129

在showH方法中有两处比较重要,一是rescheduleTimeoutH方法,该方法是计算系统音量条自动消失时间,发送延时消息去dismiss音量条,二是mDialog.show,在SystemUI启动时就已准备好了mDialog,在音量相关变更时会更新相关信息,然后在这里只需调用mDialog.show方法即会去显示系统音量条

image-20200724211928846

image-20200724211928846

2.2、音量条布局

在SystemUI启动时,会调用到VolumeDialogImpl的init方法初始化,其中initDialog方法即是对音量条的显示的重要部分,这里会创建mDialog并加载对应布局和设置显示相关参数,其中加载具体各通道音量条的相关代码如下

image-20200724214506628

image-20200724214506628

这里会对各通道的音量调用addRow方法,以将各通道的音量布局加载添加到mDialog布局中

image-20200724214732911

image-20200724214732911

在initRow方法中会根据传入的参数构建VolumeRow对象,其中会添加布局等相关信息

2.2.1、音量通道布局的显示与隐藏

前面可以看到,音量条一般有加载七个通道的布局,但其实一般的话可能只会显示一个通道的音量

在构建mDialog和音量相关变更时(onStateChanged)会触发updateRowsH方法调用

image-20200724220752911

image-20200724220752911

在updateRowsH方法中会遍历各通道的VolumeRow,调用shouldBeVisibleH方法来判断是否需要显示对应通道的音量条,然后设置对应控件可见性为VISIBLE或GONE

在音量相关变更时,会更新相关音量信息如音量大小等,然后会触发onStateChanged调用,其会调用到VolumeDialogImpl的onStateChangedH方法中更新视图相关,包括控件可见性,其也会调用updateVolumeRowH方法来更新各通道控件的信息如seekbar的进度

2.3、音量通道

前面有介绍系统音量条一般有加载七个不同通道的音量条,但其实通道并不止七个

image-20200724222036667

image-20200724222036667

其定义都在AudioSystem中

image-20200724222302846

image-20200724222302846

虽然有11个通道,但因为有些通道变更都是一起的,在音量变更时会有个映射,传到SystemUI的是其映射后的通道(其实在音量变更时,即使设置单个通道音量变更,其也会影响映射相关的多个通道)

image-20200724222521284

image-20200724222521284

其中mStreamVolumeAlias映射关系是在AudioService中赋值的

image-20200724222806145

image-20200724222806145

比如一般手机是PLATFORM_VOICE,则mStreamVolumeAlias则是STREAM_VOLUME_ALIAS_VOICE

image-20200724223455799

image-20200724223455799

上面即可看出其映射关系

2.4、activeStream

在AudioService中有个getActiveStreamType方法,其可获取当前activeStream,同一时间只有一个activeStream,一般使用中的音频通道即为activeStream,如播放音乐时一般activeStream是媒体通道STREAM_MUSIC,但也有其他情况,该方法中也说明了在多个音频通道同时播放或无音频播放时的activeStream

3、安全音量

image-20200725200542853

image-20200725200542853

在插入耳机后在调大音量时可能会弹出如上Dialog,在通过AudioService调节音量时会调用checkSafeMediaVolume方法

image-20200725203104454

image-20200725203104454

在一些特定设备如有线耳机等,且调节的音量通道是媒体通道,且调节音量大于安全音量时,checkSafeMediaVolume方法返回false,此时会调用AudioService$VolumeController的postDisplaySafeVolumeWarning方法

image-20200725203751056

image-20200725203751056

然后其流程与volumeChanged差不多,其会调用到SystemUI的VolumeDialogImpl的showSafetyWarningH方法来显示上面提示

image-20200725203947694

image-20200725203947694

4、自定义音量按键事件处理

很多视频播放界面都会自定义音量键处理和音量控件,其主要包括两部分,一是获取音量键事件,并调节音量,且注意应不让系统音量条显示,二是监听音量变更实现自定义的音量显示控件

image-20200727220151731

image-20200727220151731

如上,自己本地写了个小demo,在拦截音量上/下键并自己处理返回true后,在该界面按音量上/下键就不会弹系统音量条了(注意,这里adjustStreamVolume是调节音量的api,其第二个参数如果包含了AudioManager.FLAG_SHOW_UI那么仍是会弹出系统音量条的)

image-20200727221711842

image-20200727221711842

如上自己本地demo中写了个简单的seekbar的控件,然后监听了”android.media.VOLUME_CHANGED_ACTION”广播,收到广播后刷新seekbar进度

当然,如果需要音量控件是可滑动调节的,那么还需要监听对应控件的change事件,然后可调用AudioManager的setStreamVolume方法来设置音量

5、RingerMode

Android有三种响铃模式:响铃、振动、静音,在音量条上方按钮点击可切换不同模式,其在不同模式下主要会影响铃声相关的声音,如通知等

image-20200801161505257

image-20200801161505257

先查看下点击切换响铃模式按钮相关逻辑,响铃按钮是mRingerIcon,其点击事件如下

image-20200801161340942

image-20200801161340942

这里主要切换响铃模式逻辑是其中根据当前的模式和机器相关情况,计算新的响铃模式,然后调用mController.setRingerMode方法来设置新的响铃模式,其中mController是VolumeDialogControllerImpl的对象,其最后会调用到AudioManager的接口来设置新的响铃模式,这里按照上面逻辑会调用其setRingerModeInternal方法

image-20200801162528162

image-20200801162528162

AudioManager会直接调到AudioService中

image-20200801162915940

image-20200801162915940

这里主要会调用到AudioService的setRingerMode方法

image-20200801163446151

image-20200801163446151

其主要代码有三部分

一是setRingerModeInt方法,这里是主要部分逻辑,放在后面查看

二是mRingerModeDelegate相关回调,这里mRingerModeDelegate其实是ZenModeHelper的内部类RingerModeDelegate的对象,这里回调会记录响铃模式和可能调整勿扰模式

三是调用setRingerModeExt方法,这里会发送”android.media.RINGER_MODE_CHANGED”的广播

这里继续查看setRingerModeInt方法:

image-20200801165201500

image-20200801165201500

这里逻辑也比较多,简要介绍下

1、muteRingerModeStreams,该方法是这里主要部分逻辑,也是响铃模式切换的主要逻辑,在该方法中会根据响铃模式和其他如勿扰模式、设备等相关情况,判断是否需要将一些通道静音,如一般情况下,从响铃模式切换到振动或静音模式时,会将铃声相关通道mute,音量设为0,而切回响铃模式时,又会将音量设回去

2、如果persist参数为true,则一般会将新响铃模式设置到Settings.Global.MODE_RINGER

3、如果响铃模式变更,这里会发送”android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION”广播

5.1、音量调节触发RingerMode变更及VolumePolicy

在调节铃声音量时,我们可能注意到,在响铃模式,将铃声音量调制最低时,会自动变为振动模式,而在振动模式,将铃声音量调高时,会自动退出振动模式变为响铃模式

这是因为在调节音量时会有相关检查

在设置音量时,其在AudioService中会触发onSetStreamVolume调用

image-20200801172241812

image-20200801172241812

其中getNewRingerMode一般会根据铃声音量来计算新的响铃模式

image-20200801172418078

image-20200801172418078

在调节音量时也可能会触发checkForRingerModeChange方法调用

image-20200801172845958

image-20200801172845958

这里未将checkForRingerModeChange方法全部贴出来,其也是会根据当前相关情景调节响铃模式

在上面一些判断中,除了手机有没有振动器等的判断,还有mVolumePolicy的变量的判断,VolumePolicy是个单独的类,其主要是保存有几个变量

image-20200801174249287

image-20200801174249287

一般这个volumepolicy是SystemUI调用setVolumePolicy有设置的,

image-20200801173739711

image-20200801173739711

标签:调用,响铃,image,系统,音量,方法,通道
From: https://www.cnblogs.com/luoliang13/p/18227152

相关文章

  • rt-thread 系统pm组件在4.1.1版本的无法正常唤醒的问题解决方法
    在老的rt-thread版本系统pm组件调试ok,后来使用4.1.1版本时发现进入低功耗后无法正常唤醒,问题解决路径如下硬件信息:cpu STM32L431CCT6新建系统打开pm组件后也没有drv_pm.c和drv_lptim.c自动添加,需要到系统目下找到并复制到driver目录下C:\RT-ThreadStudio\repo\Extract\R......
  • 金铲铲系统拆解
    金铲铲系统拆解此次写游戏系统拆解的目的是帮助自己总结在学习游戏系统策划中学到的知识,以及以后回顾自己的学习是否有进步。本次的拆解文章大纲如下:游戏概述简要结论系统拆分游戏概述游戏类型《金铲铲之战》作为端游《云顶之弈》的手机版,基本还原了云顶之弈的玩法和美术风格。该......
  • Springboot计算机毕业设计一次性环保餐具销售系统小程序【附源码】开题+论文+mysql+程
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景:随着外卖和快餐文化的快速发展,一次性餐具的使用量急剧增加,给环境带来了沉重的负担。传统的一次性餐具多为塑料制品,难以降解,对环境造成了长期污染。因......
  • 高可用系统部署
    一、整体架构的规划前提:1、搭建一个wordpress博客,web网站需要搭建成一个高可用的架构。2、数据库:一主双从3、前端web产生的数据:需要存放到内网环境的一个nfs服务器上进行保存4、nfs需要搭建为高可用的状态5、前端需要使用调度器来调度用户的请求。注意:因为本地物理机......
  • JAVA计算机毕业设计基于Vue学生选课管理系统(附源码+springboot+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在现代高等教育体系中,学生选课管理是一项复杂且至关重要的工作。随着学生人数的不断增加和课程种类的日益丰富,传统的手工选课管理方式已经无法满足高......
  • JAVA计算机毕业设计基于vue图书馆选座系统设计与实现(附源码+springboot+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高校图书馆的日益繁忙和学生对学习环境需求的提高,图书馆座位管理成为了一个亟待解决的问题。传统的图书馆座位管理方式往往存在效率低下、资源浪......
  • 毕业设计-基于Java 和 Mysql 实现的宿舍管理系统
    毕业设计-基于Java和Mysql实现的宿舍管理系统    学生宿舍管理系统,是基于Java,数据库是mysql数据库。本地已调试好,可以直接部署使用。    功能还是比较丰富的,包含了学生、班级、宿舍、卫生、访客等内容的添加、删除、导出;用户还分管理员和普通用户。主要实......
  • Linux目录的基本结构(RHEL8系统基本使用之文件操作)
    1.Linux的目录树结构2.各目录的功能介绍3.理解文件路径表示方法Who?——>当前登录的用户Where?——>路径我要在哪儿创建文件?我要删除什么地方的什么文件?我所要查看的文件在哪里?What?——>操作命令How?——>理清思路,找到方法,做就对了绝对路径1.一定是以"/"(根)开......
  • 在Linux中,如何进行系统性能瓶颈分析?
    在Linux中进行系统性能瓶颈分析是一个系统性的过程,涉及多个方面。以下是一个详细的步骤说明,用于分析和诊断Linux系统性能瓶颈:1.确定性能指标CPU利用率:检查CPU是否成为瓶颈。可以使用top、htop等工具查看CPU的使用情况,包括用户态、内核态和空闲态的占比。内存使用:检查内存是否......
  • 在Linux中,如何进行系统故障恢复?
    在Linux系统中进行故障恢复是一个涉及诊断问题、制定恢复计划并执行恢复步骤的过程。以下是一些基本步骤和策略,帮助您应对不同类型的系统故障:1.初步诊断与隔离识别症状:首先,观察并记录故障的具体表现,比如系统无法启动、服务异常、性能下降等。查看系统日志:使用dmesg命令查看内......