作者:Bgwan
链接:https://zhuanlan.zhihu.com/p/23341414
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

作者:Bgwan 莳萝花
链接:android BLE 蓝牙4.0+浅析(一) - Android开发 - 知乎专栏
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

android BLE 蓝牙4.0+浅析(一)

Android 4.3 (API Level 18) introduces built-in platform support for Bluetooth Low Energy in the central roleand provides APIs that apps can use to discover devices, query for services, and read/write characteristics.

+代表蓝牙更高版本,

本文介绍Android ble 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用,如果手机系统版本API level < 18,是用不了蓝牙4.0的,我们通常可以加一个判断。

首先:操作蓝牙,我们需要在AndroidMainfest.xml中配置,如下权限,

<!--蓝牙权限-->
<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"></uses-feature>

说明:hardware是,在底判断是否支持,蓝牙,admin是超级权限,根据用户需求不同加入不同的权限,

蓝牙SDK版本判断,如下代码:

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
Toast.makeText(this, "当前版本SDK" + Build.VERSION.SDK_INT + "< Android5.0不支持蓝牙", Toast.LENGTH_SHORT).show();
mText.setText("当前版本" + Build.VERSION.SDK_INT + "< Android5.0不支持蓝牙");
return;
}

1,打开蓝牙,蓝牙状态等操作,以及是否支持蓝牙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();
mText.setText(R.string.ble_not_supported);
return;
}
// Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//需要时再初始化
mHandler = new Handler();
mProgress = new ProgressDialog(NewActivity.this);

2,如果蓝牙没有打开,我们需要打开蓝牙,打开蓝牙有两种方式,但是建议给用户显示的方式打开,因为用户需要知道这些权限,不然你这个就是牛氓行为。隐式打开为:

mBluetoothAdapter.enable();

,下面的代码为显示的打开方式。

/ 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);
Toast.makeText(this, "蓝牙正在打开,建议允许应用操作", Toast.LENGTH_SHORT).show();
}

3,搜索蓝牙操作。

如果蓝牙都已经打开正常,则可以进行搜索周围蓝牙设备的操作,这里记住,不只是手机中的蓝牙,任何外设都可以。顺带,我们查看android SDK会发现bluetooth包下面多了le.这是android 蓝牙4.2以后新加入的操作蓝牙的包,但是谷歌为了兼容以前的版本

mBluetoothAdapter.startLeScan(mLeScanCallback);

这个方法还是可以使用,这里我们使用le。包下面最新的搜索蓝牙的功能,如下:

 //最新写法。蓝牙打开才执行
if (mBluetoothAdapter.isEnabled()) {
mProgress.setMessage("正在搜索周围设备...");
mProgress.setCancelable(false);
mProgress.show();
newtext.setText("蓝牙已经打开,关闭蓝牙请在设置中设置");
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
listView.setAdapter(mLeDeviceListAdapter);
//显示dialog
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
if (mProgress != null) {
mProgress.dismiss();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
mLeDeviceListAdapter.clearDevice();
scanLeDevice(true);
}
}

scanLeDevice是对方法的封装,这里主要是调用bluetoothlescanner的starscan方法,该方法可以传递两个参数,这里先讨论传递mScanCallback这是一个扫描结果的回掉接口;当然这里操作也应该放到子线程中去处理。

mBluetoothLeScanner.startScan(mScanCallback);//新

具体的scanLeDevice()方法如下:

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 = false;
mBluetoothLeScanner.stopScan(mScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothLeScanner.startScan(mScanCallback);//新
} else {
mScanning = false;
mBluetoothLeScanner.stopScan(mScanCallback);
}
invalidateOptionsMenu();
}

4,以上我们就开启了蓝牙的搜索,功能,然后会触发mScanCallback进行结果的监听。主要监听里面的三个方法,onScanResult,onBatchScanResults,onScanFailed,搜索到结果以后,我们需要对它进行解析,代码里面都注释得很清楚

