Android蓝牙——BLE的开启、搜索、配对与连接

1、权限

首先需要在AndroidManifest中申请如下权限。

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

2、获得蓝牙管理对象

BluetoothManager的主要作用是从中得到我们需要的对象

//@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
//首先获取BluetoothManager
 BluetoothManager bluetoothManager=(BluetoothManager) context.getService(Context.BLUETOOTH_SERVICE);

3、获得蓝牙适配器

蓝牙适配器是我们操作蓝牙的主要对象,可以从中获得配对过的蓝牙集合,可以获得蓝牙传输对象等等

//获取BluetoothAdapter
if (bluetoothManager != null)
    BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

4、注册广播来接收蓝牙配对信息

蓝牙搜索结果,蓝牙状态变化是通过广播的方式通知APP的,APP需要在蓝牙开启前注册广播

// 用BroadcastReceiver来取得搜索结果
        IntentFilter intent = new IntentFilter();
        intent.addAction(BluetoothDevice.ACTION_FOUND);//搜索发现设备
        intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
        intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//行动扫描模式改变了
        intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//动作状态发生了变化
        context.registerReceiver(searchDevices, intent);

5、反注册广播和清楚蓝牙连接

在不需要使用蓝牙的时候调用,反注册广播取消蓝牙的配对

/**
     * 反注册广播取消蓝牙的配对
     *
     * @param context
     */
    public void unregisterReceiver(Context context) {
        context.unregisterReceiver(searchDevices);
        if (mBluetoothAdapter != null)
            mBluetoothAdapter.cancelDiscovery();
    }

6、蓝牙接收广播

 /**
     * 蓝牙接收广播
     */
    private BroadcastReceiver searchDevices = new BroadcastReceiver() {
        //接收
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Bundle b = intent.getExtras();
            Object[] lstName = b.keySet().toArray();


            // 显示所有收到的消息及其细节
            for (int i = 0; i < lstName.length; i++) {
                String keyName = lstName[i].toString();
                Log.e("bluetooth", keyName + ">>>" + String.valueOf(b.get(keyName)));
            }
            BluetoothDevice device;
            // 搜索发现设备时,取得设备的信息;注意,这里有可能重复搜索同一设备
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                onRegisterBltReceiver.onBluetoothDevice(device);
            }
            //状态改变时
            else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_BONDING://正在配对
                        Log.d("BlueToothTestActivity", "正在配对......");
                        onRegisterBltReceiver.onBltIng(device);
                        break;
                    case BluetoothDevice.BOND_BONDED://配对结束
                        Log.d("BlueToothTestActivity", "完成配对");
                        onRegisterBltReceiver.onBltEnd(device);
                        break;
                    case BluetoothDevice.BOND_NONE://取消配对/未配对
                        Log.d("BlueToothTestActivity", "取消配对");
                        onRegisterBltReceiver.onBltNone(device);
                    default:
                        break;
                }
            }
        }
    };

6、注册蓝牙回调广播

    /**
     * 注册蓝牙回调广播
     */
    private void blueToothRegister() {
        BltManager.getInstance().registerBltReceiver(this, new BltManager.OnRegisterBltReceiver() {


            /**搜索到新设备
             * @param device
             */
            @Override
            public void onBluetoothDevice(BluetoothDevice device) {
                if (bltList != null && !bltList.contains(device)) {
                    bltList.add(device);
                }
                if (myAdapter != null)
                    myAdapter.notifyDataSetChanged();
            }


            /**连接中
             * @param device
             */
            @Override
            public void onBltIng(BluetoothDevice device) {
                btl_bar.setVisibility(View.VISIBLE);
                blt_status_text.setText("连接" + device.getName() + "中……");
            }


            /**连接完成
             * @param device
             */
            @Override
            public void onBltEnd(BluetoothDevice device) {
                btl_bar.setVisibility(View.GONE);
                blt_status_text.setText("连接" + device.getName() + "完成");
            }


            /**取消链接
             * @param device
             */
            @Override
            public void onBltNone(BluetoothDevice device) {
                btl_bar.setVisibility(View.GONE);
                blt_status_text.setText("取消了连接" + device.getName());
            }
        });
    }

7、打开蓝牙

判断当前设备是否支持蓝牙,如果支持则打开蓝牙

   /**
     * 判断是否支持蓝牙,并打开蓝牙
     * 获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。
     * 如果没打开,需要让用户打开蓝牙:
     */
    public void checkBleDevice(Context context) {
        if (mBluetoothAdapter != null) {
            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(enableBtIntent);
            }
        } else {
            Log.i("blueTooth", "该手机不支持蓝牙");
        }
    }

8、搜索蓝牙

        搜索后添加到自定义的集合中以供自身程序的逻辑使用。注意:搜索到的结果会在广播中回调过来,这里不做回调。若使用过时的接口,则在当前逻辑里回调结果。我们这里使用广播,不建议使用过时的方法。

