Android动态设置系统音量最大值

产品需求

  • 通过设定最大音量限制大屏声音输出,设置完后需要立即生效且需要记忆;
  • 以10%为递增状态,设置最大音量后,无论最大音量调节至多少百分比,音量条始终显示为100%(比如最大音量设置为80%,即侧边音量条依然可以显示充满,但是音量只有原来的80%)。

从技术角度上理解为:Framework层需要提供一个动态设置系统音量最大值的开放接口供应用层调用,应用apk通过设置最大音量百分比后系统声音效果需要立即生效,同时原生音量条的最大值范围也要变化。

需要涉及3个地方的修改:

  • 添加Framework层接口方法
  • 应用层apk调用新增的接口
  • SystemUI音量条监听最大值变化

Framework层接口

1、以Android 13为例,如果修改系统默认的STREAM_MUSIC音量值,通常是修改AudioService.java下MAX_STREAM_VOLUME数组对应的值15。但我们需要动态修改这个值且不需要重启服务立即生效。

/** Maximum volume index values for audio streams */
protected static int[] MAX_STREAM_VOLUME = new int[] {5,  // STREAM_VOICE_CALL7,  // STREAM_SYSTEM7,  // STREAM_RING15, // STREAM_MUSIC7,  // STREAM_ALARM7,  // STREAM_NOTIFICATION......
};

2、代码实现
/frameworks/base/media/java/android/media/AudioManager.java
/frameworks/base/media/java/android/media/IAudioService.aidl
/frameworks/base/services/core/java/com/android/server/audio/AudioService.java

IAudioService.aidl主要是声明一个新的系统服务方法,然后通过AudioManager.java来调用服务的具体实现

public void setStreamMaxVolume(int streamType, int maxVolume) {final IAudioService service = getService();try {service.setStreamMaxVolume(streamType, maxVolume);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

AudioService.java具体实现setStreamMaxVolume方法

//动态变更STREAM_MUSIC最大音量值接口
public void setStreamMaxVolume(int streamType, int maxVolume) {ensureValidStreamType(streamType);if (streamType == AudioSystem.STREAM_MUSIC) {if (maxVolume <= 15 && maxVolume >= 0) {int preMaxVolume = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];//更新MAX_STREAM_VOLUME数组值同时更新mIndexMaxMAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxVolume;mStreamStates[streamType].updateMaxIndex(maxVolume);//发送一个MAX_VOLUME_CHANGED_ACTION广播用于通知最大音量值变化,该系统广播需要声明在frameworks/base/core/res/AndroidManifest.xml里Intent intent = new Intent("com.ist.media.MAX_VOLUME_CHANGED_ACTION");intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);intent.putExtra("preMaxVolume", preMaxVolume);intent.putExtra("maxVolume", maxVolume);sendBroadcastToAll(intent);}}
}//关键:该方法加在内部class VolumeStreamState中,VolumeStreamState保存了运行时的音量信息,这里有个流音量index的换算关系,更新MAX_STREAM_VOLUME数组的同时也需要更新mIndexMax       
//mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
public void updateMaxIndex(int index) {mIndexMax = index * 10;
}

设置后需要有记忆性,即重启后AudioService服务构造初始化时设置最大音量值

	int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);if (maxMusicVolume != -1) {MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;} else {//add by XXX 初始化STREAM_MUSIC最大音量值String ptsStr = mSettings.getGlobalString(mContentResolver, "persist.sys.hht.max_volume_percent");//上层通过该Settings值来保存音量设置的百分比if (TextUtils.isEmpty(ptsStr)) {ptsStr = "10";}int maxPercent = Integer.parseInt(ptsStr);maxMusicVolume = Math.round((float) maxPercent / 10 * 15);MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;Log.i(TAG, "init maxMusicVolume = " + maxMusicVolume);//end by XXX
}

应用层apk调用

 /*** 设置最大音量百分比* @param percent 0~10,10%递进*/public void setMaxVolumePercent(int percent){Log.i(TAG, "setMaxVolumePercent() percent = "+ percent);//保存最大音量百分比设置Settings.Global.putString(context.getContentResolver(), "persist.sys.hht.max_volume_percent", String.valueOf(percent));//最大音量值设置后需要立即生效if (mAudioManager != null) {int currentMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);//获取系统最大音量值int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);//当前音量值int maxMusicVolume = Math.round((float) percent / 10 * 15);//调用新增的系统接口方法mAudioManager.setStreamMaxVolume(AudioManager.STREAM_MUSIC, maxMusicVolume);Log.i(TAG, "setStreamMaxVolume = " + maxMusicVolume);if (currentVolume > maxMusicVolume) { //若当前音量值大于最大音量值则取较小值mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxMusicVolume, 0);}}}

SystemUI音量条监听最大值变化

/frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java

final String action = intent.getAction();
boolean changed = false;
if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);final int oldLevel = intent.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream+ " level=" + level + " oldLevel=" + oldLevel);changed = updateStreamLevelW(stream, level);
}
......
//add by XXX 侧边音量条最大值即时更新
else if (action.equals("com.ist.media.MAX_VOLUME_CHANGED_ACTION")) {Log.d(TAG, "onReceive com.ist.media.MAX_VOLUME_CHANGED_ACTION");final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);final int preMaxVolume = intent.getIntExtra("preMaxVolume", -1);final int maxVolume = intent.getIntExtra("maxVolume", -1);Log.i(TAG, "onReceive preMaxVolume = " + preMaxVolume + ", maxVolume = " + maxVolume);if (preMaxVolume != maxVolume) {changed = true;getState();}
}
//end by XXX
if (changed) {mCallbacks.onStateChanged(mState);
}

