Android蓝牙实现设备间数据传输

Android上的蓝牙文件传输:跨设备无缝共享 由于蓝牙技术应用广泛且方便,它已成为日常生活的必备工具。它为Android设备和 PC 传输文件提供了一种实用的方法。Android智能手机之间以及Android设备与PC之间可以实现高效的文件传输。对于那些寻求更快、更可靠的传输选项的人来说 Coolmuster Android Assistant 是一个强有力的替代品。除了提供多种用于快速文件传输的连接选择之外,它还允许用户管理Android智能手机上的数据和应用程序。对于Android来说,它是蓝牙文件传输的可靠替代品。立即尝试一下。 阅读详情

这篇文章总结通过蓝牙实现两台pad间数据传输

文章基于传统蓝牙,而不是BLE。
蓝牙应该是移动设备经常用到的功能模块,Android Bluetooth API 是Android提供的用来实现点到点和多点无线功能。
使用 Bluetooth API,Android 应用可执行以下操作:

  • 扫描其他蓝牙设备
  • 查询本地蓝牙适配器的配对蓝牙设备
  • 建立 RFCOMM 通道
  • 通过服务发现连接到其他设备
  • 与其他设备进行双向数据传输
  • 管理多个连接

蓝牙权限

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

1.设置蓝牙

您需要验证设备支持蓝牙,并且如果支持确保将其启用,然后您的应用才能通过蓝牙进行通信。

  • 获取 BluetoothAdapter
    所有蓝牙 Activity 都需要 BluetoothAdapter。

    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBluetoothAdapter == null) {
    // Device does not support Bluetooth
    }
  • 启用蓝牙
    下一步,您需要确保已启用蓝牙。

    if (!mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
    }

2.搜索蓝牙设备

要开始发现设备,只需调用 startDiscovery()。该进程为异步进程,并且该方法会立即返回一个布尔值,指示是否已成功启动发现操作。 发现进程通常包含约 12 秒钟的查询扫描,之后对每台发现的设备进行页面扫描,以检索其蓝牙名称。

/**
     * 发现蓝牙的广播
     */
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(action)){
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                //todo处理搜索到的蓝牙设备
            }
        }
    };

在Activity或者Fragment中注册广播

        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver, filter);

3.连接设备

要在两台设备上的应用之间创建连接,必须同时实现服务器端和客户端机制,因为其中一台设备必须开放服务器套接字,而另一台设备必须发起连接(使用服务器设备的 MAC 地址发起连接)。
服务器设备和客户端设备分别以不同的方法获得需要的 BluetoothSocket。服务器将在传入连接被接受时收到套接字。 客户端将在其打开到服务器的 RFCOMM 通道时收到该套接字。

注:如果两台设备之前尚未配对,则在连接过程中,Android 框架会自动向用户显示配对请求通知或对话框。因此,在尝试连接设备时,您的应用无需担心设备是否已配对。 您的 RFCOMM 连接尝试将被阻塞,直至用户成功完成配对或配对失败(包括用户拒绝配对、配对失败或超时)。

  • 连接为服务器
    当您需要连接两台设备时,其中一台设备必须通过保持开放的 BluetoothServerSocket 来充当服务器。
    • 1.通过调用 listenUsingRfcommWithServiceRecord(String, UUID) 获取 BluetoothServerSocket。
      当客户端尝试连接此设备时,它会携带能够唯一标识其想要连接的服务的 UUID。 两个 UUID 必须匹配,在下一步中,连接才会被接受。
    • 通过调用 accept() 开始侦听连接请求。
    • 除非您想要接受更多连接,否则请调用 close()。
      这将释放服务器套接字及其所有资源,但不会关闭 accept() 所返回的已连接的 BluetoothSocket。 与 TCP/IP 不同,RFCOMM 一次只允许每个通道有一个已连接的客户端,因此大多数情况下,在接受已连接的套接字后立即在 BluetoothServerSocket 上调用 close() 是行得通的。

以下是一个用于接受传入连接的服务器组件的简化线程:

private class AcceptThread extends Thread {
   
   
    private final BluetoothServerSocket mmServerSocket;

    public AcceptThread() {
        // Use a temporary object that is later assigned to mmServerSocket,
        // because mmServerSocket is final
        BluetoothServerSocket tmp = null;
        try {
            // MY_UUID is the app's UUID string, also used by the client code
            tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
        } catch (IOException e) { }
        mmServerSocket = tmp;
    }

