Android 蓝牙开发A2DP基本功能

Posted zpy_公众号_码农修仙儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 蓝牙开发A2DP基本功能相关的知识,希望对你有一定的参考价值。

转载请注明出处:http://blog.csdn.net/vnanyesheshou/article/details/71713786

本文主要是android做为Audio Source端,A2DP的基本操作:包括连接、断开连接、设置优先级、获取优先级、获取A2DP连接状态、获取A2DP连接的设备列表等功能。


##

1 简介 ##
A2DP全名是Advanced Audio Distribution Profile,高质量音频数据传输的协议,其定义里了传送单声道或立体声等高质量音频(区别于蓝牙SCO链路上传输的普通语音)信息的协议和过程。A2DP的典型应用是将音乐播放器的音频数据发送到耳机或音箱。
A2DP定义了两种角色:

Audio Source(音频源) 音频的输入端对音频数据进行编码,发送到Sink端。
Audio Sink(音频接收器) 接收到音频数据后,进行解码操作还原出音频。


##

2 A2DP profile ##
要想操作A2DP相关,首先要获取A2DP代理对象,获取代理对象的方法比较简单,如下:

mBtAdapter = BluetoothAdapter.getDefaultAdapter();
if(!mBtAdapter.isEnabled()){
	//弹出对话框提示用户是后打开  
	Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
	startActivityForResult(enabler, 1);
}
//获取A2DP代理对象
mBtAdapter.getProfileProxy(mContext, mListener, BluetoothProfile.A2DP);

getProfileProxy并不会直接返回A2DP代理对象,而是通过mListener中回调获取。

private ServiceListener mListener = new ServiceListener() {
	@Override
	public void onServiceDisconnected(int profile) {
		if(profile == BluetoothProfile.A2DP){
			mA2dp = null;
		}
	}
	@Override
	public void onServiceConnected(int profile, BluetoothProfile proxy) {
		if(profile == BluetoothProfile.A2DP){
			mA2dp = (BluetoothA2dp) proxy; //转换
		}
	}
};

成功会回调mListener中的onServiceConnected函数,判断proflie是否为BluetoothProfile.A2DP,转换为BluetoothA2dp对象。通过代理对象即可进行A2DP的相关操作了。


##

3 A2DP操作 ##
A2DP连接首先需要与蓝牙耳机进行配对,如何配对这里就不细说了。
我这里是连接到之前配对过的一个设备。设备名称为:

private final String BT_NAME = "QCY-QY7";

获取该设备,首先获取配对的蓝牙设备,然后遍历这些蓝牙设备,找出蓝牙名称符合条件的设备,就是要操作的设备,

//获取配对的蓝牙设备
Set<BluetoothDevice> bondDevice = mBtAdapter.getBondedDevices();
for(BluetoothDevice device:bondDevice){
	//获取指定名称的设备
	if(BT_NAME.equals(device.getName())){
		mConnectDevice = device;
	}
}

mConnectDevice为要操作的设备。
1 A2DP连接

private void connectA2dp(BluetoothDevice device){
	setPriority(mConnectDevice, 100); //设置priority
	try {
		//通过反射获取BluetoothA2dp中connect方法(hide的),进行连接。
		Method connectMethod =BluetoothA2dp.class.getMethod("connect",
				BluetoothDevice.class);
		connectMethod.invoke(mA2dp, device);
	} catch (Exception e) {
		e.printStackTrace();
	} 
}

BluetoothA2dp中的connect方法是hide的,不能直接访问,需要通过反射的机制获取该方法进行连接。连接成功后手机可以播放音乐,声音就会从蓝牙耳机出来。
2 断开连接

private void disConnectA2dp(BluetoothDevice device){
	setPriority(mConnectDevice, 0);
	try {
		//通过反射获取BluetoothA2dp中connect方法(hide的),断开连接。
		Method connectMethod =BluetoothA2dp.class.getMethod("disconnect",
				BluetoothDevice.class);
		connectMethod.invoke(mA2dp, device);
	} catch (Exception e) {
		e.printStackTrace();
	}
}

BluetoothA2dp中的disconnect方法也是hide的,与connect类似。
3 设置优先级

变量
PRIORITY_OFF0
PRIORITY_ON100
PRIORITY_AUTO_CONNECT1000
PRIORITY_UNDEFINED-1

设置优先级是必要的,否则可能导致连接或断开连接失败等问题。

public void setPriority(BluetoothDevice device, int priority) {
    if (mA2dp == null) return;
    try {//通过反射获取BluetoothA2dp中setPriority方法(hide的),设置优先级
    	Method connectMethod =BluetoothA2dp.class.getMethod("setPriority", 
    			BluetoothDevice.class,int.class);
    	connectMethod.invoke(mA2dp, device, priority);
    } catch (Exception e) {
		e.printStackTrace();
	}
}

4 获取优先级

public int getPriority(BluetoothDevice device) {
	int priority = 0;
    if (mA2dp == null) return priority;
    try {//通过反射获取BluetoothA2dp中getPriority方法(hide的),获取优先级
    	Method connectMethod =BluetoothA2dp.class.getMethod("getPriority", 
    			BluetoothDevice.class);
    	priority = (Integer) connectMethod.invoke(mA2dp, device);
    } catch (Exception e) {
		e.printStackTrace();
	}
    return priority;
}

5 获取与某设备A2DP连接状态

mA2dp.getConnectionState(device);

6 获取连接设备列表

//返回值类型List<BluetoothDevice>
mA2dp.getConnectedDevices();

7 A2DP是否正在发送音频流

//返回值类型boolean,表示设备是否在通过A2DP发送音频流。
mA2dp.isA2dpPlaying(device);

##

4 状态监听 ##
通过广播接收者监听A2DP连接状态的改变,A2DP播放状态的改变。

private void initReceiver(){
	//注册广播接收者监听状态改变
	IntentFilter filter = new IntentFilter(BluetoothA2dp.
			ACTION_CONNECTION_STATE_CHANGED);
	filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
	registerReceiver(mReceiver, filter);
}

广播接收者,通过intent获取状态值。

private BroadcastReceiver mReceiver = new BroadcastReceiver() {
	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();
		Log.i(TAG,"onReceive action="+action);
		//A2DP连接状态改变
		if(action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)){
			int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTED);
			Log.i(TAG,"connect state="+state);
		}else if(action.equals(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED)){
			//A2DP播放状态改变
			int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_NOT_PLAYING);
			Log.i(TAG,"play state="+state);
		}
	}
};

有问题欢迎交流指正。
连接小demo:http://www.demodashi.com/demo/14624.html

欢迎扫一扫关注我的微信公众号,定期推送优质技术文章:

这里写图片描述

以上是关于Android 蓝牙开发A2DP基本功能的主要内容,如果未能解决你的问题,请参考以下文章

Android蓝牙连接a2dp蓝牙耳机

Android蓝牙连接a2dp蓝牙耳机

Android-嵌入式蓝牙 多年蓝牙产品开发学习心路历程分享-A2DP音频流的建立A2DP播放暂停音乐命令交互HFPAVRCPRFCOMMOPPAVDTP

iOS上的蓝牙A2DP API支持?

android 获取蓝牙已连接设备

经典蓝牙蓝牙 A2DP协议分析