按键音分析

  • 触摸按键音流程
    • 第一部分
    • 第二部分
    • AudioService.java
  • 物理按键音流程

触摸按键音流程

前面简要的流程我们就不分析了,画了一下简要的流程图,由于我分析的源码具有特殊性,分为两条线路来看

第一部分

客制化实现按键音部分,也就是意味着加载资源和播放按键音是单独实现的。实际上是走外部音源调音的这条线路

第二部分

原生的按键音流程,后面会挑一些比较关键的流程分析记录一下

AudioService.java

我们看主要看下AudioService.java中的的流程

    /** @see AudioManager#playSoundEffect(int, float) */public void playSoundEffectVolume(int effectType, float volume) {if (mUseDspEffect) {final IAudioPolicyCallback extVolCtlr;synchronized (mExtVolumeControllerLock) {extVolCtlr = mExtVolumeController;}if(extVolCtlr != null) {//MSG_NOTIFY_VOL_EVENT会发送到外部路由策略端(该部分实际是用于调节音量的流程)sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,AudioManager.ADJUST_PLAY_EFFECT + effectType, 0 /*ignored*/,extVolCtlr, 0 /*delay*/);}else{dLog.e(TAG, "AudioService playSoundEffectVolume failed for no ext Volume Controller found!");}return;}// do not try to play the sound effect if the system stream is mutedif (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {return;}if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {Log.w(TAG, "AudioService effectType value " + effectType + " out of range");return;}//Android原生的按键音流程sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,effectType, (int) (volume * 1000), null, 0);}

我们主要看Android原生的按键音流程

private void onPlaySoundEffect(int effectType, int volume) {synchronized (mSoundEffectsLock) {onLoadSoundEffects(); //初始化资源文件、构造SoundPoolif (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],volFloat, volFloat, 0, 0, 1.0f);//使用soundpool实现按键音} else {//使用mediaPlayer播放按键音资源文件}}}

简单的看下onLoadSoundEffects方法

        private boolean onLoadSoundEffects() {int status;loadTouchSoundAssets();  //1、从framework/res 下的audio_assets.xml中,将id和按键音资源文件名解析后保存到SOUND_EFFECT_FILES_MAP 数组中。资源文件名保存到SOUND_EFFECT_FILES list中//构造soundpoolmSoundPool = new SoundPool.Builder().setMaxStreams(NUM_SOUNDPOOL_CHANNELS).setAudioAttributes(new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build()).build();mSoundPoolCallBack = null;mSoundPoolListenerThread = new SoundPoolListenerThread();mSoundPoolListenerThread.start(); //启动一个soundpool load资源文件的线程/** poolId table: The value -1 in this table indicates that corresponding* file (same index in SOUND_EFFECT_FILES[] has not been loaded.* Once loaded, the value in poolId is the sample ID and the same* sample can be reused for another effect using the same file.*///将poolId的每一位都设置为-1int[] poolId = new int[SOUND_EFFECT_FILES.size()];for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {poolId[fileIdx] = -1;}/** Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.* If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:* this indicates we have a valid sample loaded for this effect.*///通过soundpool load system/media/audio/ui/下的每一个文件,load成功后,将poolId的每一位重新赋值。int numSamples = 0;for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {// Do not load sample if this effect uses the MediaPlayerif (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {continue;}if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {String filePath = getSoundEffectFilePath(effect);int sampleId = mSoundPool.load(filePath, 0);if (sampleId <= 0) {Log.w(TAG, "Soundpool could not load file: "+filePath);} else {SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;numSamples++;}} else {SOUND_EFFECT_FILES_MAP[effect][1] =poolId[SOUND_EFFECT_FILES_MAP[effect][0]];}}// wait for all samples to be loaded//所有的资源文件都成功的load完成,最后将soundpool releaseif (numSamples > 0) {mSoundPoolCallBack.setSamples(poolId);attempts = 3;status = 1;while ((status == 1) && (attempts-- > 0)) {try {mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);status = mSoundPoolCallBack.status();} catch (InterruptedException e) {Log.w(TAG, "Interrupted while waiting sound pool callback.");}}} else {status = -1;}if (mSoundPoolLooper != null) {mSoundPoolLooper.quit();mSoundPoolLooper = null;}mSoundPoolListenerThread = null;if (status != 0) {Log.w(TAG,"onLoadSoundEffects(), Error "+status+ " while loading samples");for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {SOUND_EFFECT_FILES_MAP[effect][1] = -1;}}mSoundPool.release();mSoundPool = null;}}return (status == 0);}

onLoadSoundEffects load资源完成后,就可以通过soundpool play实现按键音了。

如果有兴趣了解SoundPool的同学可以点击这里

物理按键音流程

Android P 按键音分析相关推荐

  1. Android 默认按键音开关

    android 默认按键音开关的值存储位置在 frameworks/base/packages/SettingsProvider/res/values/defaults.xml , <!-- D ...

  2. android 系统按键音framework流程源码解析

    android 系统按键音framework源码解析(基于android 9.0) 今天来看下android中按键音的处理,首先看下按键是在那里开启的.然后再看看当按下按键后一个按键音是怎么播放出来的 ...

  3. Android 修改按键音

    一.按键音调用流程 摘要:按键音播放的总体逻辑是先找到系统中按键音的资源,然后调用SoundPool.load让系统加载音频资源,加载成功后在onLoadComplete回调中会返回一个非0的soun ...

  4. android 虚拟按键源码流程分析

    android 虚拟按键流程分析 今天来说说android 的虚拟按键的源码流程.大家都知道,android 系统的状态栏,虚拟按键,下拉菜单,以及通知显示,keyguard 锁屏都是在framewo ...

  5. Android按键音无效

    今天遇到Android系统按键音的问题.在Android TV中,可以通过设置-声音-按键音来设置按键音开或者关.当打开按键音时,在Android TV的各个场景中通过遥控器操作上下左右键的时候都会有 ...

  6. Android按键音的默认值修改流程

    Android 默认按键音开关_南国樗里疾的博客-CSDN博客_android 按键音接口 android setting之Settings.system设置_知不足而奋进的博客-CSDN博客_and ...

  7. Android按键音

    按键音处理流程 View层发起 AudioService 按键音是用户按下后抬起时发出的声音,可在手机系统设置打开或者关闭. 代码分析基于 API 33 View层发起 逻辑在事件分发机制的onTou ...

  8. Android 8.1 系统按键音

    最近接到的任务:实现手机键盘按键音功能 可是网上查到的资料太少,可能是现在没什么带键盘的Android设备了 一开始我以为系统会做好这些东西,是需要找到一个开关,写一个默认值就行,然鹅事情并没有这么简 ...

  9. 带着问题分析Framework层源码(一):按键音声音太小,我们该如何增大?

    作为一名Android开发人员,对源码的阅读是必不可少的.但是Android源码那么庞大,从何开始阅读,如何开始阅读,很多人都会感觉无从下手,今天我来带着问题,去带大家分析一下Android源码,并解 ...

最新文章

  1. Linux命令(30):tar命令-归档工具
  2. 个人博客三|首页后台开发
  3. 远程桌面连接“发生身份验证错误。 无法连接到本地安全机构”解决方法
  4. ListIterator特有的方法
  5. 理解C#值类型与引用类型(收藏)
  6. Linux mail 命令参数
  7. 全球IPv6网络6月6日正式启动
  8. 【STM32】USART相关函数和类型
  9. P3705-[SDOI2017]新生舞会【0/1分数规划,费用流】
  10. 树的计数(prufer序列 或 purfer序列)
  11. 贪心算法(Greedy Algorithm)
  12. idea主题颜色Linux,IntelliJ IDEA更换主题样式分享
  13. docker搭建私有registry
  14. 【已解决】能连接上无线,但打不开网页怎么办?
  15. UIView动画设置
  16. Django中使用MySQL
  17. 信息系统项目管理师(2022年)—— 重点内容:信息化和信息系统(1)
  18. windows server2012 安装网卡驱动
  19. matlab设计理想高斯巴特沃斯低通滤波器_完整二阶有源带通滤波器设计!(下载:教程+原理图+视频+代码)...
  20. 数学建模多元分析实例

热门文章

  1. Dubbo常见面试题
  2. [Deep learning 环境配置之四]YOLO算法之YAD2K配置教程
  3. 跨域:postMessage
  4. 计算机专业跨考会计,这几个专业适合跨考,考研的同学注意,会计学跨考人数最多...
  5. 内推 | 数据开发——江小白
  6. android 无线音乐播放器,玩转Openwrt(二) — 配合Android手机打造无线音乐播放器...
  7. axios、Vue案例、生命周期
  8. 算法7:迪杰斯特拉算法
  9. 海尔简爱s11 Linux,360度影音神器 海尔简爱S11笔记本评测
  10. facebook新闻页ListView优化