    public void run() {
        BluetoothSocket socket = null;
        // Keep listening until exception occurs or a socket is returned
        while (true) {
            try {
                socket = mmServerSocket.accept();
            } catch (IOException e) {
                break;
            }
            // If a connection was accepted
            if (socket != null) {
                // Do work to manage the connection (in a separate thread)
                manageConnectedSocket(socket);
                mmServerSocket.close();
                break;
            }
        }
    }

    /** Will cancel the listening socket, and cause the thread to finish */
    public void cancel() {
        try {
            mmServerSocket.close();
        } catch (IOException e) { }
    }
}

注意上面是简化线程,也是网上搜索到最多的方法。但是其稳定性真的很差劲。

  • 连接为客户端
    要发起与远程设备(保持开放的服务器套接字的设备)的连接,必须首先获取表示该远程设备的 BluetoothDevice 对象。(在前面有关查找设备的部分介绍了如何获取 BluetoothDevice)。 然后必须使用 BluetoothDevice 来获取 BluetoothSocket 并发起连接。
    • 1.使用 BluetoothDevice,通过调用 createRfcommSocketToServiceRecord(UUID) 获取 BluetoothSocket。
    • 2.通过调用 connect() 发起连接。

以下是发起蓝牙连接的线程的基本示例:

private class ConnectThread extends Thread {
   
   
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;

    public ConnectThread(BluetoothDevice device) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        mmDevice = device;

        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app's UUID string, also used by the server code
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) { }
        mmSocket = tmp;
    }

    public void run() {
        // Cancel discovery because it will slow down the connection
        mBluetoothAdapter.cancelDiscovery();

        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and get out
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;
        }

        // Do work to manage the connection (in a separate thread)
        manageConnectedSocket(mmSocket);
    }

    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}

代码很容易看懂,就不做过多解释了。


4.管理连接

在成功连接两台(或更多台)设备后,每台设备都会有一个已连接的 BluetoothSocket。 这一点非常有趣,因为这表示您可以在设备之间共享数据。 利用 BluetoothSocket,传输任意数据的一般过程非常简单:

  • 获取 InputStream 和 OutputStream,二者分别通过套接字以及 getInputStream() 和 getOutputStream() 来处理数据传输。
  • 使用 read(byte[]) 和 write(byte[]) 读取数据并写入到流式传输。

ok,至此,我们基本了解了传统蓝牙数据传输常用的API以及一些核心API的使用,接下来具体看我在项目中如何处理数据传输以及解决蓝牙Socket的稳定性。
在了解了上面一套机制以后,最开始我也是使用上面的简单实例进行蓝牙数据的传输与接受,但在传输过程中经常会出现连接异常,Socket断开等各种异常。经过不断的寻找解决方案,最后发现了官方一个通过蓝牙进行设备聊天的demo,仔细研究发现主要是通过一个自己封装的BluetoothChatService,其内部本质还是使用的我们上面介绍的知识,只不过这个Service对连接的处理更详细。

public
Android T 蓝牙传输文件流程(一) Android T 蓝牙 Opp 流程 阅读详情

相关推荐

蓝牙 GATT 协议及其在 Android 的实现

蓝牙 GATT(Generic Attribute Profile,通用属性配置文件)是基于低功耗蓝牙(Bluetooth Low Energy, BLE)的一个重要协议,用于定义如何在设备之间传输数据。它是 BLE 的核心协议之一,广泛应用于智能手环、蓝牙传感器等 IoT 设备。蓝牙GATT协议在低功耗蓝牙通信中至关重要。Android BLE 实现提供了丰富的接口,可以灵活实现扫描、连接、数据交互等功能。开发过程中需重点关注设备兼容性权限及通信稳定性。

weixin_44780781的博客 3747

Android 蓝牙BLE连接、广播、数据传输流程分析

android-蓝牙A2dp-avrcp-hfp-opp-配对流程-ble-rfcomm源码流程 Android 蓝牙低功耗ble 广播、扫描、连接、数据读写源码流程分析大全 - 点击下载 如今的社会已经从IT时代过渡到了DT时代,数据的重要性不言而喻。将数据安全快速的传输给对方是一件非常重要的事情,如今诞生了很多不同的传输技术,每一种传输技术都是为了和对方进行数据交互。BLE技术也是这样,它的最终目的就是为了在两个设备间进行数据交互。我们从BLE的本质出发,搞清楚它是如何实现数据交互的,也就真...

