首页 文章

使用Android识别器内置蓝牙耳机

提问于
浏览
23

我使用以下代码在Android中启动语音识别:

PackageManager pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);

if (activities.size() == 0) {
    displayWarning("This device does not support speech recognition");
    return;
}

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);

startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);

这很好用 . 但是,它似乎不接受来自使用“电话音频”配置文件配对和连接的蓝牙耳机的语音输入 .

我可以使用名为SoundAbout的应用程序强制"Media Audio"到"Bluetooth (mono) (SCO)" . 有了这个应用程序集,我的语音识别现在可以从我的耳机输入语音输入 .

如何使用RecognizerIntent并从蓝牙耳机获取语音输入?

我在API级别16中看到有一个新的意图动作ACTION_VOICE_SEARCH_HANDS_FREE . 这对我来说太新了,但这会解决我的问题吗?

我是否必须使用setBluetoothScoOn()或startBluetoothSco()在AudioManager中进行捣乱(就像我假设SoundAbout正在做的那样)来路由音频输入?

5 回答

  • 0

    显示许可

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    

    ActivityService 中创建内部类 BluetoothHelper extends BluetoothHeadSetUtils . 声明一个类成员 mBluetoothHelper 并在 onCreate() 中实例化它

    BluetoothHelper mBluetoothHelper;
    
    @Override
    public void onCreate()
    { 
         mBluetoothHelper = new BluetoothHelper(this);
    }  
    
    @Override
    onResume()
    { 
        mBluetoothHelper.start();
    }
    
    @Override
    onPause()
    {
        mBluetoothHelper.stop();
    }
    
    // inner class
    // BluetoothHeadsetUtils is an abstract class that has
    // 4 abstracts methods that need to be implemented.
    private class BluetoothHelper extends BluetoothHeadSetUtils
    {
        public BluetoothHelper(Context context)
        {
            super(context);
        }
    
        @Override
        public void onScoAudioDisconnected()
        {
            // Cancel speech recognizer if desired
        }
    
        @Override
        public void onScoAudioConnected()
        {           
            // Should start speech recognition here if not already started  
        }
    
        @Override
        public void onHeadsetDisconnected()
        {
    
        }
    
        @Override
        public void onHeadsetConnected()
        {
    
        }
    }
    

    要将蓝牙耳机与文本转语音一起使用,您需要在调用speak之前将AudioManager设置为STREAM_VOICE_CALL . 或者使用下面的代码

    protected void speak(String text)
    {
    
        HashMap<String, String> myHashRender = new HashMap<String, String>();
    
        if (mBluetoothHelper.isOnHeadsetSco())
        {
            myHashRender.put(TextToSpeech.Engine.KEY_PARAM_STREAM, 
                String.valueOf(AudioManager.STREAM_VOICE_CALL));
        }
        mTts.speak(text, TextToSpeech.QUEUE_FLUSH, myHashRender);
    }
    

    将BluetoothHeadsetUtils类复制到您的项目中 .

    import java.util.List;
    
    import android.annotation.SuppressLint;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothClass;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothHeadset;
    import android.bluetooth.BluetoothProfile;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.media.AudioManager;
    import android.os.Build;
    import android.os.CountDownTimer;
    import android.util.Log;
    
    /**
     * This is a utility to detect bluetooth headset connection and establish audio connection
     * for android API >= 8. This includes a work around for  API < 11 to detect already connected headset
     * before the application starts. This work around would only fails if Sco audio
     * connection is accepted but the connected device is not a headset.
     * 
     * @author Hoan Nguyen
     *
     */
    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;
    
        private static final String TAG = "BluetoothHeadsetUtils"; //$NON-NLS-1$
    
        /**
         * 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;
    
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
                {
                    mIsStarted = startBluetooth();
                }
                else
                {
                    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;
    
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
                {
                    stopBluetooth();
                }
                else
                {
                    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();
    
        /**
         * Register for bluetooth headset connection states and Sco audio states.
         * Try to connect to bluetooth headset audio by calling startBluetoothSco(). 
         * This is a work around for API < 11 to detect if a headset is connected before 
         * the application starts.
         * 
         * The official documentation for startBluetoothSco() states
         * 
         * "This method can be used by applications wanting to send and received audio to/from 
         *  a bluetooth SCO headset while the phone is not in call."
         *  
         * Does this mean that startBluetoothSco() would fail if the connected bluetooth device
         * is not a headset?
         * 
         * Thus if a call to startBluetoothSco() is successful, i.e mBroadcastReceiver will receive
         * an ACTION_SCO_AUDIO_STATE_CHANGED with intent extra SCO_AUDIO_STATE_CONNECTED, then
         * we assume that a headset is connected.
         * 
         * @return  false if device does not support bluetooth or current platform does not supports
         *                use of SCO for off call.
         */
        @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(BluetoothDevice.ACTION_ACL_CONNECTED));
                    mContext.registerReceiver(mBroadcastReceiver, 
                                            new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
                    mContext.registerReceiver(mBroadcastReceiver, 
                                            new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
    
                    // Need to set audio mode to MODE_IN_CALL for call to startBluetoothSco() to succeed.
                    mAudioManager.setMode(AudioManager.MODE_IN_CALL);
    
                    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;
        }
    
        /**
         * Register a headset profile listener
         * @return false    if device does not support bluetooth or current platform does not supports
         *                  use of SCO for off call or error in getting profile proxy.
         */
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        private boolean startBluetooth11()
        {
            Log.d(TAG, "startBluetooth11"); //$NON-NLS-1$
    
            // Device support bluetooth
            if (mBluetoothAdapter != null)
            {
                if (mAudioManager.isBluetoothScoAvailableOffCall())
                {
                    // All the detection and audio connection are done in mHeadsetProfileListener
                    if (mBluetoothAdapter.getProfileProxy(mContext, 
                                                        mHeadsetProfileListener, 
                                                        BluetoothProfile.HEADSET))
                    {
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        /**
         * API < 11
         * Unregister broadcast receivers and stop Sco audio connection
         * and cancel count down.
         */
        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);
        }
    
        /**
         * API >= 11
         * Unregister broadcast receivers and stop Sco audio connection
         * and cancel count down.
         */
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        protected void stopBluetooth11()
        {
            Log.d(TAG, "stopBluetooth11"); //$NON-NLS-1$
    
            if (mIsCountDownOn)
            {
                mIsCountDownOn = false;
                mCountDown11.cancel();
            }
    
            if (mBluetoothHeadset != null)
            {
                // Need to call stopVoiceRecognition here when the app
                // change orientation or close with headset still turns on.
                mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
                mContext.unregisterReceiver(mHeadsetBroadcastReceiver);
                mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
                mBluetoothHeadset = null;
            }
        }
    
        /**
         * Broadcast receiver for API < 11
         * Handle headset and Sco audio connection states.
         */
        private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()
        {
            @SuppressWarnings({"deprecation", "synthetic-access"})
            @Override
            public void onReceive(Context context, Intent intent)
            {
                String action = intent.getAction();
    
                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)
                        {
                            // 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();
                    }
    
                    mAudioManager.setMode(AudioManager.MODE_NORMAL);
    
                    // override this if you want to do other thing when the device is disconnected.
                    onHeadsetDisconnected();
                }
                else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED))
                {
                    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 thing when Sco audio is disconnected.
                            onScoAudioDisconnected();
                        } 
                    }
                }
            }
        };
    
        /**
         * API < 11
         * Try to connect to audio headset in onTick.
         */
        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;
                mAudioManager.setMode(AudioManager.MODE_NORMAL);
    
                Log.d(TAG, "\nonFinish fail to connect to headset audio"); //$NON-NLS-1$
            }
        };
    
        /**
         * API >= 11
         * Check for already connected headset and if so start audio connection.
         * Register for broadcast of headset and Sco audio connection states.
         */
        private BluetoothProfile.ServiceListener mHeadsetProfileListener = new BluetoothProfile.ServiceListener()
        {
    
            /**
             * This method is never called, even when we closeProfileProxy on onPause.
             * When or will it ever be called???
             */
            @Override
            public void onServiceDisconnected(int profile)
            {
                Log.d(TAG, "Profile listener onServiceDisconnected"); //$NON-NLS-1$
                stopBluetooth11();
            }
    
            @SuppressWarnings("synthetic-access")
            @TargetApi(Build.VERSION_CODES.HONEYCOMB)
            @Override
            public void onServiceConnected(int profile, BluetoothProfile proxy)
            {
                Log.d(TAG, "Profile listener onServiceConnected"); //$NON-NLS-1$
    
                // mBluetoothHeadset is just a headset profile, 
                // it does not represent a headset device.
                mBluetoothHeadset = (BluetoothHeadset) proxy;
    
                // If a headset is connected before this application starts,
                // ACTION_CONNECTION_STATE_CHANGED will not be broadcast. 
                // So we need to check for already connected headset.
                List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
                if (devices.size() > 0)
                {
                    // Only one headset can be connected at a time, 
                    // so the connected headset is at index 0.
                    mConnectedHeadset = devices.get(0);
    
                    onHeadsetConnected();
    
                    // Should not need count down timer, but just in case.
                    // See comment below in mHeadsetBroadcastReceiver onReceive()
                    mIsCountDownOn = true;
                    mCountDown11.start();
    
                    Log.d(TAG, "Start count down"); //$NON-NLS-1$
                }
    
                // During the active life time of the app, a user may turn on and off the headset.
                // So register for broadcast of connection states.
                mContext.registerReceiver(mHeadsetBroadcastReceiver, 
                                new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));
                // Calling startVoiceRecognition does not result in immediate audio connection.
                // So register for broadcast of audio connection states. This broadcast will
                // only be sent if startVoiceRecognition returns true.
                mContext.registerReceiver(mHeadsetBroadcastReceiver, 
                                new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
            }
        };
    
        /**
         *  API >= 11
         *  Handle headset and Sco audio connection states.
         */
        private BroadcastReceiver mHeadsetBroadcastReceiver = new BroadcastReceiver()
        {
    
            @SuppressWarnings("synthetic-access")
            @TargetApi(Build.VERSION_CODES.HONEYCOMB)
            @Override
            public void onReceive(Context context, Intent intent)
            {
                String action = intent.getAction();
                int state;
                if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED))
                {
                    state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, 
                                                BluetoothHeadset.STATE_DISCONNECTED);
                    Log.d(TAG, "\nAction = " + action + "\nState = " + state); //$NON-NLS-1$ //$NON-NLS-2$
                    if (state == BluetoothHeadset.STATE_CONNECTED)
                    {
                        mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    
                        // Calling startVoiceRecognition always returns false here, 
                        // that why a count down timer is implemented to call
                        // startVoiceRecognition in the onTick.
                        mIsCountDownOn = true;
                        mCountDown11.start();
    
                        // override this if you want to do other thing when the device is connected.
                        onHeadsetConnected();
    
                        Log.d(TAG, "Start count down"); //$NON-NLS-1$
                    }
                    else if (state == BluetoothHeadset.STATE_DISCONNECTED)
                    {
                        // Calling stopVoiceRecognition always returns false here
                        // as it should since the headset is no longer connected.
                        if (mIsCountDownOn)
                        {
                            mIsCountDownOn = false;
                            mCountDown11.cancel();
                        }
                        mConnectedHeadset = null;
    
                        // override this if you want to do other thing when the device is disconnected.
                        onHeadsetDisconnected();
    
                        Log.d(TAG, "Headset disconnected"); //$NON-NLS-1$
                    }
                }
                else // audio
                {
                    state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
                    Log.d(TAG, "\nAction = " + action + "\nState = " + state); //$NON-NLS-1$ //$NON-NLS-2$
                    if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED)
                    {
                        Log.d(TAG, "\nHeadset audio connected");  //$NON-NLS-1$
    
                        mIsOnHeadsetSco = true;
    
                        if (mIsCountDownOn)
                        {
                            mIsCountDownOn = false;
                            mCountDown11.cancel();
                        }
    
                        // override this if you want to do other thing when headset audio is connected.
                        onScoAudioConnected();
                    }
                    else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED)
                    {
                        mIsOnHeadsetSco = false;
    
                        // The headset audio is disconnected, but calling
                        // stopVoiceRecognition always returns true here.
                        mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
    
                        // override this if you want to do other thing when headset audio is disconnected.
                        onScoAudioDisconnected();
    
                        Log.d(TAG, "Headset audio disconnected"); //$NON-NLS-1$
                    }
                }   
            }
        };
    
        /**
         * API >= 11
         * Try to connect to audio headset in onTick.
         */
        private CountDownTimer mCountDown11 = new CountDownTimer(10000, 1000)
        {
            @TargetApi(Build.VERSION_CODES.HONEYCOMB)
            @SuppressWarnings("synthetic-access")
            @Override
            public void onTick(long millisUntilFinished)
            {
                // First stick calls always returns false. The second stick
                // always returns true if the countDownInterval is set to 1000.
                // It is somewhere in between 500 to a 1000.
                mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset);
    
                Log.d(TAG, "onTick startVoiceRecognition"); //$NON-NLS-1$
            }
    
            @SuppressWarnings("synthetic-access")
            @Override
            public void onFinish()
            {
                // Calls to startVoiceRecognition 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$
            }
        };
    
    }
    

    (2013年4月30日)编辑以在必要时更改为@TargetApi(Build.VERSION_CODES.HONEYCOMB) . 如果您对API 8或9的java.lang.NoClassDefFoundError有问题,只需删除所有API> = 11代码 . startBluetoothSco()适用于所有API版本 .

  • 11

    我认为您所要做的就是更改应用程序的音频设置 .

    当您想通过蓝牙接收和发送耳机声音时,您应该输入以下代码 .

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

    当您不使用蓝牙时,请不要忘记以下列方式恢复手机上的正常设置 .

    audioManager.setMode(AudioManager.MODE_NORMAL);
    audioManager.stopBluetoothSco();
    audioManager.setBluetoothScoOn(false);
    

    所需的权限如下:

    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    

    这很简单!

  • 3

    即使蓝牙耳机已配对并连接到电话音频配置文件(HF / HS),实际音频连接(SCO)仅在呼叫进入和接受时 Build .

    为了让您的VR应用程序接受来自蓝牙耳机的语音输入,您的应用程序必须在某些VR输入触发器上为耳机 Build SCO,您需要使用以下内容 - isBluetoothScoAvailableOffCall来检查平台是否支持此功能,然后使用startBluetoothSco和stopBluetoothSco启动SCO到耳机 .

  • 43

    startBluetoothSco需要很长时间才能 Build ,如果你需要将它用于语音控制,那就是问题 .

    有没有一种快速的方法来使用蓝牙麦克风听,然后听完后将其关闭?

    如果连接始终是连接,则无法通过A2DP传输音频 .

    那么,理想的世界:

    通过A2DP音频输出 . 当它开始收听时,它使用SCO蓝牙麦克风 . 任何回复都是A2DP .

    事实上,如果它已经连接 - 您可以通过将媒体流更改为呼叫流来实时切换吗?如果是这样,有没有明显的延迟?

  • 1

    Hoan Nguyen做得很好!
    测试他的代码我注意到在某些情况下没有调用stopBluetoothSco() .

    我建议在CountDownTimer中做一点改动:

    private CountDownTimer mCountDown11 = new CountDownTimer(10000, 1000)
    {
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        @SuppressWarnings("synthetic-access")
        @Override
        public void onTick(long millisUntilFinished)
        {
    
            mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset);
    
            Log.d(TAG, "onTick startVoiceRecognition"); //$NON-NLS-1$
        }
    
        @SuppressWarnings("synthetic-access")
        @Override
        public void onFinish()
        {
            mIsCountDownOn = false;
    
            /* START EDIT: Unregister broadcast receivers and stop Sco audio connection
               and cancel count down if fails to connect. */
    
            stopBluetooth11();
    
            /* END EDIT */
    
            Log.d(TAG, "\nonFinish fail to connect to headset audio"); //$NON-NLS-1$
        }
    };
    

相关问题