安卓开发之自动连接蓝牙2.0设备(音响,耳机)

背景

前面的文章介绍了蓝牙4.0的连接,读写操作等,这篇文章主要是蓝牙2.0(传统蓝牙)与蓝牙耳机,音响等自动连接。

权限

和BLE一样,蓝牙2.0进行蓝牙相关操作,也需要使用到蓝牙权限,在AndroidManifest.xml清单文件中添加相应权限

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

适配器

使用蓝牙前,需要获取蓝牙适配器

        blueToothAdapter = BluetoothAdapter.getDefaultAdapter();
       if (blueToothAdapter == null || !blueToothAdapter.isEnabled()) {
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, 1);
       }

广播注册

蓝牙搜索结果,配对,及连接状态,在广播中进行,因此记得实现及注册广播

 broadcastReceiver = new BroadcastReceiver() {
        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case BluetoothDevice.ACTION_FOUND:
                    device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (device != null) {
                        String name = device.getName();
                        if (name != null) {
                            Log.d(TAG, "onReceive: " + name);
                            if (name.contains("PuppyGo")) {
                                if (blueToothAdapter.isDiscovering())
                                    blueToothAdapter.cancelDiscovery();
                                device.createBond();
                            }
                        }
                    }

                    break;
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                    device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    switch (device.getBondState()) {
                        case BluetoothDevice.BOND_NONE:
                            Log.d(TAG, "取消配对");
                            search();
                            break;
                        case BluetoothDevice.BOND_BONDING:
                            Log.d(TAG, "配对中");
                            break;
                        case BluetoothDevice.BOND_BONDED:
                            blueToothAdapter.cancelDiscovery();
                            Log.d(TAG, "配对成功");
                            getBluetoothA2DP();
                            connect();
                            break;
                    }
                    break;
                case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
                    switch (intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1)) {
                        case BluetoothA2dp.STATE_CONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "device: " + device.getName() + " connecting");
                            break;
                        case BluetoothA2dp.STATE_CONNECTED:
                            isConnected = true;
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (device != null) {
                                String name = device.getName();
                                if (name != null) {
                                    mName.setText(name);
                                }
                            }
                            mPlayer = MediaPlayer.create(context, R.raw.summer);
                            mPlayer.start();

                            Log.d(TAG, "device: " + device.getName() + " connected");
                            break;
                        case BluetoothA2dp.STATE_DISCONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            break;
                        case BluetoothA2dp.STATE_DISCONNECTED:
                            isConnected = false;
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "device: " + device.getName() + " disconnected");

                            mName.setText("蓝牙名称:");
                            if (mPlayer != null) {
                                mPlayer.pause();
                                mPlayer.release();
                                mPlayer = null;
                            }
                            search();


                            break;
                        default:
                            break;
                    }
                    break;
            }
        }
    };
    //注册广播
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
    intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
    registerReceiver(broadcastReceiver, intentFilter);

搜索蓝牙

在获取适配器,注册广播之后,就可以开始搜索蓝牙设备

  if (blueToothAdapter != null && blueToothAdapter.isEnabled()) {
        blueToothAdapter.startDiscovery();
    }

搜索后的结果,会在BluetoothDevice.ACTION_FOUND中回调

     case BluetoothDevice.ACTION_FOUND:
                    device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (device != null) {
                        String name = device.getName();
                        if (name != null) {
                            Log.d(TAG, "onReceive: " + name);
                            if (name.contains("PuppyGo")) {
                                if (blueToothAdapter.isDiscovering())
                                    blueToothAdapter.cancelDiscovery();
                                device.createBond();
                            }
                        }
                    }
                    break;

如果搜索的结果,是你想要的蓝牙设备,便可以调用device.createBond()设置配对,网上也有另外的方法通过反射进行配对

配对成功

配对成功之后, 会返回BluetoothDevice.BOND_BONDED状态,亲测有些手机会自动连接上蓝牙2.0,但大部分手机还需要进行连接,这时候需要通过getProfileProxy来getBluetoothA2DP

                       case BluetoothDevice.BOND_BONDED:
                            blueToothAdapter.cancelDiscovery();
                            Log.d(TAG, "配对成功");
                            getBluetoothA2DP();
                            connect();
                            break;

之后通过mBluetoothA2dp反射来进行连接

  //connect是隐藏的方法,只能通过反射机制来调用
private void connect() {

    if (mBluetoothA2dp == null) {
        return;
    }
    if (device == null) {
        return;
    }

    try {
        Log.d(TAG, "connect" + device.getName());
        Method connect = mBluetoothA2dp.getClass().getDeclaredMethod("connect", BluetoothDevice.class);
        connect.setAccessible(true);
        connect.invoke(mBluetoothA2dp, device);
    } catch (Exception e) {
        Log.e(TAG, "connect exception:" + e);
        e.printStackTrace();
    }
}

连接成功会返回BluetoothA2dp.STATE_CONNECTED状态,至此,蓝牙设备已经连接成功,便可以进行一些操作,公司这边是要求播放歌曲来测试蓝牙音响是否卡顿,因此我这里进行简单的歌曲播放

取消配对

公司测试蓝牙连接过程中,会连接大量的蓝牙设备,如果没有取消配对,那么手机设置里面会出现一堆的配对设备。

    //取消配对
private void unPairAllDevices() {
    Log.i(TAG, "unPairAllDevices");
    for (BluetoothDevice device : blueToothAdapter.getBondedDevices()) {
        String name = device.getName();
        if (name != null) {
            if (name.contains("PuppyGo")) {
                try {
                    Method removeBond = device.getClass().getDeclaredMethod("removeBond");
                    removeBond.invoke(device);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

最后

不同于BLE连接,蓝牙2.0的连接,系统并没有提供相应方法,只能通过反射进行连接。自动连接过程中,如果在扫描结束后,仍没有搜索到相关设备,则需要通过延时操作,进行再次搜索。

new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            if (!isConnected) {
                search();
            }
        }
    }, 15000);

延时操作的方法有多种,自己使用喜欢的方式。Demo比较简单,就不上传代码了,有问题认真阅读就行了。最后,不要吝惜你的钛合金右手点个赞。

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