Android 蓝牙技术 实现终端间数据传输

本文涉及的产品
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 1个月
简介:

蓝牙技术在智能硬件方面有很多用武之地,今天我就为大家分享一下蓝牙技术在Android系统下的使用方法技巧。蓝牙是一种短距离的无线通信技术标准,蓝牙协议分为4层,即核心协议层、电缆替代协议层、电话控制协议层和采纳的其它协议层。这4种协议中最重要的是核心协议。蓝牙的核心协议包括基带、链路管理、逻辑链路控制和适应协议四部分。其中链路管理(LMP)负责蓝牙组件间连接的建立。逻辑链路控制与适应协议(L2CAP)位于基带协议层上,属于数据链路层,是一个为高层传输和应用层协议屏蔽基带协议的适配协议。

Android 支持的蓝牙协议栈有:

蓝牙协议栈 说明
Bluz Linux官方蓝牙协议栈,最成熟的开源蓝牙协议栈,灵活高效。
BlueDroid 从Android 4.2开始,Google在Android中推出了它和博通公司一起开发的BlueDroid以替代BlueZ,框架结构变得更为简洁和清晰。
BLE 低功耗蓝牙协议栈,传输距离远,速率快。

1.Android系统蓝牙本地操作

Android 系统本地蓝牙代表本地的蓝牙适配器,也是所有蓝牙交互的入口点,可以对本地或者其他终端设备进行操作。其中 BluetoothAdapter 是重要的类,代表本地蓝牙适配器。

1.判断本地蓝牙是否打开

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // null:表示不支持蓝牙
boolean enabled = mBluetoothAdapter.isEnabled(); // true:处于打开状态, false:处于关闭状态

2.调用系统对话框启动本地蓝牙

// 添加蓝牙权限,不需要动态授权
// <uses-permission android:name="android.permission.BLUETOOTH" />
// <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);

3.静默开启本地蓝牙 不会有对话框

在AndroidManifest文件中添加需要的权限:

<!-- 适配Android6.0/7.0 -->
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  • 1

由于蓝牙所需要的权限包含Dangerous Permissions,所以我们需要在Java代码中进行动态授权处理:

if (ContextCompat.checkSelfPermission(context,
        Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(context,
            new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
  • 1

接下来我们就可以静默开启和关闭本地蓝牙了:

mBluetoothAdapter.enable(); // 开启
//mBluetoothAdapter.disable(); // 关闭

4.本地蓝牙主动搜索周边蓝牙

搜索分为主动搜索和被动搜索。我们开始进行主动搜索:

1.创建 BluetoothAdapter 对象,首先获取已经配对的蓝牙设备:

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices(); // 获取已经配对的蓝牙设备
  • 1

2.下面我们定义广播接收器

// 设置广播信息过滤
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);//每搜索到一个设备就会发送一个该广播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//当全部搜索完后发送该广播
filter.setPriority(Integer.MAX_VALUE);//设置优先级 // 注册蓝牙搜索广播接收者,接收并处理搜索结果 this.registerReceiver(receiver, filter);

3.开始搜索周边蓝牙:

//如果当前在搜索,就先取消搜索
if (mBluetoothAdapter.isDiscovering()) {
    mBluetoothAdapter.cancelDiscovery();
}
//开启搜索
mBluetoothAdapter.startDiscovery();

搜索蓝牙设备

2.Android系统蓝牙远程操作

1.蓝牙的UUID

两个蓝牙设备进行连接时需要使用同一个UUID。但很多读者可能发现,有很多型号的手机(可能是非Android系统的手机)之间使用了不同的程序也可以使用蓝牙进行通讯。从表面上看,它们之间几乎不可能使用同一个UUID。

UUID的格式如下:

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

UUID的格式被分成5段,其中中间3段的字符数相同,都是4,第1段是8个字符,最后一段是12个字符。所以UUID实际上是一个8-4-4-4-12的字符串。

实际上,UUID和TCP的端口一样,也有一些默认的值。例如,将蓝牙模拟成串口的服务就使用了一个标准的UUID:

00001101-0000-1000-8000-00805F9B34FB

除此之外,还有很多标准的UUID,如下面就是两个标准的UUID:

信息同步服务:00001104-0000-1000-8000-00805F9B34FB
文件传输服务:00001106-0000-1000-8000-00805F9B34FB

2.本地蓝牙与周边蓝牙间数据传输

通过蓝牙传输数据与Socket类似。在网络中使用Socket和ServerSocket控制客户端和服务端的数据读写。而蓝牙通讯也由客户端和服务端Socket来完成。蓝牙客户端Socket是BluetoothSocket,蓝牙服务端Socket是BluetoothServerSocket。这两个类都在android.bluetooth包中。

无论是BluetoothSocket,还是BluetoothServerSocket,都需要一个UUID(全局唯一标识符,Universally Unique Identifier),UUID相当于Socket的端口,而蓝牙地址相当于Socket的IP。

我们开始进行模拟一个蓝牙数据的传输:

首先来看客户端:

(1)定义全局常量变量

private ListView lvDevices;
private BluetoothAdapter mBluetoothAdapter;
private List<String> bluetoothDevices = new ArrayList<String>();
private ArrayAdapter<String> arrayAdapter; private final UUID MY_UUID = UUID .fromString("abcd1234-ab12-ab12-ab12-abcdef123456");//随便定义一个 private BluetoothSocket clientSocket; private BluetoothDevice device; private OutputStream os;//输出流
  • 1

(2)在onCreate方法中做初始化操作

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

lvDevices = (ListView) findViewById(R.id.lv_devices);
//获取已经配对的蓝牙设备
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
    for (BluetoothDevice device : pairedDevices) {
        bluetoothDevices.add(device.getName() + ":"+ device.getAddress()); } } arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1,bluetoothDevices); lvDevices.setAdapter(arrayAdapter); lvDevices.setOnItemClickListener(this);//Activity实现OnItemClickListener接口 //每搜索到一个设备就会发送一个该广播 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(receiver, filter); //当全部搜索完后发送该广播 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(receiver, filter);
  • 1

