zoukankan      html  css  js  c++  java
  • Android 蓝牙开发之A2DP基本功能

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

    1.简介

    Audio Source(音频源) 音频的输入端对音频数据进行编码,发送到Sink端。 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为要操作的设备。

    3.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的,不能直接访问,需要通过反射的机制获取该方法进行连接。连接成功后手机可以播放音乐,声音就会从蓝牙耳机出来。

    3.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.3 设置优先级

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

    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();
        }
    }

    3.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;
    }

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

    mA2dp.getConnectionState(device);

    3.6 获取连接设备列表

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

    3.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://download.csdn.net/detail/vnanyesheshou/9841491

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

  • 相关阅读:
    森田疗法
    “不支持一个STA线程上针对多个句柄的WaitAll。”的解决方案
    烽火HG226信息
    祝贺小牛队得NBA总冠军
    .net4调用非托管代码出现:PInvoke调用导致堆栈不对称
    大怪路子逻辑
    C#内存复制与比较
    【收藏】UDP广播和多播
    Objectivec NSString
    Objectivec NSDictionary(NSMutableDictionary)
  • 原文地址:https://www.cnblogs.com/fuyaozhishang/p/7503595.html
Copyright © 2011-2022 走看看