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_OFF 0
PRIORITY_ON 100
PRIORITY_AUTO_CONNECT 1000
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);
        }
    }
};

有问题欢迎交流指正。

欢迎大家关注、评论、点赞
你们的支持是我坚持的动力。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容

  • 转载请注明出处:http://blog.csdn.net/vnanyesheshou/article/detail...
    朋永阅读 4,362评论 0 0
  • A2DP简介 A2DP(Advanced Audio Distribution Profile):高质量音频数据传...
    YoungTa0阅读 2,849评论 1 4
  • 最近项目使用蓝牙,之前并没有接触,还是发现了很多坑,查阅了很多资料,说的迷迷糊糊,今天特查看官方文档。 说下遇到的...
    King9527阅读 1,784评论 0 1
  • Android 平台包含蓝牙网络堆栈支持,凭借此项支持,设备能以无线方式与其他蓝牙设备交换数据。应用框架提供了通过...
    虎三呀阅读 762评论 0 1
  • 1 蓝牙基础知识 1.1 蓝牙相关的权限 1.2 BluetoothAdapter两种获取对象的方法 1.3 蓝牙...
    秀叶寒冬阅读 730评论 0 3