通过蓝牙进行文字转语音

时间:2013-08-20 16:17:08

标签: android text-to-speech android-bluetooth

我正在使用Text-To-Speech设计一个应用程序,它可以运行。现在我想使用蓝牙耳机(不是AD2P)来接收音频。阅读有关startBluetoothScoOn的Android文档,我看到了:

请注意,电话应用程序始终优先使用SCO连接进行电话连接。如果在电话通话时调用此方法,则会忽略此方法。同样,如果在应用程序使用SCO连接时收到或发送了一个呼叫,则该应用程序的连接将丢失,并且在呼叫结束时不会自动返回。

现在我的问题是:

  1. 呼叫结束时,是否需要侦听电话状态才能重新呼叫startBluetoothScoOn?如果有,怎么样?我没有找到任何例子;
  2. 我是否需要收听连接/断开的耳机?如果是,怎么样?
  3. 我认为当通话结束或耳机关闭时,系统会发出SCO_AUDIO_STATE_DISCONNECTED,对吗?

    编辑:我发布了我正在使用的代码:

    public class BluetoothHeadSetManager implements
        BluetoothProfile.ServiceListener {
    BluetoothManager manager;
    BluetoothHeadset bluetoothHeadset;
    Context context;
    HeadSetBroadcastReceiver recv;
    
    public BluetoothHeadSetManager(Context cont, BluetoothManager manager) {
        this.manager = manager;
        this.context = cont;
        recv = null;
    }
    
    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
        // mBluetoothHeadset is just a headset profile,
        // it does not represent a headset device.
        bluetoothHeadset = (BluetoothHeadset) proxy;
    
        List<BluetoothDevice> devices = bluetoothHeadset.getConnectedDevices();
        if (devices.size() > 0)
            manager.onHeadSetConnected();
    
        // During the active life time of the app, a user may turn on and off
        // the headset.
        // So register for broadcast of connection states.
        if (recv == null) {
            recv = new HeadSetBroadcastReceiver();
            context.registerReceiver(recv, new IntentFilter(
                    BluetoothDevice.ACTION_ACL_CONNECTED));
            context.registerReceiver(recv, new IntentFilter(
                    BluetoothDevice.ACTION_ACL_DISCONNECTED));
        }
    }
    
    public void close() {
        if (recv != null)
            context.unregisterReceiver(recv);
        if (bluetoothHeadset != null)
            BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
                    BluetoothProfile.HEADSET, bluetoothHeadset);
    }
    
    @Override
    public void onServiceDisconnected(int arg0) {
        Logger.getInstance().writeLog("onServiceDisconnected called");
        if (recv != null)
            context.unregisterReceiver(recv);
        manager.onHeadSetDisconnected();
    }
    
    private class HeadSetBroadcastReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice mConnectedHeadset;
    
            if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
                mConnectedHeadset = intent
                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                BluetoothClass bluetoothClass = mConnectedHeadset
                        .getBluetoothClass();
                if (bluetoothClass != null) {
                    // Check if device is a headset. Besides the 2 below, are
                    // there other
                    // device classes also qualified as headset?
                    int deviceClass = bluetoothClass.getDeviceClass();
                    if (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE
                            || deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) {
                        // override this if you want to do other thing when the
                        // device is connected.
                        manager.onHeadSetConnected();
                    }
                }
            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                manager.onHeadSetDisconnected();
            }
        }
    }
    

    Sco接收器:

    public class BluetoothScoReceiver extends BroadcastReceiver {
    BluetoothManager manager;
    
    public BluetoothScoReceiver(BluetoothManager manager) {
        this.manager = manager;
    }
    
    @Override
    public void onReceive(Context arg0, Intent intent) {
        Bundle extras = intent.getExtras();
        if (extras == null)
            return;
        int state = extras.getInt(AudioManager.EXTRA_SCO_AUDIO_STATE);
        if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED)
            manager.onScoConnected();
        else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED)
            manager.onScoDisconnected();
    }
    

    主:

    @Override
    public void onScoConnected() {
        this.headsetReady = true;
        requestState = CONNECTED;
    }
    
    @Override
    public void onScoDisconnected() {
        this.headsetReady = false;
        if (requestState == TRY_CONNECTION && headsetConnected)
            this.onHeadSetConnected(); //try again
    }
    
    @Override
    public void onHeadSetConnected() {
        headsetConnected = true;
        if (requestState == TRY_CONNECTION) {
            requestState = TRY_CONNECTION;
            audioMng.setMode(AudioManager.MODE_NORMAL);
            audioMng.stopBluetoothSco();
            audioMng.setMode(AudioManager.MODE_IN_CALL);
            audioMng.startBluetoothSco();
        } else {
            requestState = TRY_CONNECTION;
            audioMng.setMode(AudioManager.MODE_IN_CALL);
            audioMng.startBluetoothSco();
        }
    }
    
    @Override
    public void onHeadSetDisconnected() {
        audioMng.setMode(AudioManager.MODE_NORMAL);
        if (requestState != NOT_CONNECTED_IDLE) {
            audioMng.stopBluetoothSco();
            audioMng.setBluetoothScoOn(false);
            requestState = NOT_CONNECTED_IDLE;
        }
        headsetConnected = false;
    }
    
    @SuppressLint("InlinedApi")
    @SuppressWarnings("deprecation")
    @Override
    public void startBluetooth() {
        Intent currentScoState;
        if (audioMng.isBluetoothScoAvailableOffCall()) {
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
            if (adapter == null)
                return;
            blueInit = adapter.getProfileProxy(this, headsetMng,
                    BluetoothProfile.HEADSET);
            if (blueInit) {
                scoListner = new BluetoothScoReceiver(this);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
                    currentScoState = this
                            .registerReceiver(
                                    scoListner,
                                    new IntentFilter(
                                            AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
                else
                    currentScoState = this
                            .registerReceiver(
                                    scoListner,
                                    new IntentFilter(
                                            AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
                Bundle extras = currentScoState.getExtras();
                if (extras == null)
                    return;
                if (extras
                        .getInt(AudioManager.EXTRA_SCO_AUDIO_STATE) == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
                    this.headsetReady = true;
                    requestState = CONNECTED;
                } else {
                    this.headsetReady = false;
                    requestState = NOT_CONNECTED_IDLE;
                }
            }
        }
    }
    
    @Override
    public void stopBluetooth() {
        this.onHeadSetDisconnected();
        if (blueInit) {
            headsetMng.close();
            this.unregisterReceiver(scoListner);
        }
    }
    

1 个答案:

答案 0 :(得分:0)

  1. 您不一定要听电话状态,当通话结束时(CALL_STATE_IDLE)您将收到SCO_AUDIO_STATE_DISCONNECTED。
  2. 如果您不听耳机连接,您如何知道何时连接音频?对于蓝牙耳机实现,您可以查看Using the Android RecognizerIntent with a bluetooth headset