作者: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. 一台服务器安装运行多个Tomcat及注册服务

    项目需要,自己配置了一下,顺便分享出来. 1.下载对应版本Tomcat,这里下载Tomcat7.0.65.zip; 下载地址:http://archive.apache.org/dist/tomcat ...

  2. Python day字符串所有使用

    字符串所有的操作name = "dio"names = "my\t name is {Name} and i am a {job}"print(name.cap ...

  3. windows删除多余启动引导项

    方法1: 按快捷键win+r,打开运行界面,输入msconfig. 点击确定,进入系统配置,选择引导选项卡,如图: 选中你不需要的启动项,点击下面的删除按钮即可.删除完成之后点击确定,重启计算机就可以 ...

  4. UITouch 的使用

    直接上代码: touch 的四大状态.: // // TouchView.m // UI_practice_04 // // Created by lanouhn on 15/4/22. // Cop ...

  5. win7旗舰版怎么降级到专业版

    一.操作准备及注意事项 1.UltraISO光盘制作工具9.5 2.备份C盘及桌面文件 二.win7旗舰版改成专业版的步骤 1.当前系统为Win7 SP1 64位旗舰版: 2.按Win+R打开运行,输 ...

  6. TypeScript深入学习

    基础类型booleannumberstringstring[]//Array<string> 数组类型(ReadonlyArray<string>数组不能修改,也不允许被赋值给 ...

  7. 王小川分享AI

    王小川的分享:Link

  8. [JWT] JWT Signature With RS256 - Learn The Advantages Compared to HS256

    The advantage of RS256 over HS256 is RS256 no longer need to share the secret key between client and ...

  9. bootstrap课程10 从外部引入视频到页面用什么标签

    bootstrap课程10 从外部引入视频到页面用什么标签 一.总结 一句话总结:a.iframe标签:b.embed标签:c.video标签 1.bootstrap具有响应式特性的嵌入内容如何实现? ...

  10. Javascript和jquery事件--键盘事件KeyboardEvent

    Js和jq事件—键盘事件KeyboardEvent 键盘事件keydown,keypress和keyup,还需要涉及到一个文本事件textInput. keydown,keypress和keyup事件 ...