手机-手表蓝牙开发工程师的博客 1万+

Android蓝牙UUID通信实战指南

在现代移动应用开发中,蓝牙技术的集成使得设备间的无线通讯成为可能,为开发者提供了丰富的机会来创造全新的用户体验。Android平台,作为移动领域的重要组成部分,为蓝牙通信提供了强大的API支持。通过这些API,开发者能够实现从基础的蓝牙设备扫描、配对、连接建立到高级的数据传输和断开连接等全过程控制。Android蓝牙API不仅包括了传统的蓝牙操作,还涵盖了BLE(蓝牙低功耗)技术的使用,这意味着开发者可以更灵活地设计应用,无论是与健康监测设备的数据交换,还是与智能家居设备的无缝链接。

weixin_42527589的博客 1907

如何安装PyFluent

PyFluent 是PyAnsys生态系统的一部分, 允许您在所选的 Python 环境中结合使用 Fluent 与其他 PyAnsys 库和外部 Python 库一起使用。PyFluent 实现了客户端-服务器体系结构。它使用谷歌遥控器 过程调用或 gRPC 接口,用于启动或连接正在运行的 Fluent 进程作为服务器。但是,您只需要与 Python 交互接口。可以使用 PyFluent 以编程方式创建、交互和控制 Fluent 会话,用于创建您自己的自定义工作区。

B_etter_Man的博客 2913

✨使用 vLLM + Docker 部署 Qwen3-Embedding-8B 并实现高效文本向量生成(附 `curl` 测试)

本文介绍了如何使用 vLLM 和 Docker 部署 Qwen3-Embedding-8B 嵌入模型服务,并通过标准 OpenAI 兼容接口进行调用和结果解析。如果你在部署中遇到任何问题,欢迎留言讨论!

用大模型重构生活:猫奴程序员的AI智能日常记录 6236

保姆级教程:用Python+OpenCV实现相移法与格雷码三维重建(从生成条纹到点云生成)

本文详细介绍了使用Python和OpenCV实现相移法与格雷码三维重建的全流程,从条纹生成到点云计算。通过结构光技术,结合相移法和格雷码,实现高精度的三维重建,适用于无纹理物体表面的密集对应点生成。教程包含环境搭建、条纹生成、相位计算、三维点云重建及常见问题排查,适合计算机视觉开发者和研究人员。

weixin_33443333的博客 349

万达电影 com.wandafilm.app headers check

万达电影 安卓逆向 抓包 逆向 check

weixin_43786514的博客 1436

Axure RP 10表单数据提交制作

本文介绍了如何使用Axure RP 10实现表单数据提交。

Peppaaa的博客 989

告别手绘!用Aseprite+Unity Tilemap,从AI生成到2D游戏地图的保姆级搭建流程

本文详细介绍了如何利用Aseprite和Unity Tilemap从AI生成素材到搭建2D游戏地图的完整流程。涵盖AI生成素材的预处理、图层管理、动画制作,以及Unity中的Tilemap系统配置和性能优化技巧,帮助开发者高效创建像素风游戏地图。

weixin_29015483的博客 580

LangChain Message 官方文档

消息是聊天模型中的基本通信单位。它们用于表示聊天模型的输入和输出,以及与对话相关的其他上下文或元数据。每条消息都包含一个角色(如“用户”、“助手”)和内容(如文本或多模态数据),并可能包含根据不同聊天模型提供商而有所不同的附加元数据。LangChain 提供了一个统一的消息格式,可以跨不同聊天模型使用,简化用户在不同模型之间切换时所需关注的消息格式差异。

AI Agent 首席体验官 896

微信小程序中蓝牙打印机中文编码处理:使用iconv-lite库

本文介绍了微信小程序集成蓝牙打印机时中文乱码问题的解决方案。由于打印机通常仅支持GBK/GB2312编码,而小程序使用UTF-8,导致中文显示异常。通过引入轻量级iconv-lite库进行编码转换,可高效解决该问题。文章详细说明了从库安装、编码转换到蓝牙发送的实现步骤,并提供了完整代码示例。关键注意事项包括编码验证、分段发送和兼容性测试。该方法经实际验证,能有效保障中文打印的准确性,适用于零售、物流等场景。

canglingyue的专栏 1308

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: rxjava系列(三)-- rxjava在Android中的应用
下一篇: Android 自动更新Apk组件封装
mo_android
博客等级 码龄9年 12粉丝 12原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值