dumpsys audio调试

通过adb shell dumpsys audio命令查看音频系统的状态信息。
Stream volumes (device: index):查看各类型流的音量值。其中Muted为是否静音,Min为最小值,Max为最大值,Current为各输出设备的当前音量,Devices为当前输出设备。
调试时,我们关注STREAM_MUSIC的Max值有没有按预期的变化即可。

- STREAM_MUSIC:Muted: falseMuted Internally: falseMin: 0Max: 15streamVolume:8Current: 2 (speaker): 8, 400 (hdmi): 8, 80000 (spdif): 8, 100000 (fm_transmitter): 8, 4000000 (usb_headset): 2, 10000000 (echo_canceller): 8, 40000000 (default): 3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/867295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Threejs环境、透视相机、坐标系、光源

文章目录 如何引入threejsnpm方式script方式script module方式 基本流程与坐标摄像机Geometry(几何体)和Material(材质)光源 如何引入threejs 对于很多刚刚上手threejs的朋友&#xff0c;可能第一步引入threejs就出问题了&#xff0c; 明明已经导入了&#xff0c;就是这样问题…

【搭建Nacos服务】centos7 docker从0搭建Nacos服务

前言 本次搭建基于阿里云服务器系统为&#xff08;CentOS7 Linux&#xff09;、Nacos&#xff08;2.0.3&#xff09;、Docker version 26.1.4 本次搭建基于一个新的云服务器 安装java yum install -y java-1.8.0-openjdk.x86_64安装驱动以及gcc等前置需要的命令 yum install …

【nvm管理nodejs版本,切换node指定版本】

nvm管理nodejs版本 nvm管理nodejs版本主要功能使用 nvm nvm管理nodejs版本 nvm&#xff08;Node Version Manager&#xff09;顾名思义node版本管理器&#xff0c;无须去node管网下载很多node安装程序;用于管理多个 Node.js 版本的工具。它允许你在同一台机器上同时安装和管理…

Appium启动APP时报错Security exception: Permission Denial

报错内容Security exception: Permission Denial: starting Intent 直接通过am命令尝试也是同样的报错 查阅资料了解到&#xff1a;android:exported | App quality | Android Developers exported属性默认false&#xff0c;所以android:exported"false"修改为t…

基于java+springboot+vue实现的图书商城管理系统(文末源码+Lw)283

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本图书商城管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信…

rpm包下载

内网无法下载、选择外网的一台机器下载rpm包 下载后上传rpm包 1、创建下载目录 mkdir /data/asap/test 2、下载能留存包的工具 sudo yum install yum-utils -y 报错就是环境问题没下载成功&#xff0c;我换了个环境正常的机器就可以了 3、下载rpm包到指定目录/data/asa…

测试人员如何管理项目与风险预警

在平时工作过程中&#xff0c;你有没有因项目延时&#xff0c;需求频繁变更&#xff0c;开发提测质量不高&#xff0c;以及漏测的情况下&#xff0c;背了不少锅的情况呢&#xff1f; 作为测试人员&#xff0c;我们应该如何发挥积极主动性&#xff0c;进行项目管理&#xff0c;有…

【学术会议征稿】2024年第十届机械制造技术与工程材料国际学术会议(ICMTEM 2024)

