使用蓝牙麦克风录制

问题描述

与配对的设备连接后,蓝牙并未占用其麦克风,而是占用了手机的麦克风 下面是我的代码

public abstract class BluetoothHeadsetUtils {
    private Context mContext;

    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothHeadset mBluetoothHeadset;
    private BluetoothDevice mConnectedHeadset;

    private AudioManager mAudioManager;

    private boolean mIsCountDownOn;
    private boolean mIsStarting;
    private boolean mIsOnHeadsetSco;
    private boolean mIsStarted;
    ExminatingHelper exminatingHelper = ExminatingHelper.getInstance();
    private static final String TAG = "BluetoothHeadsetUtils";

    /**
     * Constructor
     *
     * @param context
     */
    public BluetoothHeadsetUtils(Context context) {
        mContext = context;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    }

    /**
     * Call this to start BluetoothHeadsetUtils functionalities.
     *
     * @return The return value of startBluetooth() or startBluetooth11()
     */
    public boolean start() {
        if (!mIsStarted) {
            mIsStarted = true;
            mIsStarted = startBluetooth();
            /*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
                mIsStarted = startBluetooth();
            } else {
                System.out.println("");
               // mIsStarted = startBluetooth11();
            }*/
        }

        return mIsStarted;
    }

    /**
     * Should call this on onResume or onDestroy.
     * Unregister broadcast receivers and stop Sco audio connection
     * and cancel count down.
     */
    public void stop() {
        if (mIsStarted) {
            mIsStarted = false;
            stopBluetooth();
            /*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
                stopBluetooth();
            } else {
                System.out.println("");
               // stopBluetooth11();
            }*/
        }
    }

    /**
     * @return true if audio is connected through headset.
     */
    public boolean isOnHeadsetSco() {
        return mIsOnHeadsetSco;
    }

    public abstract void onHeadsetDisconnected();

    public abstract void onHeadsetConnected();

    public abstract void onScoAudioDisconnected();

    public abstract void onScoAudioConnected();


    @SuppressWarnings("deprecation")
    private boolean startBluetooth() {
        Log.d(TAG,"startBluetooth"); //$NON-NLS-1$

        // Device support bluetooth
        if (mBluetoothAdapter != null) {
            if (mAudioManager.isBluetoothScoAvailableOffCall()) {
                mContext.registerReceiver(mBroadcastReceiver,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));

                mIsCountDownOn = true;
                // mCountDown repeatedly tries to start bluetooth Sco audio connection.
                mCountDown.start();

                // need for audio sco,see mBroadcastReceiver
                mIsStarting = true;

                return true;
            }
        }

