Android与蓝牙串口通信

本app只能在android的日志查看蓝牙发送的数据,可自己改进。但是在使用前,确保你所连接的蓝牙已配对

在AndroidManifest.xml我们还需导入以下权限:

<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- 在Android 10以上还需要 -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 唤醒锁权限,防止后台被杀。 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- 读取蓝牙UUID权限。 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 蓝牙连接权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> 
<!-- 蓝牙检测权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

在MainActivity引用以下包:

import static java.lang.Thread.sleep;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;

在MainActivity定义如下参数:

    public static BluetoothAdapter mBluetoothAdapter;        // 蓝牙实例
    private static final int REQUEST_BLUETOOTH_CONNECT = 1;  // 蓝牙权限码
    public static InputStream inputStream;                   // 蓝牙通信输入流
    public static OutputStream outputStream;                 // 蓝牙通信输出流
    public static boolean Bluetooth_flag = false;            // 当前蓝牙连接状态
    public static BluetoothSocket socket = null;             // 蓝牙socket连接实例
    public static Thread Blue_Thread=null,connect_thread;    // 蓝牙获取信息线程 蓝牙连接线程

对于android14来说需要去检测权限是否开启以及初始化:

    // 用于告诉Android的Lint工具忽略缺少权限声明的警告 
    @SuppressLint("MissingPermission")
    public void Initpermission() {    // 初始化蓝牙权限
        // 获取系统默认的蓝牙适配器
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        // 记录当前的状态
        Log.d( "Blue_tooth", "蓝牙正在连接0" );
        // 创建一个意图(Intent),用于请求用户开启蓝牙
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        // 使用startActivityForResult方法启动一个新的活动(Activity),并请求用户开启蓝牙。这里的100是一个请求码,用于在请求完成后识别结果
        startActivityForResult(enableBtIntent, 100);
        // 用于连接到蓝牙设备
        connectToBluetoothDevice();
    }

连接蓝牙的代码:

@SuppressLint("MissingPermission") // 忽略缺少权限的警告
private static void connectToBluetoothDevice() {
    // 创建一个新的线程来处理蓝牙连接
    connect_thread = new Thread(() -> {
        Log.d("Blue_tooth", "蓝牙正在连接"); // 记录日志,表示蓝牙连接正在进行

        // 检查socket是否已经存在
        if (socket != null) {
            // 如果socket已经存在,但未连接,且Blue_Thread线程存在
            if (!socket.isConnected() && Blue_Thread != null) {
                Blue_Thread.stop(); // 停止Blue_Thread线程
                Bluetooth_flag = true; // 设置标志位,表示蓝牙连接尝试正在进行
            }
        } else {
            // 如果socket不存在,设置HC05蓝牙模块的MAC地址
            String hc05MacAddress = "98:D3:61:F7:0F:46"; // 替换为HC05的MAC地址
            // 通过MAC地址获取蓝牙设备对象
            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(hc05MacAddress);
            try {
                // 创建RFCOMM(串行端口)类型的socket并连接
                socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"));
                socket.connect(); // 连接socket
                inputStream = socket.getInputStream(); // 获取输入流
                outputStream = socket.getOutputStream(); // 获取输出流

                // 调用Bule_hread()方法,可能是一个拼写错误,应该是Blue_thread
                Bule_hread();
                Blue_Thread.start(); // 启动Blue_Thread线程
            } catch (IOException e) {
                e.printStackTrace(); // 打印异常信息
            }
        }
    });
    connect_thread.start(); // 启动连接线程
}

蓝牙连接成功后需要发送数据以及接收数据:

        

        发送数据部分:

public static void Blue_send(byte[] b) {
    // 检查socket是否已经存在
    if (socket != null) {
        // 如果socket已经存在,检查是否已经连接
        if (socket.isConnected()) {
            try {
                // 如果socket已经连接,通过输出流发送数据
                outputStream.write(b);
            } catch (IOException e) {
                // 如果在写入数据时发生IOException,设置Bluetooth_flag为false
                Bluetooth_flag = false;
                // 抛出一个RuntimeException,包含原始的IOException
                throw new RuntimeException(e);
            }
        } else {
            // 如果socket存在但未连接,尝试重新连接蓝牙设备
            connectToBluetoothDevice();
            // 记录日志,表示蓝牙未连接
            Log.d("Blue_tooth", "蓝牙未连接");
        }
    } else {
        // 如果socket不存在,尝试连接蓝牙设备
        connectToBluetoothDevice();
        // 记录日志,表示蓝牙未连接
        Log.d("Blue_tooth", "蓝牙未连接");
    }
}

        接收部分:

@SuppressLint("MissingPermission") // 忽略缺少权限的警告
public static void Bule_hread() {
    // 创建一个新的线程来处理蓝牙数据接收
    Blue_Thread = new Thread(() -> {
        byte[] buffer = new byte[1024]; // 创建一个1024字节的缓冲区来读取数据
        byte[] buffer1 = new byte[1024]; // 创建另一个1024字节的缓冲区来存储接收到的数据
        int bytes; // 用于存储每次读取的字节数
        int buffer1Index = 0; // 用于记录buffer1中的当前索引位置

        while (true) { // 无限循环,持续读取数据
            try {
                bytes = inputStream.read(buffer); // 从输入流中读取数据到buffer

                // 将读取到的数据追加到buffer1中
                System.arraycopy(buffer, 0, buffer1, buffer1Index, bytes);
                buffer1Index += bytes; // 更新buffer1中的索引位置

                // 处理接收到的数据
                if (buffer1Index >= 8) { // 如果接收到的数据达到8字节
                    String received = new String(buffer1, 0, 8); // 将前8字节数据转换为字符串
                    Log.d("Blue_tooth_data", received); // 记录日志,显示接收到的数据

                    buffer1Index = 0; // 重置buffer1的索引位置
                    Arrays.fill(buffer1, (byte) 0); // 清空buffer1
                    Arrays.fill(buffer, (byte) 0); // 清空buffer
                }

                try {
                    Thread.sleep(50); // 线程休眠50毫秒,减少CPU使用率
                } catch (InterruptedException e) {
                    throw new RuntimeException(e); // 如果线程被中断,抛出RuntimeException
                }

            } catch (IOException e) {
                connectToBluetoothDevice(); // 如果读取数据时发生IOException,尝试重新连接蓝牙设备
                e.printStackTrace(); // 打印异常信息
            }
        }
    });
    Blue_Thread.start(); // 启动Blue_Thread线程
}

在app退出,防止泄露或者其他原因,最好在同时清理回收参数以及各种资源:

@Override
    public void onDestroy() {
        super.onDestroy();
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (Bluetooth_flag) {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

至此,所有代码部分已经呈现,通信的波特率默认115200,在使用前查看自己蓝牙所用波特率,这份代码在连接蓝牙使用了一个线程,然后接收数据也用了一个线程,连接线程是为了防止在进入app界面,因为连接导致会出现白屏现象,虽然无所谓,但是不好看,接收线程是为了能一直接受,其实还能用其他方式写,比如Handle或者线程池,都能进行很好的优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值