/**
     * 搜索蓝牙设备
     * 通过调用BluetoothAdapter的startLeScan()搜索BLE设备。
     * 调用此方法时需要传入 BluetoothAdapter.LeScanCallback参数。
     * 因此你需要实现 BluetoothAdapter.LeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。
     * <p/>
     * 由于搜索需要尽量减少功耗,因此在实际使用时需要注意:
     * 1、当找到对应的设备后,立即停止扫描;
     * 2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
     * <p/>
     * 如果你只需要搜索指定UUID的外设,你可以调用 startLeScan(UUID[], BluetoothAdapter.LeScanCallback)方法。
     * 其中UUID数组指定你的应用程序所支持的GATT Services的UUID。
     * <p/>
     * 注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
     */
    private boolean startSearthBltDevice(Context context) {
        //开始搜索设备,当搜索到一个设备的时候就应该将它添加到设备集合中,保存起来
        checkBleDevice(context);
        //如果当前发现了新的设备,则停止继续扫描,当前扫描到的新设备会通过广播推向新的逻辑
        if (getmBluetoothAdapter().isDiscovering())
            stopSearthBltDevice();
        Log.i("bluetooth", "本机蓝牙地址:" + getmBluetoothAdapter().getAddress());
        //开始搜索
        mBluetoothAdapter.startDiscovery();
        //这里的true并不是代表搜索到了设备,而是表示搜索成功开始。
        return true;
    }

9、停止搜索蓝牙设备

public boolean stopSearthBltDevice() {
        //暂停搜索设备
        if(mBluetoothAdapter!=null)
        return mBluetoothAdapter.cancelDiscovery();
    }

10、连接蓝牙

注意:连接蓝牙的前提是我们已经建立好了蓝牙服务器端。所以,这里我们先建立蓝牙服务器 ——1)先建立蓝牙服务器端

/**
     * 这个操作应该放在子线程中,因为存在线程阻塞的问题
     */
    public void run(Handler handler) {
        //服务器端的bltsocket需要传入uuid和一个独立存在的字符串,以便验证,通常使用包名的形式
        BluetoothServerSocket  bluetoothServerSocket = tmBluetoothAdapter.listenUsingRfcommWithServiceRecord("com.bluetooth.demo", BltContant.SPP_UUID);
        while (true) {
            try {
                //注意,当accept()返回BluetoothSocket时,socket已经连接了,因此不应该调用connect方法。
                //这里会线程阻塞,直到有蓝牙设备链接进来才会往下走
                socket = getBluetoothServerSocket().accept();
                if (socket != null) {
                    BltAppliaction.bluetoothSocket = socket;
                    //回调结果通知
                    Message message = new Message();
                    message.what = 3;
                    message.obj = socket.getRemoteDevice();
                    handler.sendMessage(message);
                    //如果你的蓝牙设备只是一对一的连接,则执行以下代码
                    getBluetoothServerSocket().close();
                    //如果你的蓝牙设备是一对多的,则应该调用break;跳出循环
                    //break;
                }
            } catch (IOException e) {
                try {
                    getBluetoothServerSocket().close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                break;
            }
        }
    }

——2)在蓝牙服务器建立之后,再进行连接蓝牙的操作。

