[英]Programmatically connect to paired Bluetooth speaker and play audio
在我们的应用程序中,我想使用 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;
}
}
};
我对现在要做什么、连接设备并将音频输出定向到它有点不知所措。 我已尝试使用以下代码连接到设备, 如 Android 文档中所述,但最终的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 设备的任何明确示例,并指导音频输出到它。 将不胜感激地收到有关如何接近两者的任何帮助。
任何关于如何解决这个问题的建议将不胜感激。
这个对我有用。 收到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();
}
}
}
泰德,
当我尝试使用蓝牙耳机时,我遇到了和你一样的问题。 我想我的工作可能适用于 A2DP。 由于我的耳机仅支持免提模式。 我只用蓝牙耳机测试。
无需建立 RFComm 通道。
为了我。 连接BluetoothHeadsetService后,1.检查音频是否已经连接
mBluetoothSpeaker.isAudioConnected(btSpeaker);
2.如果没有,建立音频连接
mBluetoothSpeaker.startVoiceRecognition(btSpeaker);
3.为BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED和BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED注册BroadcastReceiver
registerReceiver(mReceiver, new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));
registerReceiver(mReceiver, new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
4. 广播接收器
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);
}
}
}
};
有同样的问题,但发现旧帖子:
简而言之,为了连接到配对的 a2dp 设备,您只需调用 BluetoothA2dp.connect(myPairedA2dpDevice),但现在该方法对公共 API 是隐藏的,这没有帮助。 所以你通过Java反射访问它。 这有点像黑客,但按照谷歌的说法,目前似乎没有一个干净的解决方案。
mMediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
//.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build());
通过评论 .setUsage(AudioAttributes.USAGE_ALARM) 行,它对我有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.