【问题标题】:TextToSpeech on bluetooth SCO蓝牙 SCO 上的 TextToSpeech
【发布时间】:2018-04-28 15:50:36
【问题描述】:

我正在尝试将我的 TTS 输出路由到外部蓝牙 SCO 设备(与本地扬声器和麦克风一起工作正常),但它无法播放。

我正在为 AudioManager 设置路由如下 -

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);

用这种方法播放话语-

private void say(String text, String utteranceId) {
    Log.d(TAG, "Saying: " + text);
    final Bundle ttsParams = new Bundle();
    ttsParams.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_VOICE_CALL);
    mTextToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, ttsParams,  utteranceId);
}

扬声器没有声音。如果我不将BluetoothScoOn 设置为 true,它可以与内置扬声器一起正常工作。

【问题讨论】:

    标签: android google-text-to-speech


    【解决方案1】:

    使用这个类:

    public abstract class BluetoothHeadsetUtils {
        private AudioManager mAudioManager;
        private BluetoothAdapter mBluetoothAdapter;
        private BluetoothHeadset mBluetoothHeadset;
        private BluetoothDevice mConnectedHeadset;
        private Context mContext;
        private CountDownTimer mCountDown;
        private BroadcastReceiver mHeadsetBroadcastReceiver;
        private BluetoothProfile.ServiceListener mHeadsetProfileListener;
        private boolean mIsCountDownOn;
        private boolean mIsOnHeadsetSco;
        private boolean mIsStarted;
        private boolean receiverRegistered;
    
        public BluetoothHeadsetUtils(final Context context) {
    
            mHeadsetBroadcastReceiver = new BroadcastReceiver() {
                public void onReceive(final Context context, final Intent intent) {
                    final String action = intent.getAction();
                    if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                        final int intExtra = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset
                                .STATE_DISCONNECTED);
                        if (intExtra == BluetoothHeadset.STATE_CONNECTED) {
                            BluetoothHeadsetUtils.this.mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice
                                    .EXTRA_DEVICE);
                            BluetoothHeadsetUtils.this.mIsCountDownOn = true;
                            BluetoothHeadsetUtils.this.mCountDown.start();
                            BluetoothHeadsetUtils.this.onHeadsetConnected();
                        } else if (intExtra == BluetoothHeadset.STATE_DISCONNECTED) {
                            if (BluetoothHeadsetUtils.this.mIsCountDownOn) {
                                BluetoothHeadsetUtils.this.mIsCountDownOn = false;
                                BluetoothHeadsetUtils.this.mCountDown.cancel();
                            }
                            BluetoothHeadsetUtils.this.mConnectedHeadset = null;
                            BluetoothHeadsetUtils.this.onHeadsetDisconnected();
                        }
                    } else {
                        final int intExtra2 = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset
                                .STATE_AUDIO_DISCONNECTED);
                        if (intExtra2 == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
                            BluetoothHeadsetUtils.this.mIsOnHeadsetSco = true;
                            if (BluetoothHeadsetUtils.this.mIsCountDownOn) {
                                BluetoothHeadsetUtils.this.mIsCountDownOn = false;
                                BluetoothHeadsetUtils.this.mCountDown.cancel();
                            }
                            BluetoothHeadsetUtils.this.onScoAudioConnected();
                            return;
                        }
                        if (intExtra2 == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                            BluetoothHeadsetUtils.this.mIsOnHeadsetSco = false;
                            BluetoothHeadsetUtils.this.mBluetoothHeadset.stopVoiceRecognition(BluetoothHeadsetUtils.this
                                    .mConnectedHeadset);
                            BluetoothHeadsetUtils.this.onScoAudioDisconnected();
                        }
                    }
                }
            };
            mHeadsetProfileListener = new BluetoothProfile.ServiceListener() {
                public void onServiceConnected(final int n, final BluetoothProfile bluetoothProfile) {
                    BluetoothHeadsetUtils.this.mBluetoothHeadset = (BluetoothHeadset) bluetoothProfile;
                    final List<BluetoothDevice> connectedDevices = BluetoothHeadsetUtils.this.mBluetoothHeadset
                            .getConnectedDevices();
                    if (connectedDevices.size() > 0) {
                        BluetoothHeadsetUtils.this.mConnectedHeadset = connectedDevices.get(0);
                        BluetoothHeadsetUtils.this.onHeadsetConnected();
                        BluetoothHeadsetUtils.this.mIsCountDownOn = true;
                        BluetoothHeadsetUtils.this.mCountDown.start();
                    } else {
                        BluetoothHeadsetUtils.this.noHeadsetConnected();
                    }
                    IntentFilter filter = new IntentFilter();
                    filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
                    filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
                    BluetoothHeadsetUtils.this.mContext.registerReceiver(BluetoothHeadsetUtils.this
                            .mHeadsetBroadcastReceiver, filter);
                    receiverRegistered = true;
                }
    
                public void onServiceDisconnected(final int n) {
                    BluetoothHeadsetUtils.this.stop();
                }
            };
    
            mCountDown = new CountDownTimer(10000L, 1000L) {
                public void onFinish() {
                    BluetoothHeadsetUtils.this.mIsCountDownOn = false;
                    onTimeout();
                }
    
                public void onTick(final long n) {
                    BluetoothHeadsetUtils.this.mBluetoothHeadset.startVoiceRecognition(BluetoothHeadsetUtils.this
                            .mConnectedHeadset);
                }
            };
            mContext = context;
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            mAudioManager = (AudioManager) this.mContext.getSystemService(Context.AUDIO_SERVICE);
        }
    
        private boolean startBluetooth() {
            return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() && mAudioManager
                    .isBluetoothScoAvailableOffCall() &&
                    mBluetoothAdapter.getProfileProxy(mContext, mHeadsetProfileListener, BluetoothProfile.HEADSET);
        }
    
        public boolean isOnHeadsetSco() {
            return mIsOnHeadsetSco;
        }
    
        protected void onTimeout() {
        }
    
        protected void noHeadsetConnected() {
        }
    
        protected void onHeadsetConnected() {
        }
    
        protected void onHeadsetDisconnected() {
        }
    
        protected void onScoAudioConnected() {
        }
    
        protected void onScoAudioDisconnected() {
        }
    
        @UiThread
        public boolean start() {
            if (!mIsStarted) {
                mIsStarted = true;
                mIsStarted = startBluetooth();
            }
            return mIsStarted;
        }
    
        @UiThread
        public void stop() {
            if (mIsStarted) {
                mIsStarted = false;
                stopBluetooth();
            }
        }
    
        private void stopBluetooth() {
            if (mIsCountDownOn) {
                mIsCountDownOn = false;
                mCountDown.cancel();
            }
            try {
                if (receiverRegistered) {
                    mContext.unregisterReceiver(mHeadsetBroadcastReceiver);
                }
            } catch (IllegalArgumentException ignored) {
            } finally {
                receiverRegistered = false;
            }
            if (mBluetoothHeadset != null) {
                mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
                mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
                mBluetoothHeadset = null;
            }
            mIsOnHeadsetSco = false;
        }
    }
    

    在 onScoAudioConnected 回调中使用你的 say 方法。

    【讨论】:

    • onScoAudioConnected 永远不会被调用。函数 D/BluetoothHeadset: startVoiceRecognition() 在日志中不断被调用
    • 确实有倒计时。 10 滴答声。
    • 即使在 10 个滴答声之后.. onScoAudioConnected 也不会被调用
    • 在这种情况下 onTimeout 被调用,使用该设备你不走运
    • 也许它使用了不同的 API,我每天都使用这段代码,它按预期工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 2011-11-04
    • 2022-09-28
    • 2017-02-23
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    相关资源
    最近更新 更多