// Device scan callback.
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
if (result == null || result.getDevice() == null
|| TextUtils.isEmpty(result.getDevice().getName())) {
mText.setText("没有搜索到蓝牙设备");
// return;
}
//如果是外设则可能存在没有ServiceUuids
// builder.append("/n").append(
// new String(result.getScanRecord().getServiceData(
// result.getScanRecord().getServiceUuids().get(0)),
// Charset.forName("UTF-8"))); BluetoothDevice device = result.getDevice();
Log.d(TAG, "Device name: " + device.getName());
Log.d(TAG, "Device address: " + device.getAddress());
Log.d(TAG, "Device service UUIDs: " + device.getUuids());
if (builder.toString().contains(device.getName())) {
} else {
builder.append("\n" + device.getName() + "&" + device.getAddress() + "\n");
}
ScanRecord record = result.getScanRecord();
Log.d(TAG, "Record advertise flags: 0x" + Integer.toHexString(record.getAdvertiseFlags()));
Log.d(TAG, "Record Tx power level: " + record.getTxPowerLevel());
Log.d(TAG, "Record device name: " + record.getDeviceName());
Log.d(TAG, "Record service UUIDs: " + record.getServiceUuids());
Log.d(TAG, "Record service data: " + record.getServiceData()); mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged(); mText.setText("搜索结果,builder:" + builder.toString());
} @Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
for (ScanResult result : results) {
Toast.makeText(getApplicationContext(), "result:" + result.getDevice().getAddress(), Toast.LENGTH_SHORT).show();
}
} @Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
mText.setText("搜索蓝牙失败 errorCode:" + errorCode); }
};

这里我自己对搜索的结果操作为,

mLeDeviceListAdapter.addDevice(device);

加入到mLeDeviceListAdapter中去,这是一个listview的适配器,

5,蓝牙列表,结果显示的适配器代码,很简单,如下面。

// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator; public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflator = NewActivity.this.getLayoutInflater();
} public void addDevice(BluetoothDevice device) {
if (!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
} public void clearDevice() {
if (mLeDevices.size() > 0) {
mLeDevices.clear();
}
} public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
} public void clear() {
mLeDevices.clear();
} @Override
public int getCount() {
return mLeDevices.size();
} @Override
public Object getItem(int i) {
return mLeDevices.get(i);
} @Override
public long getItemId(int i) {
return i;
} @Override
public View getView(int i, View view, ViewGroup viewGroup) {
DeviceScanActivity.ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflator.inflate(R.layout.listitem_device, null);
viewHolder = new DeviceScanActivity.ViewHolder();
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (DeviceScanActivity.ViewHolder) view.getTag();
} BluetoothDevice device = mLeDevices.get(i);
final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 0)
viewHolder.deviceName.setText(deviceName);
else
viewHolder.deviceName.setText(R.string.unknown_device);
viewHolder.deviceAddress.setText(device.getAddress()); return view;
}
}

以上就是全部代码,下面文章,会从源码的角度分析,最新的开启,蓝牙和以前版本的对比,方便理解,在以后的文章会讲解如何连接嵌入式的蓝牙设备进行数据的传送。当然这里会由浅到深的体现出来。

