如何在TextToSpeech.speak()时接收蓝牙耳机播放/暂停事件?
针对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
相关产品推荐
相关产品推荐

