Java 以编程方式连接成对的蓝牙扬声器并播放音频
在我们的应用程序中,我想连接到先前配对的A2DP蓝牙扬声器,并使用Android v4.2或更高版本直接播放音频 我可以使用以下代码成功创建A2DP配置文件对象来启动该过程:Java 以编程方式连接成对的蓝牙扬声器并播放音频,java,android,bluetooth,android-bluetooth,a2dp,Java,Android,Bluetooth,Android Bluetooth,A2dp,在我们的应用程序中,我想连接到先前配对的A2DP蓝牙扬声器,并使用Android v4.2或更高版本直接播放音频 我可以使用以下代码成功创建A2DP配置文件对象来启动该过程: 和以下侦听器来响应连接: private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, Blu
和以下侦听器来响应连接:
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;
}
}
};
代码似乎确实以某种方式连接到了设备,例如当我停止执行时,蓝牙扬声器会通知它已准备好配对(当它与音频源断开连接时总是这样)
较旧版本的BluetoothA2dp
似乎有一个connect(BluetoothDevice)
方法,但该方法现在已经被删除(从4.2开始),我正在努力寻找任何清晰的示例,说明如何通过编程方式连接到A2DP设备,并将音频输出定向到该设备。任何关于如何接近这两者的帮助都将不胜感激
如果您有任何关于如何处理此问题的建议,我们将不胜感激。Ted
当我尝试使用蓝牙耳机时,我和你有同样的问题。
我想我的工作可能与A2DP有关。
因为我的耳机只支持免提模式。我只测试蓝牙耳机
无需建立RFComm通道
对我来说。
连接到BluetoothHeadset服务后,
1.检查音频是否已连接
mBluetoothSpeaker.isAudioConnected(btSpeaker);
二,。如果没有,请建立音频连接
mBluetoothSpeaker.startVoiceRecognition(btSpeaker);
三,。注册BluetoothHeadset.ACTION\连接\状态\更改和BluetoothHeadset.ACTION\音频\状态\更改的广播接收器
registerReceiver(mReceiver, new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));
registerReceiver(mReceiver, new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
四,。广播接收机
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);
}
}
}
};
protectedbroadcastReceiver mReceiver=new BroadcastReceiver(){
@凌驾
公共void onReceive(上下文、意图){
String action=intent.getAction();
int state=BluetoothHeadset.state\u已断开连接;
int previousState=intent.getIntExtra(蓝牙耳机.EXTRA\u先前的状态,蓝牙耳机.STATE\u已断开);
if(action.equals(蓝牙耳机.action\u CONNECTION\u STATE\u CHANGED)){
state=intent.getIntExtra(蓝牙耳机.EXTRA\u状态,蓝牙耳机.state\u已断开);
if(state==蓝牙耳机。state\u已连接){
mConnectedHeadset=intent.getParcelableExtra(蓝牙设备.EXTRA_设备);
mInfoTextview.append(“\n\n设备名称=“+mConnectedHeadset.getName());
//音频还不应该连接,只是为了确保。
如果(mBluetoothHeadset.isAudioConnected(mConnectedHeadset)){
Log.d(标签“耳机音频已连接”);
}否则{
if(!mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset)){
Log.e(标记“也许您以前没有调用stopVoiceRecognition”);
mBluetoothHeadset.停止语音识别(mConnectedHeadset);
mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset);
}
}
}
else if(状态==蓝牙耳机。状态\u已断开){
mConnectedHeadset=null;
}
}
else if(action.equals(BluetoothHeadset.action\u AUDIO\u STATE\u CHANGED))//音频
{
state=intent.getIntExtra(BluetoothHeadset.EXTRA\u state,BluetoothHeadset.state\u AUDIO\u DISCONNECTED);
如果(状态==蓝牙耳机。状态\音频\已连接){
//蓝牙音频已连接。您现在将音频流发送到耳机!!!
mAudioManager.setMode(AudioManager.STREAM\u VOICE\u CALL);
mMediaPlayer=新媒体播放器();
AssetManager AssetManager=getAssets();
试一试{
AssetFileDescriptor fd=assetManager.openFd(“radiotic.mp3”);
mmediplayer.setDataSource(fd.getFileDescriptor());
//将音频流类型设置为“流”\u语音通话将向耳机发送音频
//@见
mmediplayer.setAudioStreamType(AudioManager.STREAM\u VOICE\u CALL);
mmediplayer.prepare();
Log.d(标签“开始播放音乐”);
mmediplayer.start();
}捕获(IOE异常){
e、 printStackTrace();
}
}
else if(状态==蓝牙耳机。状态\u音频\u断开){
if(mmediplayer!=null){
mmediplayer.stop();
mmediplayer=null;
}
mBluetoothHeadset.停止语音识别(mConnectedHeadset);
}
}
}
};
这个适合我。
在接收蓝牙A2DP.STATE_连接后,您可以正常播放音乐
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设备,您只需调用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\u ALARM)行,它对我有效。我假设您在调用
getProfileProxy(…)
之前正在创建mProfileListener
实例?是,onServiceConnected
块启动得很愉快。这个问题的答案和对它的评论似乎不太可能。感谢Squonk,我可以通过调用createInsurerCommsockettoServiceRecord()
,让设备连接(或者至少启动一个BluetoothDevice.ACTION\uACL\uConnected
事件),但如果这篇文章是正确的,那么无论如何,RFcomm对于A2DP广播是错误的。连接A2DP设备的正确方式是什么?Android蓝牙文档中似乎有一个很大的漏洞(或者至少是我对它的理解)。老实说,我不知道,因为我从未尝试过A2DP,但我同意文档中存在一个漏洞
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);
}
}
}
};
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();
}
}
mMediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
//.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build());