android 8.1 蓝牙开发 静默开启蓝牙 将蓝牙暴露给其他蓝牙设备 扫描蓝牙设备 静默配对 建联相互通信

android 8.1 蓝牙开发 静默开启蓝牙 将蓝牙暴露给其他蓝牙设备 扫描蓝牙设备 静默配对 建联相互通信

阿。 第一次接触蓝牙开发 还是一头雾水的 不过还好经过2天时间 调试好了蓝牙的基本功能 暴露设备 扫描 配对 连接 收发消息等等。。 嗯。。 这几天在网上搜了很多关于蓝牙的帖子 大部分 都是没有将重点问题 暴露出来 解析 和 解决 使我开发及其难受 开发中我就决定 自己解决好问题 要发一篇贴子 没错 再弄蓝牙的你看到这里是值得庆幸的 因为你找到了答案,哈哈(android 8.1 系统 默认14蓝牙版本) 当然在其他版本的问题也是有可能没遇到的,哈哈 不装逼了 开始公布答案

  1. 我长话短说哈,添加 蓝牙相关的权限,要启用蓝牙 是依赖这个定位权限的 一定要加上
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />

这里重点说一下哈, 这个权限

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

是为了做静默配对,需要添加的,注意 这个权限普通第三方程序添加了也没有 必须要有系统权限才行
添加 android:sharedUserId=“android.uid.system” 用系统签名才行 当然如果说你不做静默配对 这个就不需要了
因为我是追求完美的人,所以我是必须要静默的 , O(∩_∩)O哈哈~

获取蓝牙适配器

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

2.开启蓝牙 这里有两种方式 第一种


```java
/**
     * 打开设备蓝牙
     *
     * @return
     */
    public BluetoothClient openBluetooth() {
        if (!hasBluetooth()) return mBluetoothClient;
        if (!mBluetoothAdapter.isEnabled()) {
            boolean enable = mBluetoothAdapter.enable();
            if(enable)
                Toast.makeText(mContext, "蓝牙打开成功", Toast.LENGTH_SHORT).show();
            else
                Toast.makeText(mContext, "蓝牙打开失败", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(mContext, "蓝牙已打开", Toast.LENGTH_SHORT).show();
        }
        return mBluetoothClient;
    }

第二种方式。。

 Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
 startActivityForResult(intent,1);

第二种方式是有弹窗的 我是更喜欢第一种



3.蓝牙开启了   接下来就是扫描蓝牙设备了,  我一开始以为蓝牙开启后   就能被蓝牙设备发现,    后来发现这玩意tm 的还得暴露给别人
你穿着衣服别人看不见,你必须得脱掉才能看得见。明白了吗。emmm....

```java
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
startActivityForResult(discoverableIntent,0);

我这里是设置的暴露300秒, 这个数值应该是有个上限好像 我记得是3600,有点记不清了 没有细研究 因为这个问题不大,因为300 秒后我还可以在发起一次。

4扫描

   // 开始搜索
        mBluetoothAdapter.startDiscovery();

方法执行后扫描到设备将以广播形式,接收所以需要注册广播

/**
     * 注册接受搜索到的蓝牙设备广播
     */
    public void regiestReceiver() {
        mBluetoothReceiver = new BluetoothReceiver();
        IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(mBluetoothReceiver, intentFilter);
    }
