You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TextToSpeech.speak()时接收蓝牙耳机播放/暂停事件?

解决方案:TTS播放期间捕获蓝牙耳机MediaButton事件(无需静音音频)

针对TTS播放时无法通过常规MediaSession捕获蓝牙耳机播放/暂停按键的问题,以下是两种无需依赖静音音频的替代方案:

方案1:通过AudioManager直接注册MediaButton监听

直接使用系统AudioManager注册自定义接收器,绑定音频生命周期与按键监听:

步骤1:实现自定义MediaButton接收器

public class TTSMediaButtonReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
            KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if (event != null && event.getAction() == KeyEvent.ACTION_DOWN) {
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                        Log.d("TTS_Button", "蓝牙耳机播放/暂停按键触发");
                        break;
                }
            }
        }
    }
}

步骤2:在Activity中绑定监听与TTS生命周期

private AudioManager audioManager;
private ComponentName buttonReceiverComponent;
private TextToSpeech tts;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    buttonReceiverComponent = new ComponentName(this, TTSMediaButtonReceiver.class);
    
    // 初始化TTS并设置进度监听
    tts = new TextToSpeech(this, status -> {
        if (status == TextToSpeech.SUCCESS) {
            tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                @Override
                public void onStart(String utteranceId) {
                    // TTS开始前请求音频焦点并注册监听
                    requestAudioFocusAndRegisterReceiver();
                }

                @Override
                public void onDone(String utteranceId) {
                    // TTS结束后释放资源
                    releaseAudioFocusAndUnregister();
                }

                @Override
                public void onError(String utteranceId) {
                    releaseAudioFocusAndUnregister();
                }
            });
        }
    });
}

// 请求音频焦点并注册按键监听
private void requestAudioFocusAndRegisterReceiver() {
    AudioAttributes ttsAttrs = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY)
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            .build();
    AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
            .setAudioAttributes(ttsAttrs)
            .setOnAudioFocusChangeListener(focusChange -> {})
            .build();
    
    if (audioManager.requestAudioFocus(focusRequest) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        audioManager.registerMediaButtonEventReceiver(buttonReceiverComponent);
    }
}

// 释放音频焦点并注销监听
private void releaseAudioFocusAndUnregister() {
    audioManager.abandonAudioFocus(focusChange -> {});
    audioManager.unregisterMediaButtonEventReceiver(buttonReceiverComponent);
}

// 启动TTS的方法
public void startTTS(String content) {
    HashMap<String, String> params = new HashMap<>();
    params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "tts_session");
    tts.speak(content, TextToSpeech.QUEUE_FLUSH, params);
}

步骤3:在Manifest中注册接收器

<receiver android:name=".TTSMediaButtonReceiver" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

方案2:强制绑定MediaSession与TTS播放状态

通过手动控制MediaSessionCompat的活跃状态和播放状态,抢占MediaButton事件的分发权:

代码实现

private MediaSessionCompat mediaSession;
private AudioManager audioManager;
private TextToSpeech tts;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    
    // 初始化MediaSession
    mediaSession = new MediaSessionCompat(this, "TTS_Media_Session");
    mediaSession.setCallback(new MediaSessionCompat.Callback() {
        @Override
        public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
            KeyEvent event = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if (event != null && event.getAction() == KeyEvent.ACTION_DOWN) {
                if (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
                    Log.d("TTS_MediaSession", "蓝牙耳机播放/暂停按键触发");
                    return true; // 消费事件,避免传递给其他应用
                }
            }
            return super.onMediaButtonEvent(mediaButtonIntent);
        }
    });
    
    // 初始化TTS
    tts = new TextToSpeech(this, status -> {
        if (status == TextToSpeech.SUCCESS) {
            tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                @Override
                public void onStart(String utteranceId) {
                    activateMediaSession();
                }

                @Override
                public void onDone(String utteranceId) {
                    deactivateMediaSession();
                }

                @Override
                public void onError(String utteranceId) {
                    deactivateMediaSession();
                }
            });
        }
    });
}

// 激活MediaSession并设置播放状态
private void activateMediaSession() {
    // 请求音频焦点
    AudioAttributes ttsAttrs = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY)
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            .build();
    AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
            .setAudioAttributes(ttsAttrs)
            .build();
    
    if (audioManager.requestAudioFocus(focusRequest) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        mediaSession.setActive(true);
        PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder()
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 1.0f)
                .build();
        mediaSession.setPlaybackState(playbackState);
    }
}

// 停用MediaSession
private void deactivateMediaSession() {
    mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
            .setState(PlaybackStateCompat.STATE_STOPPED, 0, 1.0f)
            .build());
    mediaSession.setActive(false);
    audioManager.abandonAudioFocus(focusChange -> {});
}

// 启动TTS
public void startTTS(String content) {
    HashMap<String, String> params = new HashMap<>();
    params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "tts_session");
    tts.speak(content, TextToSpeech.QUEUE_FLUSH, params);
}

注意事项

  • 无需额外在Manifest中注册MediaButtonReceiver,MediaSessionCompat会自动处理事件绑定
  • 确保在TTS结束后及时停用MediaSession,避免影响其他应用的按键事件

内容的提问来源于stack exchange,提问作者sfinja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:52:02