Recording Audio from a Bluetooth Audio Device in Android

前端 未结 3 1961
心在旅途
心在旅途 2020-12-28 11:46

How can I record the voice from a paired Bluetooth audio device (i.e. Moster Clarity Bluetooth Speaker) in Android.

I\'ve paired with the device from within Android,

相关标签:
3条回答
  • 2020-12-28 12:15

    code to voice recording from bluetooth headset

    public class Recording {
    
    static int count = 0;
    static String Shared;
    static String bFlag;
    public static int TIMEOUT = 5000;
    public static int COUNTDOWN_INTERVAL = 1000;
    static Context context;
    
    public static void checkAndRecord(Context context,
            OnBluetoothRecording BluetoothRecording, boolean resume) {
    
        // Check bluetooth flag And Bluetooth is ON or OFF
        if (getBluetoothFlag(context) && isBluetoothON()) {
    
            // Check for bluetooth and Record
            startBluetoothRecording(BluetoothRecording, resume, context);
    
        } else {
    
            // If Bluetooth is OFF Show Toast else Dont Show
            if (getBluetoothFlag(context) && !isBluetoothON()) {
                // false because recording not started
                Toast.makeText(context,
                        "Bluetooth is OFF. Recording from Phone MIC.",
                        Toast.LENGTH_SHORT).show();
                BluetoothRecording.onStartRecording(resume, false);
            } else {
                // false because recording not started
                BluetoothRecording.onStartRecording(resume, false);
            }
        }
    
    }
    
    private static void startBluetoothRecording(
            final OnBluetoothRecording BluetoothRecording,
            final boolean resume, Context context) {
        // TODO Auto-generated method stub
    
        final int MAX_ATTEPTS_TO_CONNECT = 3;
        final AudioManager audioManager = (AudioManager) context
                .getSystemService(Context.AUDIO_SERVICE);
    
        final CountDownTimer timer = getTimer(BluetoothRecording, audioManager,
                resume);
    
        context.registerReceiver(new BroadcastReceiver() {
    
            @Override
            public void onReceive(Context context, Intent intent) {
    
                int state = intent.getIntExtra(
                        AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
                if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
                    // cancel Timer
                    timer.cancel();
                    context.unregisterReceiver(this);
    
                    // pass through and true because
                    // recording from bluetooth so set 8000kHz
    
                    BluetoothRecording.onStartRecording(resume, true);
    
                } else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state) {
                    if (count > MAX_ATTEPTS_TO_CONNECT) {
                        context.unregisterReceiver(this);
                        // Stop BluetoothSCO
                        audioManager.stopBluetoothSco();
                        // reset Counter
                        count = 0;
                        // stop timer
                        timer.cancel();
                        // false because still recording not started
                        BluetoothRecording.onStartRecording(resume, false);
                    } else {
                        // Increment Disconnect state Count
                        count++;
    
                    }
                }
    
            }
        }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
    
        // Start the timer
        timer.start();
        audioManager.startBluetoothSco();
    
    }
    
    // set the Timeout
    private static CountDownTimer getTimer(
            final OnBluetoothRecording BluetoothRecording,
            final AudioManager audioManager, final boolean resume) {
        // TODO Auto-generated method stub
        return new CountDownTimer(TIMEOUT, COUNTDOWN_INTERVAL) {
    
            @Override
            public void onTick(long millisUntilFinished) {
                // Do Nothing
    
            }
    
            @Override
            public void onFinish() {
    
                // stopBluetoothSCO() and start Normal Recording
                audioManager.stopBluetoothSco();
    
                // false because recording button is already clicked but still
                // not recording.
                BluetoothRecording.onStartRecording(resume, false);
            }
        };
    }
    
    // Return's the bluetooth state
    private static boolean isBluetoothON() {
    
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter
                .getDefaultAdapter();
        return bluetoothAdapter.isEnabled();
    }
    
    // Return's the bluetoothFlag state
    private static boolean getBluetoothFlag(Context context) {
    
        // shared pref
        SharedPreferences sp = context.getSharedPreferences(Shared,
                Context.MODE_PRIVATE);
        return sp.getBoolean(bFlag, false);
    
    }
    
    }
    

    Interface OnBluetoothRecording.java

    public interface OnBluetoothRecording {
    
    void onStartRecording(boolean state,boolean bluetoothFlag);
    void onCancelRecording();
    }
    
    0 讨论(0)
  • 2020-12-28 12:33

    Try this code maybe helpful for you..

    am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    
    registerReceiver(new BroadcastReceiver() {
    
    @Override
    public void onReceive(Context context, Intent intent) {
        int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
        Log.d(TAG, "Audio SCO state: " + state);
    
        if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) { 
            /* 
             * Now the connection has been established to the bluetooth device. 
             * Record audio or whatever (on another thread).With AudioRecord you can          record   with an object created like this:
             * new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
             * AudioFormat.ENCODING_PCM_16BIT, audioBufferSize);
             *
             * After finishing, don't forget to unregister this receiver and
             * to stop the bluetooth connection with am.stopBluetoothSco();
             */
            unregisterReceiver(this);
        }
    
        }
    }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
    
    Log.d(TAG, "starting bluetooth");
    am.startBluetoothSco();
    
    0 讨论(0)
  • 2020-12-28 12:34

    The key thing is to call audioManager.startBluetoothSco().

    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.

    This is an asynchronous operation, as such, you can register a BroadcastReceiver to be notified once audio will start being recorded through the bluetooth headset like so

    private BroadcastReceiver mBluetoothScoReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
    
            if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
                // Start recording audio
            }
        }
    };
    
    
    @Override
    protected void onResume() {
        super.onResume();
    
        IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
        registerReceiver(mBluetoothScoReceiver, intentFilter);
    
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.startBluetoothSco();
    }
    

    The docs also mention something very important

    the application can check the SCO audio state before calling startBluetoothSco() by reading the intent returned by the receiver registration. If the state is already CONNECTED, no state change will be received via the intent after calling startBluetoothSco().

    And...

    It is however useful to call startBluetoothSco() so that the connection stays active in case the current initiator stops the connection.

    This means you do not have to wait for the receiver to be called if the SCO connection is already active. Here is the updated code snippet.

    @Override
    protected void onResume() {
        super.onResume();
    
        IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
        Intent intent = registerReceiver(mBluetoothScoReceiver, intentFilter);
        if (intent == null) {
            Log.e(TAG, "Failed to register bluetooth sco receiver...");
            return;
        }
    
        int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
        if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
            // Start recording
        }
    
        // Ensure the SCO audio connection stays active in case the
        // current initiator stops it.
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.startBluetoothSco();
    }
    

    You should stop the SCO connection if you are not using it.

    private void onPause() {
        super.onPause();
    
        unregisterReceiver(mBluetoothScoReceiver);
    
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.stopBluetoothSco();
    }
    

    You will also need the following permissions in your AndroidManifest.xml file

    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.BROADCAST_STICKY"/>
    
    0 讨论(0)
提交回复
热议问题