Android 12 - 重复播放按键音(上下左右、OK)

问题描述:

自定义按键音播放,在Launcher上按 上下左右和OK 按键发现会播放两次按键提示音,其他的都是正常的。

首先找一下播放的是哪个文件,在下面的README中有定义

frameworks/base/data/sounds/README.txt


Touch sounds
------------

effects/Effect_Tick.ogg
  old, referenced by AudioPackage[2345].mk OriginalAudio.mk

effects/ogg/Effect_Tick.ogg
  new, referenced by AudioPackage[6789].mk AudioPackage7alt.mk AudioPackage10.mk

effects/ogg/Effect_Tick_48k.ogg
  oggdec -o temp.wav ogg/Effect_Tick.ogg
  sox temp.wav -r 48000 temp48k.wav
  oggenc -b 80 -o ogg/Effect_Tick_48k.ogg temp48k.wav

effects/wav/Effect_Tick.wav
  does not appear to be related to the other files in any obvious way

也就是触摸和点击事件都是播放的 Effect_Tick 这个音频文件。直接检索这个在哪里调用。

 xml文件是为了替换默认声音资源,并且可以看到很多需要的如上下左右都在这里定义了,并且播放的都是Effect_Tick。

framework/base/core/res/res/xml/audio_assets.xml

<!-- Mapping of UI sound effects to audio assets under /system/media/audio/ui.
     Modify this file to override default sound assets.
-->

<audio_assets version="1.0">
    <asset id="FX_KEY_CLICK" file="Effect_Tick.ogg"/>
    <asset id="FX_FOCUS_NAVIGATION_UP" file="Effect_Tick.ogg"/>
    <asset id="FX_FOCUS_NAVIGATION_DOWN" file="Effect_Tick.ogg"/>
    <asset id="FX_FOCUS_NAVIGATION_LEFT" file="Effect_Tick.ogg"/>
    <asset id="FX_FOCUS_NAVIGATION_RIGHT" file="Effect_Tick.ogg"/>
    <asset id="FX_KEYPRESS_STANDARD" file="KeypressStandard.ogg"/>
    <asset id="FX_KEYPRESS_SPACEBAR" file="KeypressSpacebar.ogg"/>
    <asset id="FX_KEYPRESS_DELETE" file="KeypressDelete.ogg"/>
    <asset id="FX_KEYPRESS_RETURN" file="KeypressReturn.ogg"/>
    <asset id="FX_KEYPRESS_INVALID" file="KeypressInvalid.ogg"/>
    <asset id="FX_BACK

再根据 SoundEffectsHelper.java 找到实现播放的方法 void playSoundEffect(int effect, int volume)

其实是在 AudioService.java 定义的 

    /** @see AudioManager#playSoundEffect(int) */
    public void playSoundEffect(int effectType) {
        playSoundEffectVolume(effectType, -1.0f);
    }

    /** @see AudioManager#playSoundEffect(int, float) */
    public void playSoundEffectVolume(int effectType, float volume) {
        // do not try to play the sound effect if the system stream is muted
        if (isStreamMute(STREAM_SYSTEM)) {
            return;
        }

        if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
            Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
            return;
        }

        sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
                effectType, (int) (volume * 1000), null, 0);
    }

 根据注释,可以确定是通过 AudioManager 调用的。目前已经确定了播放按键提示音的调用方法。再次检索。

是在这里实现的播放

    @Override
    public void playSoundEffect(@SoundEffectConstants.SoundEffect int effectId) {
        checkThread();

        try {
            final AudioManager audioManager = getAudioManager();

            if (mFastScrollSoundEffectsEnabled
                    && SoundEffectConstants.isNavigationRepeat(effectId)) {
                audioManager.playSoundEffect(
                        SoundEffectConstants.nextNavigationRepeatSoundEffectId());
                return;
            }

            if (true) {
                    Log.e(TAG, "lichang playSoundEffect avoid click tone");
                    return;
            }

            switch (effectId) {
                case SoundEffectConstants.CLICK:
                    audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
                    return;
                case SoundEffectConstants.NAVIGATION_DOWN:
                case SoundEffectConstants.NAVIGATION_REPEAT_DOWN:
                    audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
                    return;
                case SoundEffectConstants.NAVIGATION_LEFT:
                case SoundEffectConstants.NAVIGATION_REPEAT_LEFT:
                    audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
                    return;
                case SoundEffectConstants.NAVIGATION_RIGHT:
                case SoundEffectConstants.NAVIGATION_REPEAT_RIGHT:
                    audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
                    return;
                case SoundEffectConstants.NAVIGATION_UP:
                case SoundEffectConstants.NAVIGATION_REPEAT_UP:
                    audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
                    return;
                default:
                    throw new IllegalArgumentException("unknown effect id " + effectId +
                            " not defined in " + SoundEffectConstants.class.getCanonicalName());
            }
        } catch (IllegalStateException e) {
            // Exception thrown by getAudioManager() when mView is null
            Log.e(mTag, "FATAL EXCEPTION when attempting to play sound effect: " + e);
            e.printStackTrace();
        }
    }

直接屏蔽掉即可。或者其实从 framework/base/core/res/res/xml/audio_assets.xml 也可以看到有方向键等音频资源,可以通过检索直接定位到位置。

只在framework下检索是因为对日志进行分析,过滤Audiotrack

11:42:03.414 AudioTrack                I  start mClientAttributionSource.uid:1000 mClientAttributionSource.pid:1013  mSessionId:129 app name:system_server 
11:42:03.433 AudioTrack                I  start mClientAttributionSource.uid:1000 mClientAttributionSource.pid:1013  mSessionId:145 app name:system_server 
11:42:03.525 AudioTrack                I  stop mClientAttributionSource.uid:1000 mClientAttributionSource.pid:1013  mSessionId:129 app name:system_server 
11:42:03.553 AudioTrack                I  stop mClientAttributionSource.uid:1000 mClientAttributionSource.pid:1013  mSessionId:145 app name:system_server 
可以看到这两次声音播放都是 system_server 这个进程调用的。

补充,由于是自定义按键音播放的,因此需要实现原生的按键音开关功能,增加条件

            if (System.getInt(context.getContentResolver(), System.SOUND_EFFECTS_ENABLED, 1) == 1)
                    playEffect(context);

并且,由于屏蔽了所有点击事件,因此,目前点击屏幕时没有提示,我的方案是在view触摸事件监听中增加提示音播放,如下:

frameworks/base/core/java/android/view/View.java

    /**
     * Pass the touch screen motion event down to the target view, or this
     * view if it is the target.
     *
     * @param event The motion event to be dispatched.
     * @return True if the event was handled by the view, false otherwise.
     */
    public boolean dispatchTouchEvent(MotionEvent event) {
	// lichang 触摸屏幕后播放触摸音
	/*@start*/
	if (event.getAction() == MotionEvent.ACTION_UP && android.provider.Settings.System.getInt(getContext().getContentResolver(), android.provider.Settings.System.SOUND_EFFECTS_ENABLED, 1) == 1) {
            AudioManager audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);;
            audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
	}
	/*@end*/
        // If the event should be handled by accessibility focus first.
        if (event.isTargetAccessibilityFocus()) {
            // We don't have focus or no virtual descendant has it, do not handle the event.
            if (!isAccessibilityFocusedViewOrHost()) {
                return false;
            }
            // We have focus and got the event, then use normal event dispatch.
            event.setTargetAccessibilityFocus(false);
        }
        boolean result = false;

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值