        return false;
    }

    private CountDownTimer mCountDown = new CountDownTimer(10000,1000) {

        @SuppressWarnings("synthetic-access")
        @Override
        public void onTick(long millisUntilFinished) {
            // When this call is successful,this count down timer will be canceled.
            mAudioManager.startBluetoothSco();

            Log.d(TAG,"\nonTick start bluetooth Sco"); //$NON-NLS-1$
        }

        @SuppressWarnings("synthetic-access")
        @Override
        public void onFinish() {
            // Calls to startBluetoothSco() in onStick are not successful.
            // Should implement something to inform user of this failure
            mIsCountDownOn = false;
            Log.d(TAG,"\nonFinish fail to connect to headset audio"); //$NON-NLS-1$
        }
    };

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @SuppressWarnings({"deprecation","synthetic-access"})
        @Override
        public void onReceive(Context context,Intent intent) {
            String action = intent.getAction();
            int getRecrodingDevice = exminatingHelper.getRecordingDevice();
            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
                    || deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES
                    || deviceClass == BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER
                    ) {
                        // start bluetooth Sco audio connection.
                        // Calling startBluetoothSco() always returns faIL here,// that why a count down timer is implemented to call
                        // startBluetoothSco() in the onTick.
                        mAudioManager.setMode(AudioManager.MODE_IN_CALL);
                        mIsCountDownOn = true;
                        mCountDown.start();

                        // override this if you want to do other thing when the device is connected.
                        onHeadsetConnected();
                    }
                }

                Log.d(TAG,mConnectedHeadset.getName() + " connected"); //$NON-NLS-1$
            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                Log.d(TAG,"Headset disconnected"); //$NON-NLS-1$

                if (mIsCountDownOn) {
                    mIsCountDownOn = false;
                    mCountDown.cancel();
                }

                // override this if you want to do other thing when the device is disconnected.
                onHeadsetDisconnected();
            } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED) && getRecrodingDevice != 2) {
                int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,AudioManager.SCO_AUDIO_STATE_ERROR);

                if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
                    mIsOnHeadsetSco = true;

                    if (mIsStarting) {
                        // When the device is connected before the application starts,// ACTION_ACL_CONNECTED will not be received,so call onHeadsetConnected here
                        mIsStarting = false;
                        onHeadsetConnected();
                    }

                    if (mIsCountDownOn) {
                        mIsCountDownOn = false;
                        mCountDown.cancel();
                    }

                    // override this if you want to do other thing when Sco audio is connected.
                    onScoAudioConnected();

                    Log.d(TAG,"Sco connected"); //$NON-NLS-1$
                } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
                    Log.d(TAG,"Sco disconnected"); //$NON-NLS-1$

                    // Always receive SCO_AUDIO_STATE_DISCONNECTED on call to startBluetooth()
                    // which at that stage we do not want to do anything. Thus the if condition.
                    if (!mIsStarting) {
                        mIsOnHeadsetSco = false;

                        // Need to call stopBluetoothSco(),otherwise startBluetoothSco()
                        // will not be successful.
                        mAudioManager.stopBluetoothSco();

                        // override this if you want to do other things when Sco audio is disconnected.
                        onScoAudioDisconnected();
                    }
                }
            }
        }
    };

    private void stopBluetooth() {
        Log.d(TAG,"stopBluetooth"); //$NON-NLS-1$

        if (mIsCountDownOn) {
            mIsCountDownOn = false;
            mCountDown.cancel();
        }

        // Need to stop Sco audio connection here when the app
        // change orientation or close with headset still turns on.
        mContext.unregisterReceiver(mBroadcastReceiver);
        mAudioManager.stopBluetoothSco();
        mAudioManager.setMode(AudioManager.MODE_NORMAL);
    }
}
}

以正常方式使用电话时,此方法效果很好。但是,即使插入了头戴式耳机,它也无法检测到蓝牙头戴式耳机的存在,并且仍使用手机自带的麦克风。

解决方法

这是我的一个剪辑,在 SO 上共享了这个蓝牙接收器类,但它对我不起作用(长话短说,不要使用 (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) 因为当我触发时它通过单击按钮,通常有误报)。 尝试按照日志...

然后

onHeadsetConnected();

喜欢

private void onHeadsetConnected(){
       speech.startListening(theIntent);
}

当您“断开连接”时捕获,而不是计算 SCO_AUDIO_STATE_DISCONNECTED,只需捕获 onError、onPartialResult、onResult 并重新检查设备是否仍然存在 ..再听一遍,而不是完成后..

mBluetoothHeadset.getConnectionState(mConnectedHeadset) == BluetoothHeadset.STATE_CONNECTED

我这样做是为了确保我连接到了正确的耳机(带有麦克风!)

if (mBluetoothHeadset.getConnectedDevices().size()>0) {
        mConnectedHeadset = null;
        for (int i=0;i<mBluetoothHeadset.getConnectedDevices().size(); i ++){
            int deviceClass = mBluetoothHeadset.getConnectedDevices().get(i).getBluetoothClass().getDeviceClass();
            switch (deviceClass){
                case BluetoothClass.Device.Major.PHONE:
                case BluetoothClass.Device.Major.AUDIO_VIDEO:
                case BluetoothClass.Device.AUDIO_VIDEO_MICROPHONE:
                case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
                    mAudioManager.setMode(AudioManager.MODE_IN_CALL);
                    mConnectedHeadset = mBluetoothHeadset.getConnectedDevices().get(i);
                    registerReceiver(mHeadsetBroadcastReceiver,new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
                    return;
            }
        }
    }

希望这能帮助你/或某人..因为我试图实现那个类,太麻烦了,所以我只是把它的一部分放到我的活动中并使用我需要的东西(绝对不需要支持老安卓)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...