android 车载安富蓝牙电话开发,Android平台BLE低功耗蓝牙开发
Android平台BLE低功耗蓝牙开发
[复制链接]
安卓4.3(API 18)为BLE的核心功能提供平台支持和API,App可以利用它来发现设备、查询服务和读写特性。相比传统的蓝牙,BLE更显著的特点是低功耗。这一优 点使android App可以与具有低功耗要求的BLE设备通信,如近距离传感器、心脏速率监视器、健身设备等。BLE权限
为了在app中使用蓝牙功能,必须声明蓝牙权限BLUETOOTH。利用这个权限去执行蓝牙通信,例如请求连接、接受连接、和传输数据。
如果想让你的app启动后能够发现或操纵蓝牙设置,必须声明BLUETOOTH_ADMIN权限。注意:如果你使用BLUETOOTH_ADMIN权限,你也必须声明BLUETOOTH权限。
在你的app manifest文件中声明蓝牙权限。
如果想声明你的app只为具有BLE的设备提供,在manifest文件中包括:
但是如果想让你的app提供给那些不支持BLE的设备,需要在manifest中包括上面代码并设置required="false",然后在运行时可以通过使用PackageManager.hasSystemFeature()确定BLE的可用性。
// 使用此检查确定BLE是否支持在设备上,然后你可以有选择性禁用BLE相关的功能
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this,R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}设置BLE
你的app能与BLE通信之前,你需要确认手机是否支持BLE,如果支持,确认已经启用。注意如果设置为false,这个检查才是必需的。
如果不支持BLE,那么你应该适当地禁用部分BLE功能。如果支持BLE但被禁用,你可以无需离开应用程序而要求用户启动蓝牙。使用BluetoothAdapter两步完成该设置。
获取 BluetoothAdapter
所有的蓝牙活动都需要蓝牙适配器。BluetoothAdapter代表手机本身的蓝牙适配器(蓝牙无线)。整个系统只有一个蓝牙适配器,而且你的app使用它与系统交互。下面的代码片段显示了如何得到适配器。注意该方法使用getSystemService()]返回BluetoothManager,然后将其用于获取适配器的一个实例。Android 4.3(API 18)引入BluetoothManager。
// 初始化蓝牙适配器
final BluetoothManager bluetoothManager =
(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();开启蓝牙
接下来,你需要确认蓝牙是否开启。调用isEnabled())去检测蓝牙当前是否开启。如果该方法返回false,蓝牙被禁用。下面的代码检查蓝牙是否开启,如果没有开启,将显示错误提示用户去设置开启蓝牙。
// 确保蓝牙在手机上可以开启
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = newIntent (BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}发现BLE设备
为了发现BLE设备,使用startLeScan())方法。这个方法需要一个参数BluetoothAdapter.LeScanCallback。你必须实现它的回调函数,那就是返回的扫描结果。因为扫描非常消耗电量,你应当遵守以下准则:
只要找到所需的设备,停止扫描。
不要在循环里扫描,并且对扫描设置时间限制。以前可用的设备可能已经移出范围,继续扫描消耗电池电量。
下面代码显示了如何开始和停止一个扫描:
/**
* 扫描和显示可以提供的蓝牙设备.
*/
public class DeviceScanActivity extends ListActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
// 10秒后停止寻找.
private static final long SCAN_PERIOD = 10000;
...
private void scanLeDevice(final boolean enable) {
if (enable) {
// 经过预定扫描期后停止扫描
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
...
}
...
}
如果你只想扫描指定类型的外围设备,可以改为调用startLeScan(UUID[], BluetoothAdapter.LeScanCallback)),需要提供你的app支持的GATT Services的UUID对象数组。
作为BLE扫描结果的接口,下面是BluetoothAdapter.LeScanCallback的实现。
private LeDeviceListAdapter mLeDeviceListAdapter;
...
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};连接到GATT服务端
与一个BLE设备交互的第一步就是连接它——更具体的,连接到BLE设备上的GATT服务端。为了连接到BLE设备上的GATT 服务端,需要使用connectGatt( )方法。这个方法需要三个参数:一个Context对象,自动连接(boolean值,表示只要BLE设备可用是否自动连接到它),和 BluetoothGattCallback调用。
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
连接到GATT服务端时,由BLE设备做主机,并返回一个BluetoothGatt实例,然后你可以使用这个实例来进行 GATT客户端操作。请求方(Android app)是GATT客户端。BluetoothGattCallback用于传递结果给用户,例如连接状态,以及任何进一步GATT客户端操作。
在这个例子中,这个BLE APP提供了一个activity(DeviceControlActivity)来连接,显示数据,显示该设备支持的GATT Services和Characteristics。根据用户的输入,这个activity与BluetoothLeService通信,通过 Android BLE API实现与BLE设备交互。
//通过BLE API服务端与BLE设备交互
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager; //蓝牙管理器
private BluetoothAdapter mBluetoothAdapter; //蓝牙适配器
private String mBluetoothDeviceAddress; //蓝牙设备地址
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0; //设备无法连接
private static final int STATE_CONNECTING = 1; //设备正在连接状态
private static final int STATE_CONNECTED = 2; //设备连接完毕
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
public final static UUID UUID_HEART_RATE_MEASUREMENT =
UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
//通过BLE API的不同类型的回调方法
private final BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {//当连接状态发生改变
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {//当蓝牙设备已经连接
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attempting to start Service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {//当设备无法连接
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
@Override
// 发现新服务端
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
// 读写特性
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic Characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, Characteristic);
}
}
...
};
...
}
当一个特定的回调被触发的时候,它会调用相应的broadcastUpdate()辅助方法并且传递给它一个action。注意在该部分中的数据解析按照蓝牙心率测量配置文件规格进行。
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic Characteristic) {
final Intent intent = new Intent(action);
// 这是心率测量配置文件。
if (UUID_HEART_RATE_MEASUREMENT.equals(Characteristic.getUuid())) {
int flag = Characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = Characteristic.getIntValue(format, 1);
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
} else {
// 对于所有其他的配置文件,用十六进制格式写数据
final byte[] data = Characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" +
stringBuilder.toString());
}
}
sendBroadcast(intent);
}
返回DeviceControlActivity, 这些事件由一个BroadcastReceiver来处理:
// 通过服务控制不同的事件
// ACTION_GATT_CONNECTED: 连接到GATT服务端
// ACTION_GATT_DISCONNECTED: 未连接GATT服务端.
// ACTION_GATT_SERVICES_DISCOVERED: 未发现GATT服务.
// ACTION_DATA_AVAILABLE: 接受来自设备的数据,可以通过读或通知操作获得。
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.
ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// 在用户接口上展示所有的Services and Characteristics
displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};关闭客户端App
当你的app完成BLE设备的使用后,应该调用close( ),系统可以合理释放占用资源。
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
android 车载安富蓝牙电话开发,Android平台BLE低功耗蓝牙开发相关推荐
- android 车载安富蓝牙电话开发,为了进一步助力物联网产品的开发,安富利研发安卓 9.0 操作系统...
球领先的技术解决方案提供商安富利推出了全新的 MaaXBoard Mini 单板计算机,进一步扩大其硬件产品阵容.此举旨在帮助物联网开发者快速将新产品推向市场,并降低开发成本.MaaXBoard Mi ...
- Android BLE低功耗蓝牙开发
啦啦啦在上一个项目中有用到BLE低功耗蓝牙开发,当时baidu google了很多资料,但大多数都是千篇一律,英文文档我这种渣渣又看不懂...总之刚开始查的很痛苦.所以要把自己的踩坑之路写下来记录下, ...
- Android 8.0 BLE 低功耗蓝牙开发记录
Android 8.0 BLE 低功耗蓝牙开发记录(1-3)--------------(权限申请篇未完待续) 目的:开源博客,希望大家一起修改博客错误地方,共同完善并会鸣谢提供意见的朋友.为大家提供 ...
- ble 低功耗蓝牙开发学习 嵌入式交流学习
ble 低功耗蓝牙开发学习 嵌入式交流学习 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 这篇文章教你学会低功耗蓝牙开发,从0到深入,适合自学的学生.初级工程师 前言 随着疫情爆发 ...
- c# 低功耗蓝牙_Android ble低功耗蓝牙开发-客户端
什么是BLE(低功耗蓝牙) BLE(Bluetooth Low Energy,低功耗蓝牙)是对传统蓝牙BR/EDR技术的补充. 尽管BLE和传统蓝牙都称之为蓝牙标准,且共享射频,但是,BLE是一个完全 ...
- Android ble covana,Android BLE低功耗蓝牙开发
最近做了一个智能硬件开发(针灸仪)的项目,有一部分涉及到低功耗蓝牙的开发,就是通过蓝牙和设备进行数据的交互,比如控制改设备的LED的开关,设备的开关机,设置设备的时间和温度等,下面就项目中遇到的坑一一 ...
- android低耗能蓝牙开发,Android BLE低功耗蓝牙开发
最近做了一个智能硬件开发(针灸仪)的项目,有一部分涉及到低功耗蓝牙的开发,就是通过蓝牙和设备进行数据的交互,比如控制改设备的LED的开关,设备的开关机,设置设备的时间和温度等,下面就项目中遇到的坑一一 ...
- Android BLE低功耗蓝牙开发(下) BLE客户端(中央设备)与GATT服务的通讯
之前的文章简单实现了使用传统蓝牙进行通讯的DEMO,说是最简单其实只是夸张的写法~毕竟标题党横行,我们也得学学点~至少没有UC震惊部那么夸张. 然后,本来是要写Android开发之BlueTooth- ...
- BLE低功耗蓝牙开发学习,从零到深教程文档总结(持续更新2022/6/14更新)
写在前面: 写教程原因: 说说自己写这次的ble教程的由来吧.以往公司总有很多是做单片机的或者应届生毕业,他们对ble不是很连接,公司一般都会安排别人来做一点培训啊,或者老员工带.巧了,之前帮别的培训 ...
- 20_微信小程序-BLE低功耗蓝牙开发-发布小程序
所有功能测试OK了,就剩下最后一步了,那就是把开发好的微信小程序发布出去. 1. 填写小程序信息,登录小程序管理平台,在设置->填写信息,里面填写小程序相关信息(后面我直接把小程序名称改为&qu ...
最新文章
- 通过性能计数器确定.net应用程序是否存在内存溢出
- iphone电池怎么保养_苹果iPhone手机怎么开启【优化电池充电】
- 测试管理 | 4种优先级排序方法一定要掌握
- mkdir: 无法创建目录“/home/lj/.tldr“: 文件已存在
- linux ping策略打开_Linux Iptables允许或阻止ICMP ping请求
- CC1101魔幻的收发切换机制
- 深掘工业互联网大数据五大维度
- Python学习教程:教你用Python通过微信来控制电脑摄像头
- ssh 远程连接、上传下载命令
- erdas几何校正_ERDAS遥感图像的几何校正.docx
- zmq xsub/xpub 实现消息订阅(一)
- gopher对mysql的利用_[题目]记一次利用gopher的内网mysql盲注
- 锐捷交换机忘记密码解决方案:恢复出厂设置、重置配置文件
- 8-详解前缀树贪心算法N皇后问题
- rm: cannot remove `/usr/local/tmp/‘: Directory not empty
- Android ADB USB 驱动 万能配置方式
- 累计投放贷款1000亿,马云是如何做银行的?
- 2020中国彩礼地图:哪里娶媳妇最贵?
- 浅谈三次数学危机——费马大定理
- docker迁移遇到torch不能使用
热门文章
- 鼠标移动文字上显示图片
- C语言库函数:memcmp/strcmp和strncmp的区别
- 使用halcon实现3维点云物体与模型的匹配并显示差异
- Riverbed SteelHead 9.5.0
- 电脑系统更新完后,计算机管理服务中找不到mysql的服务
- 网络编程中常用的fd是什么
- OSChina 周五乱弹 —— 为什么程序媛那么少?
- OpenAI 最强对话模型 ChatGPT 注册使用笔记
- 问题 B: 神棍的纯真愿望
- 【转】iPhone通讯录AddressBook.framework和AddressBookUI.framework的应用