安卓 蓝牙 mbluetoothadapter.stoplescan 过时方法过期了用什么替代

>> DeviceScanActivity.java
DeviceScanActivity.java ( 文件浏览 )
* Copyright (C) 2013 The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the &License&);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &AS IS& BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
package com.example.bluetooth.
import android.app.A
import android.app.ListA
import android.bluetooth.BluetoothA
import android.bluetooth.BluetoothD
import android.bluetooth.BluetoothG
import android.bluetooth.BluetoothGattC
import android.bluetooth.BluetoothGattD
import android.bluetooth.BluetoothGattS
import android.bluetooth.BluetoothM
import android.content.C
import android.content.I
import android.content.pm.PackageM
import android.os.B
import android.os.H
import android.util.L
import android.view.LayoutI
import android.view.M
import android.view.MenuI
import android.view.V
import android.view.ViewG
import android.widget.BaseA
import android.widget.ListV
import android.widget.TextV
import android.widget.T
import java.util.ArrayL
import java.util.L
import java.util.UUID;
import com.example.bluetooth.le.BluetoothLeClass.OnDataAvailableL
import com.example.bluetooth.le.BluetoothLeClass.OnServiceDiscoverL
* Activity for scanning and displaying available Bluetooth LE devices.
public class DeviceScanActivity extends ListActivity {
private final static String TAG = DeviceScanActivity.class.getSimpleName();
private final static String UUID_KEY_DATA = &0000ffe1-00-fb&;
private LeDeviceListAdapter mLeDeviceListA
/**搜索BLE终端*/
private BluetoothAdapter mBluetoothA
/**读写BLE终端*/
private BluetoothLeClass mBLE;
private boolean mS
private Handler mH
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle(R.string.title_devices);
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device.
Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
// Initializes a Bluetooth adapter.
For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
//开启蓝牙
mBluetoothAdapter.enable();
mBLE = new BluetoothLeClass(this);
if (!mBLE.initialize()) {
Log.e(TAG, &Unable to initialize Bluetooth&);
//发现BLE终端的Service时回调
mBLE.setOnServiceDiscoverListener(mOnServiceDiscover);
//收到BLE终端数据交互的事件
mBLE.setOnDataAvailableListener(mOnDataAvailable);
protected void onResume() {
super.onResume();
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter(this);
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
protected void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
mBLE.disconnect();
protected void onStop() {
super.onStop();
mBLE.close();
protected void onListItemClick(ListView l, View v, int position, long id) {
final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
if (device == null)
if (mScanning) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mScanning =
mBLE.connect(device.getAddress());
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
public void run() {
mScanning =
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}, SCAN_PERIOD);
mScanning =
mBluetoothAdapter.startLeScan(mLeScanCallback);
mScanning =
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
* 搜索到BLE终端服务的事件
private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener(){
public void onServiceDiscover(BluetoothGatt gatt) {
displayGattServices(mBLE.getSupportedGattServices());
* 收到BLE终端数据交互的事件
private BluetoothLeClass.OnDataAvailableListener mOnDataAvailable = new OnDataAvailableListener(){
* BLE终端数据被读的事件
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS)
Log.e(TAG,&onCharRead &+gatt.getDevice().getName()
+characteristic.getUuid().toString()
+Utils.bytesToHexString(characteristic.getValue()));
* 收到BLE终端写入数据回调
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.e(TAG,&onCharWrite &+gatt.getDevice().getName()
+& write &
+characteristic.getUuid().toString()
+new String(characteristic.getValue()));
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
private void displayGattServices(List&BluetoothGattService& gattServices) {
if (gattServices == null)
for (BluetoothGattService gattService : gattServices) {
//-----Service的字段信息-----//
int type = gattService.getType();
Log.e(TAG,&--&service type:&+Utils.getServiceType(type));
Log.e(TAG,&--&includedServices size:&+gattService.getIncludedServices().size());
Log.e(TAG,&--&service uuid:&+gattService.getUuid());
//-----Characteristics的字段信息-----//
List&BluetoothGattCharacteristic& gattCharacteristics =gattService.getCharacteristics();
for (final BluetoothGattCharacteristic
gattCharacteristic: gattCharacteristics) {
Log.e(TAG,&----&char uuid:&+gattCharacteristic.getUuid());
int permission = gattCharacteristic.getPermissions();
Log.e(TAG,&----&char permission:&+Utils.getCharPermission(permission));
int property = gattCharacteristic.getProperties();
Log.e(TAG,&----&char property:&+Utils.getCharPropertie(property));
byte[] data = gattCharacteristic.getValue();
if (data != null && data.length & 0) {
Log.e(TAG,&----&char value:&+new String(data));
//UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic
if(gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA)){
//测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
mHandler.postDelayed(new Runnable() {
public void run() {
mBLE.readCharacteristic(gattCharacteristic);
//接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
mBLE.setCharacteristicNotification(gattCharacteristic, true);
//设置数据内容
gattCharacteristic.setValue(&send data-&&);
//往蓝牙模块写入数据
mBLE.writeCharacteristic(gattCharacteristic);
//-----Descriptors的字段信息-----//
List&BluetoothGattDescriptor& gattDescriptors = gattCharacteristic.getDescriptors();
for (BluetoothGattDescriptor gattDescriptor : gattDescriptors) {
Log.e(TAG, &--------&desc uuid:& + gattDescriptor.getUuid());
int descPermission = gattDescriptor.getPermissions();
Log.e(TAG,&--------&desc permission:&+ Utils.getDescPermission(descPermission));
byte[] desData = gattDescriptor.getValue();
if (desData != null && desData.length & 0) {
(文件超长,未完全显示,请下载后阅读剩余部分)
展开> <收缩
下载源码到电脑,阅读使用更方便
还剩0行未阅读,继续阅读 ▼
Sponsored links
源码文件列表
温馨提示: 点击源码文件名可预览文件内容哦 ^_^
.classpath491.00 B 15:56
.project851.00 B 16:41
org.eclipse.jdt.core.prefs177.00 B 15:54
1.94 kB 09:35
1.94 kB 18:04
BluetoothLeGatt.apk40.77 kB 18:25
classes.dex21.64 kB 18:25
BluetoothLeClass$1.class3.39 kB 18:33
BluetoothLeClass$OnConnectListener.class313.00 B 18:33
BluetoothLeClass$OnDataAvailableListener.class502.00 B 18:33
BluetoothLeClass$OnDisconnectListener.class322.00 B 18:33
BluetoothLeClass$OnServiceDiscoverListener.class337.00 B 18:33
BluetoothLeClass.class6.32 kB 18:33
BuildConfig.class357.00 B 18:04
DeviceScanActivity$1.class1.16 kB 18:25
DeviceScanActivity$2.class2.16 kB 18:25
DeviceScanActivity$3$1.class1.29 kB 18:25
DeviceScanActivity$3.class1.28 kB 18:25
DeviceScanActivity$4.class1.24 kB 18:25
DeviceScanActivity$5.class1.10 kB 18:25
DeviceScanActivity.class9.42 kB 18:25
LeDeviceListAdapter$ViewHolder.class654.00 B 18:04
LeDeviceListAdapter.class2.92 kB 18:04
R$attr.class358.00 B 18:07
R$drawable.class425.00 B 18:07
R$id.class738.00 B 18:07
R$layout.class532.00 B 18:07
R$menu.class443.00 B 18:07
R$string.class1.00 kB 18:07
R.class625.00 B 18:07
Utils.class3.79 kB 18:04
resources.ap_28.51 kB 18:04
ic_launcher.png4.09 kB 18:04
ic_launcher.png2.48 kB 18:04
ic_launcher.png5.58 kB 18:04
ic_launcher.png9.39 kB 18:04
166.00 B 16:42
2.49 kB 16:47
ic_launcher-web.png36.23 kB 19:56
53.00 B 15:57
781.00 B 19:56
project.properties563.00 B 15:57
ic_launcher.png5.05 kB 23:37
ic_launcher.png2.95 kB 23:37
ic_launcher.png7.06 kB 23:37
ic_launcher.png12.50 kB 23:37
942.00 B 23:37
3.31 kB 23:37
1.24 kB 23:37
1.24 kB 23:37
1.22 kB 23:37
1.62 kB 23:37
9.99 kB 18:33
10.11 kB 18:25
2.18 kB 10:11
5.75 kB 16:24
Sponsored links
23 篇源代码 21 篇源代码 18 篇源代码 13 篇源代码 9 篇源代码
285 篇源代码 173 篇源代码 48 篇源代码 42 篇源代码 36 篇源代码
评价成功,多谢!
下载BluetoothLeGatt.zip
CodeForge积分(原CF币)全新升级,功能更强大,使用更便捷,不仅可以用来下载海量源代码马上还可兑换精美小礼品了
您的积分不足
支付宝优惠套餐快速获取 30 积分
10积分 / ¥100
30积分 / ¥200原价 ¥300 元
100积分 / ¥500原价 ¥1000 元
订单支付完成后,积分将自动加入到您的账号。以下是优惠期的人民币价格,优惠期过后将恢复美元价格。
支付宝支付宝付款
微信钱包微信付款
更多付款方式:、
您本次下载所消耗的积分将转交上传作者。
同一源码,30天内重复下载,只扣除一次积分。
鲁ICP备号-2 runtime:Elapsed:106.515ms .206
登录 CodeForge
还没有CodeForge账号?
Switch to the English version?
^_^"呃 ...
Sorry!这位大神很神秘,未开通博客呢,请浏览一下其他的吧6223人阅读
Android(20)
一、关键概念:
Attribute Profile (GATT)
通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。
Protocol (ATT)
GATT是基于ATT
Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。
Characteristic
Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。
Descriptor
对Characteristic的描述,例如范围、计量单位等。
Characteristic的集合。例如一个service叫做“Heart
Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement&的Characteristic。
二、角色和职责:
Android设备与BLE设备交互有两组角色:
中心设备和外围设备(Central
vs. peripheral);
server vs. GATT client.
vs. peripheral:
中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan
advertisement。而peripheral角色负责make advertisement。
server vs. GATT client:
这两种角色取决于BLE连接成功后,两个设备间通信的方式。
举例说明:
现有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。
当连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则Android设备作为server端可能更合适。
三、权限及feature:
和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限:
&uses-permission
android:name=&android.permission.BLUETOOTH&/&
&uses-permission android:name=&android.permission.BLUETOOTH_ADMIN&/&
除了蓝牙权限外,如果需要BLE
feature则还需要声明uses-feature:
&uses-feature
android:name=&android.hardware.bluetooth_le& android:required=&true&/&
按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE
Use this check to determine whether BLE is supported on the device. Then
// you can selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
& & Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
& & finish();
四、启动蓝牙:
在使用蓝牙BLE之前,需要确认Android设备是否支持BLE
feature(required为false时),另外要需要确认蓝牙是否打开。&
如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。
打开蓝牙的步骤:
1、获取BluetoothAdapter
BluetoothAdapter是Android系统中所有蓝牙操作都需要的,它对应本地Android设备的蓝牙模块,在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙操作了。
获取BluetoothAdapter代码示例如下:
Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager =
& && &&&(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
注:这里通过getSystemService获取BluetoothManager,再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android4.3以上支持(API
level 18)。
2、判断是否支持蓝牙,并打开蓝牙
获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。
如果没打开,需要让用户打开蓝牙:
BluetoothAdapter mBluetoothA
// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
& & Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
& & startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
五、搜索BLE设备:
通过调用BluetoothAdapter的startLeScan()搜索BLE设备。调用此方法时需要传入BluetoothAdapter.LeScanCallback参数。
因此你需要实现&BluetoothAdapter.LeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。
由于搜索需要尽量减少功耗,因此在实际使用时需要注意:
1、当找到对应的设备后,立即停止扫描;
2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
搜索的示例代码如下:
* Activity for scanning and displaying available BLE devices.
public class DeviceScanActivity extends ListActivity {
& & private BluetoothAdapter mBluetoothA
& & private boolean mS
& & private Handler mH
& & // Stops scanning after 10 seconds.
& & private static final long SCAN_PERIOD = 10000;
& & private void scanLeDevice(final boolean enable) {
& && &&&if (enable) {
& && && && &// Stops scanning after a pre-defined scan period.
& && && && &mHandler.postDelayed(new Runnable() {
& && && && && & @Override
& && && && && & public void run() {
& && && && && && &&&mScanning =
& && && && && && &&&mBluetoothAdapter.stopLeScan(mLeScanCallback);
& && && && && & }
& && && && &}, SCAN_PERIOD);
& && && && &mScanning =
& && && && &mBluetoothAdapter.startLeScan(mLeScanCallback);
& && &&&} else {
& && && && &mScanning =
& && && && &mBluetoothAdapter.stopLeScan(mLeScanCallback);
& && &&&...
如果你只需要搜索指定UUID的外设,你可以调用&startLeScan(UUID[],
BluetoothAdapter.LeScanCallback)方法。
其中UUID数组指定你的应用程序所支持的GATT
Services的UUID。
BluetoothAdapter.LeScanCallback的实现示例如下:
LeDeviceListAdapter mLeDeviceListA
// 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();
& && && &&&}
& && & });
注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
六、连接GATT Server:
两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT
Server,你需要调用BluetoothDevice的connectGatt()方法。此函数带三个参数:Context、autoConnect(boolean)和BluetoothGattCallback对象。调用示例:
mBluetoothGatt
= device.connectGatt(this, false, mGattCallback);
函数成功,返回BluetoothGatt对象,它是GATT
profile的封装。通过这个对象,我们就能进行GATT Client端的相关操作。BluetoothGattCallback用于传递一些连接状态及结果。
BluetoothGatt常规用到的几个操作示例:
:连接远程设备。
discoverServices()
: 搜索连接设备所支持的service。
disconnect():断开与远程设备的GATT连接。
close():关闭GATT
Client端。
readCharacteristic(characteristic)
:读取指定的characteristic。
setCharacteristicNotification(characteristic,
enabled) :设置当指定characteristic值变化时,发出通知。
getServices()
:获取远程设备所支持的services。
1、某些函数调用之间存在先后关系。例如首先需要connect上才能discoverServices。
2、一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回。例如discoverServices与onServicesDiscovered回调,readCharacteristic与onCharacteristicRead回调,setCharacteristicNotification与onCharacteristicChanged回调等。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:57124次
排名:千里之外
转载:30篇
(1)(2)(1)(1)(11)(5)(1)(1)(1)(7)(2)(1)(2)(2)Android 蓝牙4.0 BLE 开发 - 逗不过奇葩 - 博客园
&&& 个人认为,Android开发后台部分的技术难题只要把google提供的API看懂了就没什么太多的难点了,关键在于运用,蓝牙4.0也是,琢磨了好久没搞懂,结果下了个doc下来自己翻译一下也就理清了整个过程了,大家可能比较忙,我翻译一下吧,翻译得不好别打脸~网上还有很多人的翻译,我尽量用自己的语言来翻译,稍微带点自己的理解。
低功耗蓝牙(Bluetooth Low Energy)
Android 4.3 (API Level 18)介绍了一种以低功耗蓝牙为核心的开发平台,并提供了可以让应用程序来发现设备、查询服务、读写特征值等相关API(关于服务、特征值的概念请参考BLE4.0蓝牙经典问答,要是不知道可以参考我转发的一篇,讲得很好,蓝牙4.0开发人员必看:)。&因为低功耗蓝牙作为经典蓝牙的拓展,相比经典蓝牙2.0为了统一通信设备,跟3.0增加数据传输速率,4.0尽可能的在降低功耗方面进行了优化。这就允许了android应用程序和低功耗蓝牙设备进行通讯,如各类传感器,心率仪,健身设备等。
关键术语和概念
下面是一些主要的BLE的概念性知识:
Generic Attribute Profile (GATT)&GATT协议是一个通过BLE连接从而发送和接收数据(这种数据格式我们通常称之为&属性&)的通用协议。当前所有的低功耗蓝牙的应用协议都是基于GATT的。
蓝牙技术联盟为低功耗蓝牙设备定义了很多协议(我们直接用就行了,so easy,但很重要,大家开发时找准了协议直接下载参考使用就好了,下载地址:)。这些协议其实就是个在应用程序中如何在连接的设备中进行通信使用的说明书。每个设备可以使用多个协议,譬如我做的智能硬件就加载了电池电量检测跟心率监控的协议,用到就加进去就行了,好像我们在Android开发时用的包一样。
Attribute Protocol (ATT)&GATT 是ATT的上层架构,GATT把ATT的数据打包成service供我们使用. ATT 运行在我们的蓝牙外设设备上.为了达到最优化的目的,它在运行中使用尽可能少的字节。& 每个属性以唯一的UUID(就是把特定的字符串转换成128位长的数字,通常是16进制的)定义,这个属性就有ATT进行传送,我们看到的就是services和characteristics .
Characteristic&一个 characteristic 包含了一个值和多个描述符。它就好像一个类(可以实例化出一个对象,里面具体的属性可以由自己定义一样,不知道这么理解对不对)
Descriptor&描述符是用来定义属性的,就像上面讲的用来描述characteristic 的(应该想类里面的set 跟get方法一样的吧)。如指定特征值是否可读,可接受的范围或者特征值特定的单位等。
Service&service是一些列的characteristic 的总集。如你有个服务叫&心率检测仪&,里面就有个characteristic 叫&心率测量&(应用程序中直接对这个characteristic 的UUID进行数据读取就行了)。 你可以找到很多基于GATT协议的应用协议,就在上面给的那个网址链接中。
角色和责任
下面是android手机和BLE设备通信时需要我们注意的一些游戏规则,不遵守的就没得玩了(中间一段抄的人家的,感觉讲得很简练,可耻地copy了,第一次写博客,请轻砸):
Central vs. peripheral:
中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。
GATT server vs. GATT client:
这两种角色取决于BLE连接成功后,两个设备间通信的方式。
举例说明:
现有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。
当连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则Android设备作为server端可能更合适。
在文件包含的例子中,手机端作为client,从GATT server(一个支持心率协议:的BLE硬件智能设备)中获取数据,当然,你也可以手动指定你的手机app作为server端,关于可以了解一下:
废话不多说,你要想在手机里使用蓝牙的功能你就得申明蓝牙的使用权限:,你需要这个权限来完成各种蓝牙通信,如请求连接,接受连接,收发数据。
如果你想要你的APP发起设备发现或者修改蓝牙设置,你必须要申明:权限。不过你想要用该权限那必须先得拥有的权限。
在manifest 文件中申明权限的方法:
&uses-permission android:name="android.permission.BLUETOOTH"/&&uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/&
如果你想让你的应用程序只在低功耗蓝牙手机上工作,那你可以如下设置:
&uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/&
然而,如果你想让你的应用程序同样可以在不支持蓝牙4.0的设备上工作的话,你也应该申明上述权限,但要set required="false". 然后在程序运行过程中你可以通过来申明低功耗蓝牙是否可用。
// Use this check to determine whether BLE is supported on the device. Then// you can selectively disable BLE-related features.通过下面代码来检查你手机是否直接低功耗蓝牙,然后你可以有选择的设置是否开启蓝牙服务。if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {& & Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();& & finish();}
下面就简单了,主要是低功耗蓝牙的代码开发步骤,大家随便看看,然后把官网提供的范例下载下来学习一下,范例只有读,没有写,大家百度一下就可以找到,。
找不到的再问我要吧:至于我自己开发的项目中的一些功能我到时看看稍微修改一下放出来让大家也帮忙指导一下,这个博客我还不会上传附件。
需要的问我QQ:要吧,QQ不在可以到我微博上留邮箱:微博VIA:逗不过奇葩;
鉴于本人不是专业的android开发工程师,大家太高深的问题就别问了,只是项目中需要才研究做个android APP的。
在你应用程序通过低功耗蓝牙通讯前,你需要query你的设备是否支持BLE,确保它是可用的。注意:这个检查只有在&uses-feature.../&中set to false的时候才是必须做的。
如果BLE不支持,那你就没办法使用BLE的功能咯。如果支持BLE,但没有开启蓝牙功能,你可以请求使用者在你的应用程序中开启。设置蓝牙可以通过分两步完成:
几乎所有的蓝牙activity都需要
代表了设备自身的蓝牙适配器。在整个系统中只有一个蓝牙适配器,你的应用程序可以通过使用它,下面的代码演示了如何获取适配器。注意:该方法是通过返回的一个实例来得到适配器,关于在Android 4.3 (API Level 18)中有详细介绍。
// Initializes Bluetooth adapter.初始化蓝牙适配器final BluetoothManager bluetoothManager =& & & & (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = bluetoothManager.getAdapter();
下一步,你需要确定蓝牙是可用的,调用来检测蓝牙当前状态是否可用,如果返回false,当前蓝牙不可用。下面的代码演示了如何检测是否可用,如果不可用,则设置开启蓝牙
private BluetoothAdapter mBluetoothA...// Ensures Bluetooth is available on the device and it is enabled. If not,// displays a dialog requesting user permission to enable Bluetooth.if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {& & Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);& & startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}
寻找BLE蓝牙设备
你可以使用()方法来发现BLE设备,该方法用作为参数,你必须继承这个回调来获取扫描结果,由于扫描过程很耗电,你应该遵守以下的引导来降低功耗:
一旦发现目标设备立刻停止扫描.
不要重复扫描,设置一个i额扫描时间限制,以前连接的设备可能已经离开了当前可扫描的范围,持续扫描会增加功耗。
下面代码演示了如何发起和停止扫描:
/**&* Activity for scanning and displaying available BLE devices.&*/public class DeviceScanActivity extends ListActivity {& & private BluetoothAdapter mBluetoothA& & private boolean mS& & private Handler mH& & // Stops scanning after 10 seconds.& & private static final long SCAN_PERIOD = 10000;& & ...& & private void scanLeDevice(final boolean enable) {& & & & if (enable) {& & & & & & // Stops scanning after a pre-defined scan period.& & & & & & mHandler.postDelayed(new Runnable() {& & & & & & & & @Override& & & & & & & & public void run() {& & & & & & & & & & mScanning =& & & & & & & & & & mBluetoothAdapter.stopLeScan(mLeScanCallback);& & & & & & & & }& & & & & & }, SCAN_PERIOD);& & & & & & mScanning =& & & & & & mBluetoothAdapter.startLeScan(mLeScanCallback);& & & & } else {& & & & & & mScanning =& & & & & & mBluetoothAdapter.stopLeScan(mLeScanCallback);& & & & }& & & & ...& & }...}
如果你想扫描特定的外围设备,你可以用这个方法来代替上面代码的扫描函数。该方法中的UUID就是你app中支持的服务的UUIP,在搜索过程中就进行了一遍筛选连接。
下面的代码是的实现过程,这个接口是用来传递BLE搜索到的结果的。
private LeDeviceListAdapter mLeDeviceListA...// 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();& & & & & &}& & & &});& &}};
注意: 搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索.
连接到一个GATT server
两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server。
连接GATT Server,你需要调用BluetoothDevice的方法。此函数带三个参数:Context、autoConnect(boolean来表明当BLE设备可用时是否主动去连接它)和对象。调用示例:
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
函数成功,返回对象,它是GATT profile的封装。通过这个对象,我们就能进行GATT Client端(就是我们手机端的APP)的相关操作。用于传递一些连接状态及结果给client端。
在该实例中,app提供了一个DeviceControlActivity来连接,显示数据,并列出了由设备提供的服务和特征,基于用户的输入,这个activity通过Android BLE API来调用BluetoothLeService和service通讯。
// A service that interacts with the BLE device via the Android BLE API.public class BluetoothLeService extends Service {& & private final static String TAG = BluetoothLeService.class.getSimpleName();& & private BluetoothManager mBluetoothM& & private BluetoothAdapter mBluetoothA& & private String mBluetoothDeviceA& & private BluetoothGatt mBluetoothG& & 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);& & // Various callback methods defined by the BLE API.& & private final BluetoothGattCallback mGattCallback =& & & & & & new BluetoothGattCallback() {& & & & @Override& & & & public void onConnectionStateChange(BluetoothGatt gatt, int status,& & & & & & & & int newState) {& & & & & & String intentA& & & & & & 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& & & & // New services discovered& & & & 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& & & & // Result of a characteristic read operation& & & & public void onCharacteristicRead(BluetoothGatt gatt,& & & & & & & & BluetoothGattCharacteristic characteristic,& & & & & & & & int status) {& & & & & & if (status == BluetoothGatt.GATT_SUCCESS) {& & & & & & & & broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);& & & & & & }& & & & }& & &...& & };...}
当一个具体的回调被发起时,它会调用合适的broadcastUpdate()方法并给它发一个动作,下面这段是Bluetooth Heart Rate Measurement 中的实现代码,可以参考了解一下:
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);& & // This is special handling for the Heart Rate Measurement profile. Data& & // parsing is carried out as per profile specifications.& & 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 {& & & & // For all other profiles, writes the data formatted in HEX.& & & & 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中,&这些事件就由 进行处理:
// Handles various events fired by the Service.// ACTION_GATT_CONNECTED: connected to a GATT server.// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.// ACTION_DATA_AVAILABLE: received data from the device. This can be a// result of read or notification operations.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 =& & & & & & updateConnectionState(R.string.connected);& & & & & & invalidateOptionsMenu();& & & & } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {& & & & & & mConnected =& & & & & & updateConnectionState(R.string.disconnected);& & & & & & invalidateOptionsMenu();& & & & & & clearUI();& & & & } else if (BluetoothLeService.& & & & & & & & ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {& & & & & & // Show all the supported services and characteristics on the& & & & & & // user interface.& & & & & & displayGattServices(mBluetoothLeService.getSupportedGattServices());& & & & } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {& & & & & & displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));& & & & }& & }};
读取BLE属性(数据)
一旦你的APP连接到了一个GATT server并且发现相关的服务(serices),它就可以根读写服务中提供的属性(参考上面的概念);
下面的代码演示了如何把搜索到的可用的服务和特征遍历显示在UI界面上:
public class DeviceControlActivity extends Activity {& & ...& & // Demonstrates how to iterate through the supported GATT& & // Services/Characteristics.& & // In this sample, we populate the data structure that is bound to the& & // ExpandableListView on the UI.& & private void displayGattServices(List&BluetoothGattService& gattServices) {& & & & if (gattServices == null)& & & & String uuid =& & & & String unknownServiceString = getResources().& & & & & & & & getString(R.string.unknown_service);& & & & String unknownCharaString = getResources().& & & & & & & & getString(R.string.unknown_characteristic);& & & & ArrayList&HashMap&String, String&& gattServiceData =& & & & & & & & new ArrayList&HashMap&String, String&&();& & & & ArrayList&ArrayList&HashMap&String, String&&& gattCharacteristicData& & & & & & & & = new ArrayList&ArrayList&HashMap&String, String&&&();& & & & mGattCharacteristics =& & & & & & & & new ArrayList&ArrayList&BluetoothGattCharacteristic&&();& & & & // Loops through available GATT Services.& & & & for (BluetoothGattService gattService : gattServices) {& & & & & & HashMap&String, String& currentServiceData =& & & & & & & & & & new HashMap&String, String&();& & & & & & uuid = gattService.getUuid().toString();& & & & & & currentServiceData.put(& & & & & & & & & & LIST_NAME, SampleGattAttributes.& & & & & & & & & & & & & & lookup(uuid, unknownServiceString));& & & & & & currentServiceData.put(LIST_UUID, uuid);& & & & & & gattServiceData.add(currentServiceData);& & & & & & ArrayList&HashMap&String, String&& gattCharacteristicGroupData =& & & & & & & & & & new ArrayList&HashMap&String, String&&();& & & & & & List&BluetoothGattCharacteristic& gattCharacteristics =& & & & & & & & & & gattService.getCharacteristics();& & & & & & ArrayList&BluetoothGattCharacteristic& charas =& & & & & & & & & & new ArrayList&BluetoothGattCharacteristic&();& & & & & &// Loops through available Characteristics.& & & & & & for (BluetoothGattCharacteristic gattCharacteristic :& & & & & & & & & & gattCharacteristics) {& & & & & & & & charas.add(gattCharacteristic);& & & & & & & & HashMap&String, String& currentCharaData =& & & & & & & & & & & & new HashMap&String, String&();& & & & & & & & uuid = gattCharacteristic.getUuid().toString();& & & & & & & & currentCharaData.put(& & & & & & & & & & & & LIST_NAME, SampleGattAttributes.lookup(uuid,& & & & & & & & & & & & & & & & unknownCharaString));& & & & & & & & currentCharaData.put(LIST_UUID, uuid);& & & & & & & & gattCharacteristicGroupData.add(currentCharaData);& & & & & & }& & & & & & mGattCharacteristics.add(charas);& & & & & & gattCharacteristicData.add(gattCharacteristicGroupData);& & & & &}& & ...& & }...}
获取GATT的通知
当设备端的某个特定的特征值发生改变时BLE的APP就会收到通知。
下面的代码演示了如何通过()方法来为一个特征设置通知:
private BluetoothGatt mBluetoothGBluetoothGattCharacter...mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);...BluetoothGattDescriptor descriptor = characteristic.getDescriptor(& & & & UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);mBluetoothGatt.writeDescriptor(descriptor);
Once notifications are enabled for a characteristic, an
callback is triggered if the characteristic changes on the remote device:
@Override// Characteristic notificationpublic void onCharacteristicChanged(BluetoothGatt gatt,& & & & BluetoothGattCharacteristic characteristic) {& & broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);}
关闭client的APP:
一旦你的APP结束使用BLE设备,它需要调用close()来让系统适当的回收资源和释放内存空间。
示例代码:
public void close() {& & if (mBluetoothGatt == null) {& & & && & }& & mBluetoothGatt.close();& & mBluetoothGatt =}
摘抄的人家的一段,算是备注一下:
BluetoothGatt常规用到的几个操作示例:
connect() :连接远程设备。
discoverServices() : 搜索连接设备所支持的service。
disconnect():断开与远程设备的GATT连接。
close():关闭GATT Client端。
readCharacteristic(characteristic) :读取指定的characteristic。
setCharacteristicNotification(characteristic,&enabled) :设置当指定characteristic值变化时,发出通知。
getServices()&:获取远程设备所支持的services。
1、某些函数调用之间存在先后关系。例如首先需要connect上才能discoverServices。
2、一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回。例如discoverServices与onServicesDiscovered回调,readCharacteristic与onCharacteristicRead回调,setCharacteristicNotification与onCharacteristicChanged回调等。
本文中除了自己理解的部分外,参考的博客地址是:
自己翻译前大概浏览过《低功耗蓝牙开发权威指南》跟《蓝牙4.0BLE开发完全手册》,这两本书很实用,可惜没时间好好看,推荐给大家!}

我要回帖

更多关于 thread stop 替代 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信