/**
     * 尝试连接一个设备,子线程中完成,因为会线程阻塞
     *
     * @param btDev 蓝牙设备对象
     * @param handler 结果回调事件
     * @return
     */
    private void connect(BluetoothDevice btDev, Handler handler) {
        try {
            //通过和服务器协商的uuid来进行连接
            mBluetoothSocket = btDev.createRfcommSocketToServiceRecord(BltContant.SPP_UUID);
            if (mBluetoothSocket != null)
                //全局只有一个bluetooth,所以我们可以将这个socket对象保存在appliaction中
                BltAppliaction.bluetoothSocket = mBluetoothSocket;
            //通过反射得到bltSocket对象,与uuid进行连接得到的结果一样,但这里不提倡用反射的方法
            //mBluetoothSocket = (BluetoothSocket) btDev.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(btDev, 1);
            Log.d("blueTooth", "开始连接...");
            //在建立之前调用
            if (getmBluetoothAdapter().isDiscovering())
                //停止搜索
                getmBluetoothAdapter().cancelDiscovery();
            //如果当前socket处于非连接状态则调用连接
            if (!getmBluetoothSocket().isConnected()) {
                //你应当确保在调用connect()时设备没有执行搜索设备的操作。
                // 如果搜索设备也在同时进行,那么将会显著地降低连接速率,并很大程度上会连接失败。
                getmBluetoothSocket().connect();
            }
            Log.d("blueTooth", "已经链接");
            if (handler == null) return;
            //结果回调
            Message message = new Message();
            message.what = 4;
            message.obj = btDev;
            handler.sendMessage(message);
        } catch (Exception e) {
            Log.e("blueTooth", "...链接失败");
            try {
                getmBluetoothSocket().close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }

11、自动连接以往配对成功的设备

注意:连接的前提是服务器端已开启,若没开启则进行8.1的操作

/**
     * 尝试配对和连接
     *
     * @param btDev
     */
    public void createBond(BluetoothDevice btDev, Handler handler) {
        if (btDev.getBondState() == BluetoothDevice.BOND_NONE) {
            //如果这个设备取消了配对,则尝试配对
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                btDev.createBond();
            }
        } else if (btDev.getBondState() == BluetoothDevice.BOND_BONDED) {
            //如果这个设备已经配对完成,则尝试连接
            connect(btDev, handler);
        }
    }


 /**
     * 获得系统保存的配对成功过的设备,并尝试连接
     */
    public void getBltList() {
        if (getmBluetoothAdapter() == null) return;
        //获得已配对的远程蓝牙设备的集合
        Set<BluetoothDevice> devices = getmBluetoothAdapter().getBondedDevices();
        if (devices.size() > 0) {
            for (Iterator<BluetoothDevice> it = devices.iterator(); it.hasNext(); ) {
                BluetoothDevice device = it.next();
                //自动连接已有蓝牙设备
                createBond(device, null);
            }
        }
    }

        外界只需要调用getBltList();方法即可进行自动连接。

12、输入mac地址自动连接设备

        前提是系统原来连接过该地址。

 /**
     * 输入mac地址进行自动配对
     * 前提是系统保存了该地址的对象
     *
     * @param address
     */
    public void autoConnect(String address, Handler handler) {
        if (getmBluetoothAdapter().isDiscovering()) getmBluetoothAdapter().cancelDiscovery();
        BluetoothDevice btDev = getmBluetoothAdapter().getRemoteDevice(address);
        connect(btDev, handler);
    }

13、蓝牙连接状态

        用于我们判断该蓝牙设备是出于:未配对还是配对未连接还是已连接状态

public String bltStatus(int status) {
        String a = "未知状态";
        switch (status) {
            case BluetoothDevice.BOND_BONDING:
                a = "连接中";
                break;
            case BluetoothDevice.BOND_BONDED:
                a = "连接完成";
                break;
            case BluetoothDevice.BOND_NONE:
                a = "未连接/取消连接";
                break;
        }
        return a;
    }

14、蓝牙点击事件

包括蓝牙的打开,关闭,被搜索,断开连接

/**
     * 蓝牙操作事件
     *
     * @param context
     * @param status
     */
    public void clickBlt(Context context, int status) {
        switch (status) {
            case BltContant.BLUE_TOOTH_SEARTH://搜索蓝牙设备,在BroadcastReceiver显示结果
                startSearthBltDevice(context);
                break;
            case BltContant.BLUE_TOOTH_OPEN://本机蓝牙启用
                if (getmBluetoothAdapter() != null)
                    getmBluetoothAdapter().enable();//启用
                break;
            case BltContant.BLUE_TOOTH_CLOSE://本机蓝牙禁用
                if (getmBluetoothAdapter() != null)
                    getmBluetoothAdapter().disable();//禁用
                break;
            case BltContant.BLUE_TOOTH_MY_SEARTH://本机蓝牙可以在300s内被搜索到
                Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                context.startActivity(discoverableIntent);
                break;
            case BltContant.BLUE_TOOTH_CLEAR://本机蓝牙关闭当前连接
                try {
                    if (getmBluetoothSocket() != null)
                        getmBluetoothSocket().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

        到此,蓝牙从打开到连接的方法都写完了。最后我们来总结一下。

        当我们获得到了bluetoothsocket对象的时候,我们就可以像使用socket编程一样,让两个蓝牙之间传输数据。甚至可以在程序内部监听蓝牙耳机的暂停/播放/音量键等的点击事件。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BLE(低功耗)是一种通过无线技术进行低功耗通信的协议。它是在传统(Classic Bluetooth)的基础上发展而来,主要用于物联网、智能家居和健康追踪等领域。 BLE主要特点有以下几个方面: 1. 低功耗:BLE采用了一种优化的通信方式,使设备在通信过程中的功耗大大降低,从而延长了设备的电池寿命,这对于需要长时间运行的设备非常重要。 2. 简化传输:BLE使用了一种称为GATT(通用属性)的协议,将数据分为服务和特征,通过读、写或订阅操作来传输数据,这种简化了传输过程,减少了额外的开销。 3. 快速连接BLE连接速度比传统更快,可以在几十毫秒内建立连接,这对于移动设备和传感器等需要快速响应的设备非常重要。 4. 多设备连接BLE支持同时连接多个设备,可以通过同一个移动设备与多个BLE设备进行通信,提高了系统的灵活性和可扩展性。 Android提供了一套完整的BLE开发API,开发者可以使用这些API来实现BLE通信功能。在Android中,开发BLE应用涉及到四个主要组件:BLE设备扫描、设备连接、数据传输和GATT服务管理。 开发者可以使用Android的BluetoothAdapter类来进行设备扫描和连接操作,可以通过BluetoothGatt类来进行GATT服务的操作,包括读、写、订阅等。 总之,BLE作为一种低功耗的通信协议,在物联网和智能设备领域应用广泛。在Android平台上进行BLE开发,可以借助Android提供的API,快速实现BLE通信功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值