首页 文章

以编程方式连接到配对的蓝牙扬声器并播放音频

提问于
浏览
7

在我们的应用程序中,我想使用Android v4.2或更高版本连接到之前配对的A2DP蓝牙扬声器并直接播放音频 .

我可以使用此代码成功创建A2DP配置文件对象以启动该过程:


/* Manifest permissions */
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

// Get the default adapter
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

// Establish connection to the proxy.
mBluetoothAdapter.getProfileProxy(this, mProfileListener, BluetoothProfile.A2DP)

并且以下监听器响应连接:

private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {

    if (profile == BluetoothProfile.A2DP) {

        mBluetoothSpeaker = (BluetoothA2dp) proxy;

        // no devices are connected         
        List<BluetoothDevice> connectedDevices = mBluetoothSpeaker.getConnectedDevices();

        //the one paired (and disconnected) speaker is returned here
        int[] statesToCheck = {BluetoothA2dp.STATE_DISCONNECTED};           
        List<BluetoothDevice> disconnectedDevices = mBluetoothSpeaker.getDevicesMatchingConnectionStates(statesToCheck);



        BluetoothDevice btSpeaker = disconnectedDevices.get(0); 

        //WHAT NOW?

    }
}
public void onServiceDisconnected(int profile) {
    if (profile == BluetoothProfile.A2DP) {
        mBluetoothSpeaker = null;
    }
}
};

我已尝试使用以下代码连接到设备as detailed in the Android docs,但最终 BluetoothSpeaker.getConnectedDevices() 调用不返回任何已连接的设备 .

BluetoothSocket tmp = null;
    UUID MY_UUID = UUID.fromString("00001108-0000-1000-8000-00805f9b34fb");
    try {           
        tmp = btSpeaker.createInsecureRfcommSocketToServiceRecord(MY_UUID);

    } catch (IOException e1) {
        // TODO Auto-generated catch block
        Log.d("createRfcommSocketToServiceRecord ERROR", e1.getMessage());
    }
    mmSocket = tmp;

    try {
        // Connect the device through the socket. This will block
        // until it succeeds or throws an exception
        mmSocket.connect();
    } catch (IOException connectException) {
        // Unable to connect; close the socket and get out
        try {
            Log.d("connectException", connectException.getMessage());
            mmSocket.close();
        } catch (IOException closeException) { }
        return;
    }

    connectedDevices = mBluetoothSpeaker.getConnectedDevices();

代码似乎确实以某种方式连接到设备,因为当我停止执行时,蓝牙扬声器宣布它已准备好配对(就像它从音频源断开时一样) .

旧版本的 BluetoothA2dp 似乎有一个 connect(BluetoothDevice device) 方法,但现在已被删除(截至4.2),我很难找到任何明确的例子,说明如何以编程方式连接到A2DP设备,并将音频输出定向到它 . 我们将非常感激地提供任何关于如何接近任何一方的帮助 .

任何有关如何处理此问题的建议都将受到极大的赞赏 .