蓝牙设备的广播接收器如下:

/**
 * 定义广播接收器
 */
private final BroadcastReceiver receiver = 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); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { bluetoothDevices.add(device.getName() + ":" + device.getAddress()); arrayAdapter.notifyDataSetChanged();//更新适配器 } } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //已搜素完成 } } };

(4)我们创建一个Button按钮,当点击Button时进行搜索,Button点击事件如下:

//如果当前在搜索,就先取消搜索
if (mBluetoothAdapter.isDiscovering()) {
    mBluetoothAdapter.cancelDiscovery();
}
//开启搜索
mBluetoothAdapter.startDiscovery();
  • 1

(5)接下来我们设置列表的点击事件:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { String s = arrayAdapter.getItem(position); String address = s.substring(s.indexOf(":") + 1).trim();//把地址解析出来 //主动连接蓝牙服务端 try { //判断当前是否正在搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } try { if (device == null) { //获得远程设备 device = mBluetoothAdapter.getRemoteDevice(address); } if (clientSocket == null) { //创建客户端蓝牙Socket clientSocket = device.createRfcommSocketToServiceRecord(MY_UUID); //开始连接蓝牙,如果没有配对则弹出对话框提示我们进行配对 clientSocket.connect(); //获得输出流(客户端指向服务端输出文本) os = clientSocket.getOutputStream(); } } catch (Exception e) { } if (os != null) { //往服务端写信息 os.write("蓝牙信息来了".getBytes("utf-8")); } } catch (Exception e) { } }

(2)定义服务端线程类:

private Handler handler = new Handler() {
    public void handleMessage(Message msg) { Toast.makeText(getApplicationContext(), String.valueOf(msg.obj), Toast.LENGTH_LONG).show(); super.handleMessage(msg); } }; //服务端监听客户端的线程类 private class AcceptThread extends Thread { public AcceptThread() { try { serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (Exception e) { } } public void run() { try { socket = serverSocket.accept(); is = socket.getInputStream(); while(true) { byte[] buffer =new byte[1024]; int count = is.read(buffer); Message msg = new Message(); msg.obj = new String(buffer, 0, count, "utf-8"); handler.sendMessage(msg); } } catch (Exception e) { } } }

(3)在onCreate方法中初始化线程类并开启

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
acceptThread = new AcceptThread();
acceptThread.start();
  • 1
  • 2
  • 3

我们运行程序看一下效果图:

client

点击“搜索蓝牙设备”按钮,就会搜索到另一台手机的蓝牙信息,我们点击条目,另一台手机会出现如下变化:

server

弹出Toast,此时证明我们的蓝牙数据已经传输过来了。


    本文转自 一点点征服   博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/6945155.html,如需转载请自行联系原作者


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
相关文章
|
1月前
|
XML 存储 JSON
51. 【Android教程】JSON 数据解析
51. 【Android教程】JSON 数据解析
46 2
|
2天前
|
开发工具 Android开发 数据安全/隐私保护
探索iOS与安卓应用开发的异同:技术、工具和市场趋势
在移动操作系统的广阔舞台上,iOS和安卓两大主角各自演绎着怎样的精彩?本文将深入剖析这两大平台在应用开发过程中的技术差异、开发工具的选择以及面对的市场环境。通过数据支撑和案例分析,我们将一窥这两个系统如何影响开发者的决策,并探讨它们未来的发展方向。
|
5天前
|
存储 缓存 Java
Android性能优化:内存管理与LeakCanary技术详解
【7月更文挑战第21天】内存管理是Android性能优化的关键部分,而LeakCanary则是进行内存泄漏检测和修复的强大工具。
|
23天前
|
机器学习/深度学习 人工智能 文字识别
文本,文字扫描01,OCR文本识别技术展示,一个安卓App,一个简单的设计,文字识别可以应用于人工智能,机器学习,车牌识别,身份证识别,银行卡识别,PaddleOCR+SpringBoot+Andr
文本,文字扫描01,OCR文本识别技术展示,一个安卓App,一个简单的设计,文字识别可以应用于人工智能,机器学习,车牌识别,身份证识别,银行卡识别,PaddleOCR+SpringBoot+Andr
|
1月前
|
Android开发
技术经验分享:Android前后台切换的监听
技术经验分享:Android前后台切换的监听
19 2
|
1月前
|
安全 vr&ar Python
【计算巢】光纤通信技术:高速数据传输的未来
【6月更文挑战第1天】光纤通信技术在数据传输中扮演金牌角色,速度极快,带宽宽,信号衰减小,抗干扰强。简单Python代码示例展示了其应用魅力,它是高清流媒体、远程医疗等领域的关键。作为数字世界的关键动力,光纤通信技术开启高速传输大门,引领未来发展方向。一起探索这个充满潜力的光纤通信世界吧!
【计算巢】光纤通信技术:高速数据传输的未来
|
17天前
|
安全 搜索推荐 Android开发
安卓与iOS的较量:技术深度与用户体验的博弈
在数字时代的浪潮中,安卓与iOS两大操作系统如同巨人般主宰着移动设备的生态。本文将深入探讨这两大系统在技术架构、安全性、应用生态和用户体验等方面的差异,并结合最新的市场数据和技术发展动态,为读者呈现一个全面而深入的分析视角。我们将看到,尽管安卓以其开放性和高度可定制性赢得了广泛的市场份额,iOS则以其卓越的用户体验和强大的品牌忠诚度构建了坚固的护城河。两者的竞争不仅推动了技术的快速进步,也不断塑造着我们对智能手机的期待和想象。
|
25天前
|
5G Android开发 iOS开发
探索iOS与安卓在移动操作系统领域的技术竞争与合作
本文将深入探讨iOS和安卓这两大移动操作系统的技术竞争与合作。通过对市场份额、用户忠诚度、技术创新、生态系统建设以及安全性等方面的比较,我们将揭示这两个系统各自的优势和挑战。同时,我们还将分析它们如何通过技术合作来推动整个移动行业的发展。
|
1月前
|
JSON 编解码 Apache
Android中使用HttpURLConnection实现GET POST JSON数据与下载图片
Android中使用HttpURLConnection实现GET POST JSON数据与下载图片
23 1
|
29天前
|
算法 安全 Android开发
新一代安卓系统:技术演进与用户体验革新
在移动操作系统领域,安卓系统一直处于不断演进的过程中。本文探讨了新一代安卓系统的技术创新,以及这些创新如何为用户带来全新的体验和功能。
18 0