2024年第十届机械制造技术与工程材料国际学术会议&#xff08;ICMTEM 2024&#xff09; 2024 10th International Forum on Manufacturing Technology and Engineering Materials 第十届机械制造技术与工程材料国际学术会议&#xff08;ICMTEM 2024&#xff09;将于2024年10月…

(七)[重制]C++命名空间与标准模板库(STL)

​ 引言 在专栏C教程的第六篇C中的结构体与联合体中&#xff0c;介绍了C中的结构体和联合体&#xff0c;包括它们的定义、初始化、内存布局和对齐&#xff0c;以及作为函数参数和返回值的应用。在专栏C教程的第七篇中&#xff0c;我们将深入了解C中的命名空间&#xff08;nam…

linux 基础命令、gcc的基础用法

1、ls——>列出目录下的内容 语法&#xff1a;ls [-a -l -h] [Linux路径] &#xff08;1&#xff09;-a -l -h 是可选的选项 &#xff08;2&#xff09;Linux路径是此命令的可选参数 ①当不使用选项和参数&#xff0c;直接使用 ls 命令本体&#xff0c;表示&#xff1a;…

kubernetes集群部署:环境准备及master节点部署(二)

主机名IPv4地址IPv6地址角色安装组件操作系统k8s130-node190192.168.XX.190240a:XX::190masterkubeadm、kubelet、containerdAnolis OS 8.94.19.91-28.1.an8.x86_64k8s130-node191192.168.XX.191240a:XX::191nodekubeadm、kubelet、cri-oAnolis OS 8.94.19.91-28.1.an8.x86_64k…

Java基础-接口与实现

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 Java 接口 什么是接口&#xff1f; 声明接口 实现接口 继承接口 接口的多继承 标记接口 Java 接口 …

华为仓颉可以取代 Java 吗?

大家好&#xff0c;我是君哥。 在最近的华为开发者大会上&#xff0c;华为亮相了仓颉编程语言&#xff0c;这是华为历经 5 年&#xff0c;投入大量研发成本沉淀的一门编程语言。 1 仓颉简介 按照官方报告&#xff0c;仓颉编程语言是一款面向全场景智能的新一代编程语言&#…

好消息!Stable Diffusion 3 允许商业化,很快开源更大版本模型

7月6日凌晨&#xff0c;著名开源大模型平台Stability AI修改了社区许可协议&#xff0c;最新发布的文生图模型Stable Diffusion 3 Medium允许商业化&#xff08;以下简称“SD3-M”&#xff09;。 如果企业、个人开发者每年收入低于100万美元&#xff08;大约726万元人民币&…

《安全行业大模型技术应用态势发展报告(2024)》

人工智能技术快速迭代发展&#xff0c;大模型应用场景不断拓展&#xff0c;随着安全行业对人工智能技术的应用程度日益加深&#xff0c;大模型在网络安全领域的应用潜力和挑战逐渐显现。安全行业大模型技术的应用实践不断涌现&#xff0c;其在威胁检测、风险评估和安全运营等方…

腐蚀服务器如何设置管理员

可以设置服主与管理员 控制台中设置&#xff08;需游戏账号在线&#xff09; 服主 添加&#xff1a;在控制台中输入ownerid空格SteamID 删除&#xff1a;在控制台中输入removeowner空格SteamID 管理员 添加&#xff1a;在控制台中输入moderatorid空格SteamID 删除&#…

C++:二维数组的遍历

方式一&#xff1a; #include <vector> #include <iostream> int main() { // 初始化一个2x3的二维向量&#xff08;矩阵&#xff09; std::vector<std::vector<float>> matrix { {1.0, 2.0, 3.0}, // 第一行 {4.0, 5.0, 6.0} // 第二行 };…

【Python文件】操作终极指南:高效管理和处理文件系统的必备技能

目录 ​编辑 1. 文件的基础操作 1.1 打开/关闭文件 ​编辑 示例代码 文件对象 使用with语句打开文件 2. 读文件 2.1 使用read方法读取文件 2.2 使用readline方法读取文件 2.3 使用readlines方法读取文件 2.4 使用for循环读取文件 3. 写文件 3.1 使用write方法写文…

B组亚太赛数学建模

问题1 1.对训练数据集进行数据清洗&#xff0c;处理缺失值和异常值。 2.采用散点图作为可视化手段。 3.采用皮尔逊相关系数进行相关性分析。 4.提出预防措施。 问题2 1.采用k-means聚类算法将洪水概率分为高中低三个群组。 2.通过线性回归模型计算特征权重。 3.选择特定…