3 回答

  • 0

    这个对我有用 . 收到BluetoothA2dp.STATE_CONNECTED后,您可以正常播放音乐 .

    public class A2DPActivity extends Activity {
    
    protected static final String TAG = "ZS-A2dp";
    
    Button mBtPlay;
    
    BluetoothAdapter mBtAdapter;
    BluetoothA2dp mA2dpService;
    
    AudioManager mAudioManager;
    MediaPlayer mPlayer;
    
    BroadcastReceiver mReceiver = new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context ctx, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "receive intent for action : " + action);
            if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
                int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTED);
                if (state == BluetoothA2dp.STATE_CONNECTED) {
                    setIsA2dpReady(true);
                    playMusic();
                } else if (state == BluetoothA2dp.STATE_DISCONNECTED) {
                    setIsA2dpReady(false);
                }
            } else if (action.equals(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED)) {
                int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_NOT_PLAYING);
                if (state == BluetoothA2dp.STATE_PLAYING) {
                    Log.d(TAG, "A2DP start playing");
                    Toast.makeText(A2DPActivity.this, "A2dp is playing", Toast.LENGTH_SHORT).show();
                } else {
                    Log.d(TAG, "A2DP stop playing");
                    Toast.makeText(A2DPActivity.this, "A2dp is stopped", Toast.LENGTH_SHORT).show();
                }
            }
        }
    
    };
    
    boolean mIsA2dpReady = false;
    void setIsA2dpReady(boolean ready) {
        mIsA2dpReady = ready;
        Toast.makeText(this, "A2DP ready ? " + (ready ? "true" : "false"), Toast.LENGTH_SHORT).show();
    }
    
    private ServiceListener mA2dpListener = new ServiceListener() {
    
        @Override
        public void onServiceConnected(int profile, BluetoothProfile a2dp) {
            Log.d(TAG, "a2dp service connected. profile = " + profile);
            if (profile == BluetoothProfile.A2DP) {
                mA2dpService = (BluetoothA2dp) a2dp;
                if (mAudioManager.isBluetoothA2dpOn()) {
                    setIsA2dpReady(true);
                    playMusic();
                } else {
                    Log.d(TAG, "bluetooth a2dp is not on while service connected");
                }
            }
        }
    
        @Override
        public void onServiceDisconnected(int profile) {
            setIsA2dpReady(false);
        }
    
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout ll = new LinearLayout(this);
        setContentView(ll);
    
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        registerReceiver(mReceiver, new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED));
        registerReceiver(mReceiver, new IntentFilter(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED));
    
        mBtAdapter = BluetoothAdapter.getDefaultAdapter();
        mBtAdapter.getProfileProxy(this, mA2dpListener , BluetoothProfile.A2DP);
    
    }
    
    @Override
    protected void onDestroy() {
        mBtAdapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dpService);
        releaseMediaPlayer();
        unregisterReceiver(mReceiver);
        super.onDestroy();
    }
    
    @Override
    protected void onPause() {
        releaseMediaPlayer();
        super.onPause();
    }
    
    private void releaseMediaPlayer() {
        if (mPlayer != null) {
            mPlayer.release();
            mPlayer = null;
        }
    }
    
    private void playMusic() {
        mPlayer = new MediaPlayer();
        AssetManager assetManager = this.getAssets();
        AssetFileDescriptor fd;
        try {
            fd = assetManager.openFd("Radioactive.mp3");
            Log.d(TAG, "fd = " + fd);
            mPlayer.setDataSource(fd.getFileDescriptor());
            mPlayer.prepare();
            Log.d(TAG, "start play music");
            mPlayer.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    }

  • 1

    特德

    当我尝试使用BluetoothHeadset时,我遇到了和你一样的问题 . 我想我的工作可能适用于A2DP . 由于我的耳机仅支持免提配置文件 . 我只用BlueHeadset测试 .

    无需 Build RFComm Channels .

    为了我 . 连接到BluetoothHeadsetService后,1 . 检查音频是否已连接

    mBluetoothSpeaker.isAudioConnected(btSpeaker);
    

    2.如果没有, Build 音频连接

    mBluetoothSpeaker.startVoiceRecognition(btSpeaker);
    

    3.为BluetoothHeadset注册BroadcastReceiver.ACTION_CONNECTION_STATE_CHANGED和BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED

    registerReceiver(mReceiver, new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));
    registerReceiver(mReceiver, new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
    
    1. BroadcastReceiver
    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            int state = BluetoothHeadset.STATE_DISCONNECTED;
            int previousState = intent.getIntExtra(BluetoothHeadset.EXTRA_PREVIOUS_STATE, BluetoothHeadset.STATE_DISCONNECTED);
            if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
                if (state == BluetoothHeadset.STATE_CONNECTED) {
                    mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    mInfoTextview.append("\n\nDevice name = " + mConnectedHeadset.getName());
    
                    // Audio should not be connected yet but just to make sure.
                    if (mBluetoothHeadset.isAudioConnected(mConnectedHeadset)) {
                        Log.d(TAG, "Headset audio connected already");
                    } else {
                        if (!mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset)) {
                            Log.e(TAG, "maybe you do not call stopVoiceRecognition previously");
                            mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
                            mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset);
                        }
                    }
                }
                else if (state == BluetoothHeadset.STATE_DISCONNECTED) {
                    mConnectedHeadset = null;
                }
            }
            else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED))// audio
            {
                state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
                if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
                    // Bluetooth audio connected. you send audio stream to headset now!!!
                    mAudioManager.setMode(AudioManager.STREAM_VOICE_CALL);
                    mMediaPlayer = new MediaPlayer();
                    AssetManager assetManager = getAssets();
                    try {
            AssetFileDescriptor fd = assetManager.openFd("Radioactive.mp3");
            mMediaPlayer.setDataSource(fd.getFileDescriptor());
                        // set audio stream type to STREAM_VOICE_CALL will send audio to headset
                        // @see <a href="http://developer.android.com/reference/android/media/AudioManager.html#startBluetoothSco()">SCO</a>
                        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
            mMediaPlayer.prepare();
            Log.d(TAG, "start play music");
            mMediaPlayer.start();
            } catch (IOException e) {
            e.printStackTrace();
            }
                }
                else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                    if (mMediaPlayer != null) {
                    mMediaPlayer.stop();
                    mMediaPlayer = null;
                    }
                    mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
                }
            }   
        }
    };
    
  • 7

    有同样的问题,但发现老帖子:

    Programmatically connect to paired Bluetooth device

    简而言之,为了连接到配对的a2dp设备,你只需要调用BluetoothA2dp.connect(myPairedA2dpDevice),但是现在该方法对公共API是隐藏的,这是没有用的 . 所以你通过Java反射访问它 . 这是一种黑客行为,但谷歌的方式,现在似乎没有一个干净的解决方案 .

相关问题