Android 蓝牙技术 实现终端间数据传输
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
我们运行程序看一下效果图:
点击“搜索蓝牙设备”按钮,就会搜索到另一台手机的蓝牙信息,我们点击条目,另一台手机会出现如下变化:
弹出Toast,此时证明我们的蓝牙数据已经传输过来了。
Android 蓝牙技术 实现终端间数据传输相关推荐
- Android蓝牙技术+Demo
蓝牙技术 蓝牙(Bluetooth)是一种短距离的无线通信技术标准. 蓝牙的野史: 蓝牙的名字来源于10世纪丹麦国王Harald Blatand,英文名字是Harald Bluetooth,没错,这个 ...
- Android 蓝牙技术(一)- 经典蓝牙
Android平台支持蓝牙设备通过蓝牙协议栈来实现无线通信.应用层提供了Bluetooth APIs来使用蓝牙功能, 这些API可以使应用可以无线连接其他蓝牙设备实现点对点及多点间通信. 使用Blue ...
- android蓝牙设计与实现,一个Android客户端的蓝牙支付系统设计与实现
摘要: 本文实现了一种利用Android系统上的蓝牙技术,完成用户间资金流动的功能.本功能基于一个电子钱包客户端,本人希望以此来拓展电子钱包支付的途径,给用户提供一种新的便捷.安全的支付渠道.并希望借 ...
- Android蓝牙实现设备间数据传输
这篇文章总结通过蓝牙实现两台pad间数据传输 文章基于传统蓝牙,而不是BLE. 蓝牙应该是移动设备经常用到的功能模块,Android Bluetooth API 是Android提供的用来实现点到点和 ...
- Android BLE(低功耗蓝牙)技术总结
文章目录 前言 一.蓝牙介绍 1.什么是蓝牙? 2.蓝牙版本介绍 二.低功耗蓝牙(BLE) 1.BLE介绍 2.经典蓝牙(Classic Bluetooth)与低功耗蓝牙(BLE)的区别 3.低功耗蓝 ...
- Android BLE 低功耗蓝牙技术使用解析
什么是BLE BLE 全称为 Bluetooth low energy,意思是低功耗蓝牙. Android 4.3 (API 18)之后引入Ble. 最常用的Ble蓝牙技术是设备之间传输数据. And ...
- android 蓝牙低耗能(LBE)技术介绍
蓝牙低能耗(BLE)技术是低成本.短距离.可互操作的鲁棒性无线技术.工作在免许可的2.4GHz ISM射频频段.它从一開始就设计为超低功耗(ULP)无线技术. 它利用很多智能手段最大限度地减少功耗. ...
- android 音频双工,蓝牙技术实现半双工语音通信低能耗的方法都在这里
低能耗蓝牙被业界广泛认为是实现物联网(IoT)应用愿景的关键技术.事实上,极低的功耗使其成为电池供电的物联网产品最理想的无线通信解决方案,尽管目前低能耗蓝牙技术规范还是局限于几种特定应用,但是,创新的 ...
- Android中的蓝牙技术
随着智能化生活的发展,手机成为人们生活的必需品,而蓝牙技术也随之应运而生.蓝牙技术作为现代移动设备与设备之间传输数据的一种主流方式,已经广泛应用于手表.耳机.车载系统等多种设备.在Android设备中 ...
最新文章
- Python中常见的配置文件写法分享!
- 【渝粤题库】国家开放大学2021春2585城市轨道交通概论答案
- 在企业中使用的Silverlight:RAD数据通信用户友好的数据库访问
- Openssl更新步骤
- OpenResty之ngx.ssl
- 3月13 论文学习步骤:google的cartographer的论文《Real-Time Loop Closure in 2D LIDAR SLAM》
- 数值计算求解动态热传导方程
- 中国电信5G技术无线频率
- 乱世王者服务器维护,乱世王者微信541区风平浪静开服时间表_乱世王者新区开服预告_第一手游网手游开服表...
- 【3D激光SLAM(二)】Velodyne激光SLAM学习之Velodyne-16线激光雷达在Jetson Nano上的配置使用
- 如何从根本上防止服务器被攻击
- 2018.08.21 bzoj4668: 冷战(并查集+启发式合并)
- Mysql8.0.17压缩包安装——超详细简单教程
- 上海计算机协会-10月月赛-丙组-T5-组队竞赛
- Linux日志快速定位
- 托福、雅思、GRE、SAT、GMAT
- 九龙证券|次新股叠加智慧交通+信创+数字经济概念,开盘冲涨停!
- 一文读懂AI圣经,凡研究《深度学习》都知道的一本书!
- 【FFmpeg】没有平均fps,计算音视频 pkt duration
- 计算机中丢失dqdui d,dqd的含义,dqd是什么的缩写,dqd的词语,dqd代表的意思
热门文章
- 监控程序必须要放到服务器上进行吗?_五大最佳开源java性能监控工具,你知道几个?...
- tensorflow打印模型结构_五行代码用图提升模型表现,TensorFlow开源NSL神经结构学习框架...
- python以二进制读取的文件显示b'b'_python - Python读取二进制文件并解码 - 堆栈内存溢出...
- aes算法c语言实现_C语言实现常用数据结构:Dijkstra最短路径算法(第18篇)
- linux6.5配置ssh,CentOS 6.5 配置 SSH 免密登录
- linux libstdc 怎样升级,linux 更新libstdc++.so.6
- java开发http协议接口_java开发接口利用http协议传输数据
- python百度知道_用Python写的一个【百度知道】自动点赞
- linux中波浪号代表什么_Linux有什么吸引力,在程序员中如此受欢迎?
- 有php注入的源码,php注入3_php