android5.0 BLE 蓝牙4.0+浅析demo搜索(一)的更多相关文章

  1. Android5.0(Lollipop) BLE蓝牙4.0+浅析demo连接(三)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/23363591来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. Android5.0(L ...

  2. Android5.0(Lollipop) BLE蓝牙4.0+浅析code(二)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/23347612来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. Android5.0(L ...

  3. Android ble 蓝牙4.0 总结

    本文介绍Android ble 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用,如果手机系统版本API level < 18,也是用不了蓝牙4.0的哦 ...

  4. Android ble 蓝牙4.0 总结一

    本文介绍Android ble 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用,如果手机系统版本API level < 18,也是用不了蓝牙4.0的哦 ...

  5. 蓝牙BLE: 蓝牙4.0 BLE广播数据解析(转)

    BLE 设备工作的第一步就是向外广播数据.广播数据中带有设备相关的信息.本文主要说一下 BLE 的广播中的数据的规范以及广播包的解析. 1. 广播模式 BLE 中有两种角色 Central 和 Per ...

  6. IOS BLE蓝牙4.0

    前言: 自己做的项目里面有这么一个功能,总结归纳一下. 先导入必要的框架  CoreBluetooth.framework 在要用到蓝牙的文件里面导入以下头文件 #import <CoreBlu ...

  7. 10分钟完成一个最最简单的BLE蓝牙接收数据的DEMO

    这两天在研究蓝牙,网上有关蓝牙的内容非常有限,Github上的蓝牙框架也很少很复杂,为此我特地写了一个最最简单的DEMO,实现BLE蓝牙接收数据的问题, 不需要什么特定的UUID, 不需要什么断开重连 ...

  8. RF-BM-S02(V1.0)蓝牙4.0模块 使用手册

    一.产品概述 图1 RF-BM-S02纯硬件模块 RF-BM-S02是一款采用美国德州仪器TI 蓝牙4.0 CC2540作为核心处理器的高性能.超低功耗(Bluetooth Low Energy)射频 ...

  9. 蓝牙1.1、蓝牙1.2、蓝牙2.0(蓝牙2.0+EDR)区别

    蓝牙1.2版本相对于1.1版本: 1.Adaptive Frequency Hopping(AFH):即所谓适应性跳频技术,主要的功能是用来减少蓝牙产品与其它无线通讯装置之间所产生的干扰问题 2.Ex ...

随机推荐

  1. #学习笔记#——JavaScript 数组部分编程(七)

    24.柯里化 首先想解释一下,“柯里化”的意思, [在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结 ...

  2. 转 SQL集合函数中利用case when then 技巧

    SQL集合函数中利用case when then 技巧 我们都知道SQL中适用case when then来转化数据库中的信息 比如  select (case sex when 0 then '男' ...

  3. OpenCV —— 直方图与匹配

    直方图就是对数据进行统计,将统计值组织到一系列事先定义好的bin中.bin中的数值是从数据中计算出来的特征的统计量,这些数据可以是诸如梯度,方向,色彩或任何其他特征. 直方图获得是是数据分布的统计图 ...

  4. spark源码编译,本地调试

    1.下载源码 2.进入源码根据README.md编译源码,注意使用的是源码目录下的maven编译 3.用idea导入顶层pom文件 4.修改顶层pom文件和example下的pom文件,将scope的 ...

  5. at&&atq&&atrm---定时任务

    at放在 ls /var/spool/at/ 目录下 At的配置文件/etc/at.deny和/etc/at.allow 如果deny单独存在,则是deny以为的所有用户都可以使用at命令 如果all ...

  6. git把本地文件上传到github上的步骤

    1.清除clean 2.返回上一级cd .. 3.克隆仓库地址git clone+地址 4.添加忽悠文件vim .gitignore 5查看cat .gitignore 6.进入到test,并且添加所 ...

  7. 【Codeforces Round #427 (Div. 2) D】Palindromic characteristics

    [Link]:http://codeforces.com/contest/835/problem/D [Description] 给你一个字符串; 让你在其中找到1..k阶的回文子串; 并统计它们的数 ...

  8. UVALive 5292 Critical Links

    Critical Links Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Ori ...

  9. JavaScript--数据结构与算法之排序

    排序总结————常见的排序 常见的9中排序(冒泡,选择,插入(二分插入,希尔),归并,快速,堆,计数,基数,桶排序)可分为两类 比较排序:冒泡,选择,插入(二分插入,希尔),归并,堆,快速 非比较排序 ...

  10. 如果把父组件的数据实时的传递到子组件:用watch

    1.在子组件使用watch来监听传递给子组件的数据,然后更新子组件的数据. 2.watch和computed结合使用效果非常好. 参考链接:https://blog.csdn.net/zhouweix ...