Android 蓝牙BLE开发从官方源码demo开始(一)

2,882 阅读7分钟

1.前言

蓝牙在我们生活中扮演者许多重要的角色,蓝牙耳机、蓝牙音箱、蓝牙灯泡、蓝牙智能硬件等等!可见,蓝牙无处不在,而且也是物联网的基础纽带,它改变了我们的许多生活方式,给我们带来了许多益处。

前段时间我也简单地使用了小程序的蓝牙api操作,接下来我也要开始重新认识下Android蓝牙开发,蓝牙又分为经典蓝牙和BLE(低功耗蓝牙),这次我主要学习蓝牙BLE,所以我第一时间找了谷歌给我们提供了官方源码demo:

github.com/googlesampl…

2.权限

配置文件需要先声明蓝牙权限:

<!--蓝牙必须的权限-->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

除了蓝牙权限外,还有如下权限是声明程序是否可用于支持BLE或者支持出BLE外的设备;如果required=true,则应用只能在支持BLE的Android设备上安装运行,不支持BLE的设备将finish。

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

此外还有一个很关键的问题,不知道你们在开发中有没有遇到过呢?官方demo没有适配到这里。Android6.0以上的手机仅仅是添加如上蓝牙权限是不行的,这将会造成无法扫描到其他设备,针对这问题,果断查了资料,需要添加位置权限;

<!--android6.0以上使用蓝牙需要的权限,否则在Android6.0以上的手机扫描不到蓝牙设备-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

在Android6.0以上 位置相关的权限属于运行时权限,所以代码同时也要请求一下 让用户确认,这个就不多说了。

3.是否支持蓝牙BLE

在前面的权限也说了如果required=true,则应用只能在支持BLE的Android设备上安装运行,不支持BLE的设备将finish;

如果想在java代码上实现上面的逻辑也是可以的,官方demo如下:

/**使用此检查确定设备是否支持BLE。 然后你可以有选择地禁用与BLE相关的功能。*/
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
   Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
   finish();
}

4.初始化蓝牙适配器

初始化蓝牙适配器。 对于API级别18及更高级别,请通过BluetoothManager获取对BluetoothAdapter的引用。最后这里记得要判空!

        // 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();
            finish();
            return;
        }

5.当前设备是否已开启蓝牙

要想操作蓝牙,必须确保在设备上启用蓝牙。如果当前未启用蓝牙,因此我们可以触发Intent调用系统显示一个对话框,要求用户授予启用蓝牙的权限。

       if (!mBluetoothAdapter.isEnabled()) {
            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
        }

6.初始化listview列表适配器

这里目的就是将扫描到的蓝牙设备显示到listview列表上,然后用户就可以点击对应的item,程序就可以进行下一步操作。这一步骤可根据需要定制。

7.扫描

官方demo的扫描方法如下,如果要扫描的话就要传入true执行scanLeDvice(true)方法,然后蓝牙适配器就调用startLeScan()方法进行扫描,mLeScanCallback是扫描回调,下面会说到;执行扫描的同时开启了一个延时操作,时间到了就调用stopLeScan()方法停止扫描。

我觉得这里设置了一个延时停止扫描操作是非常友好的,因为扫描非常耗资源。

       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;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    invalidateOptionsMenu();
                }
            }, SCAN_PERIOD);
 
            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
        invalidateOptionsMenu();
    }
 

接下来就看看扫描的Callback回调吧,这个回调里面有个onLeScan方法,蓝牙扫描成功后的结果会返回此方法中,然后就可以处理BluetoothDevice拿到设备信息 最后展示到前面初始化的listview列表中,大概流程就是这样。

      // 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();
                }
            });
        }
    };

接着再看看这个onLeScan方法中的值吧!

第一个参数device,表示一个远程蓝牙设备,里面有它独有的蓝牙地址Address和Name等,所以后续需要进行连接蓝牙操作也需要用到这里获取的蓝牙Address;

第二个参数rssi表示扫描到的设备信号强度,这里应该可以用来判断距离的远近。

第三个参数scanRecord表示远程设备提供的广告记录的内容。

至此已经完成初始化配置、一些设备的判断逻辑和扫描操作了,如果能成功地扫描到设备并展示到界面上的话,下一步如果用户点击了列表,将进行蓝牙连接和相关的读写操作!

所以下一篇文章不出意外的话,就是继续学习Android蓝牙的连接和读写操作。 Android 蓝牙BLE开发从官方源码demo开始(二)

扫一扫关注我的微信公众号:程序猿在广东

my二维码.jpg