/**
     * 搜索设备和配对状态改变广播
     */
    class BluetoothReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND == action) { // 找到设备
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                Message message = Message.obtain();
                message.what = MSG_WHAT_FOUND_DEVICE;
                message.obj = device;
                mHandler.sendMessage(message);
                Toast.makeText(mContext, "找到设备" + device.getName(), Toast.LENGTH_SHORT).show();
                try{
                    if(device.getName().contains("ZL809") || device.getName().contains("zzy-edu-m1")) // 这里是做了蓝牙名称匹配(静默匹配)
                    {
                        if (device.getBondState() == BluetoothDevice.BOND_NONE) {
                            try {
                                device.createBond();// 发起匹配(静默匹配)
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }catch (Exception e){

                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) {
                mHandler.sendEmptyMessage(MSG_WHAT_FINISHED_SEARCH);
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED == action) { 
                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
                switch (state) {
                    case BluetoothDevice.BOND_NONE:
                        mHandler.sendEmptyMessage(MSG_WHAT_BOND_NONE);
                        Logger.d("BOND_NONE 删除配对");
                        break;
                    case BluetoothDevice.BOND_BONDING:
                        mHandler.sendEmptyMessage(MSG_WHAT_BOND_BONDING);
                        Logger.d("BOND_BONDING 正在配对");
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        mHandler.sendEmptyMessage(MSG_WHAT_BOND_BONDED);
                        Logger.d("BOND_BONDED 配对成功");
                        break;
                }
            }else if(action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)){
                try{
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if(device.getName().contains("ZL809") || device.getName().contains("zzy-edu-m1"))
                    {
                        abortBroadcast();//拦截广播,为了阻止弹窗
                        int pin = intent.getIntExtra("android.bluetooth.device.extra.PAIRING_KEY", 1234);
                        device.setPin((""+pin).getBytes());
                        device.setPairingConfirmation(true);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

代码中根据扫描到的设备名称进行匹配自己想要连接的设备,进行静默配对 不做静默的可以去掉 手动确认匹配也是ok的

5 连接通信 完成前面的工作 通信就简单了
两个蓝牙设备通信,即 服务端,客户端 这里注意 一方发起连接请求之前另一方要先开启服务等待连接请求 这里和socket开发很像 几乎就是socket开发了

服务端

mBluetoothServerSocket= mBluetoothAdapter.listenUsingRfcommWithServiceRecord(
                            Constants.NAME_SECURE, Constants.MY_UUID_SECURE);
bluetoothSocket = mBluetoothServerSocket.accept();

等待客户端接入,当有蓝牙连接后 通过输入输出流 交互数据

@Override
        public void onAccept(BluetoothSocket bluetoothSocket) {
            try {
                InputStream inputStream = bluetoothSocket.getInputStream();
                outputStream = bluetoothSocket.getOutputStream();
                while (true) {
                    byte[] bytes = new byte[1024];
                    inputStream.read(bytes);
                    String s = new String(bytes, 0, bytes.length);
                    chatContent.add("B" + s);
                    handler.sendEmptyMessage(MSG_UPDATE_UI);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

客户端

 mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(Constants.MY_UUID_SECURE);
 if (!mBluetoothSocket.isConnected())
                    mBluetoothSocket.connect();

要注意连接过程要在子线程

 /**
     * 读取和发送的线程
     */
    class ReadWriteThread extends Thread {
        OutputStream outputStream;
        InputStream inputStream;

        public ReadWriteThread(BluetoothSocket bluetoothSocket) {
            try {
                this.outputStream = bluetoothSocket.getOutputStream();
                this.inputStream = bluetoothSocket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            if (inputStream != null) {
                while (true) {
                    try {
                        byte[] bytes = new byte[1024];
                        inputStream.read(bytes);
                        chatContent.add("B" + new String(bytes, 0, bytes.length));
                        handler.sendEmptyMessage(MSG_UPDATE_UI);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        public void sendMessage(String message) {
            if (outputStream != null) {
                try {
                    outputStream.write(message.getBytes());
                    chatContent.add("A" + message);
                    handler.sendEmptyMessage(MSG_UPDATE_UI);
                    handler.sendEmptyMessage(MSG_CLEAR_EDITTEXT);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

后续更新个demo 吧 等几天哈

2023-06-30 更新
抱歉让我给忘记了 今天更新一下demo

 class BluetoothReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND == action) { // 找到设备
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                Message message = Message.obtain();
                message.what = MSG_WHAT_FOUND_DEVICE;
                message.obj = device;
                mHandler.sendMessage(message);
                Toast.makeText(mContext, "找到设备" + device.getName(), Toast.LENGTH_SHORT).show();
                try{
                    if(device.getName().contains("ZL809") || device.getName().contains("zzy-edu-m1"))
                    {
                        if (device.getBondState() == BluetoothDevice.BOND_NONE) {
                            try {
                                device.createBond();
                            } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                }catch (Exception e){

                }
            }

需要注意调试时要换成自己的设备名称或者将过滤条件注释掉 (ZL809,zzy-edu-m1)
if(device.getName().contains(“ZL809”) || device.getName().contains(“zzy-edu-m1”))

下载地址 MyBlueToothSerialPort

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百思不得姐1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值