Android Bluetooth(蓝牙) - BLE开发

目录

1.何为BLE?

2.基础术语和概念

3.初始化配置

3.1.权限

3.2.是否支持蓝牙BLE

3.3.初始化蓝牙适配器

3.4.开启蓝牙

3.5.初始化ListView列表适配器

3.6.发现BLE设备(扫描设备)

4.创建BluetoothLeService服务类并初始化蓝牙连接

4.1.创建服务

4.2.初始化蓝牙

4.3.执行connect()和connectGatt

4.4. BluetoothGattCallback 回调

4.5.设置特征值变化通知

4.6.读取特征值

4.7.写入特征值

4.8.获取已连接蓝牙的所有服务

4.9.读取蓝牙设备的RSSI值

4.10.发送广播

5.广播监听器:

5.1注册/取消注册广播监听

5.2.广播回调监听

5.3.处理数据的输入和获取

5.4.数据的接收

5.5.发送数据

参考文献:

1.何为BLE?


首先得说明什么是低功耗蓝牙BLE,BLE的全称为Bluetooth low energy(或称Blooth LE,BLE),从英文全称便可以知晓其是一种低功耗的蓝牙技术,是蓝牙技术联盟设计和销售的一种个人局域网技术,旨在用于医疗保健、运动健身、信标、安防、家庭娱乐等领域的新兴应用。相较经典蓝牙,低功耗蓝牙旨在保持同等通信范围的同时显著降低功耗和成本。而正因为其低功耗的优点,可以让Android APP可以具有与低功耗要求的BLE设备通信,如近距离传感器、心脏速率监视器、健身设备等

2.基础术语和概念


在正式开发前,要对基本的蓝牙的术语和概念要有个大致的认识,因为我本人学习的也不长,就是个简单的总结先:

  • Generic Attribute Profile:简称为GATT,现在的低功耗BLE的连接都是建立在GATT协议之上实现的,蓝牙技术联盟规定了许多低功耗设备的配置文件,配置文件是设备如何在特定的应用程序在工作的规格,而一个设备中可以有多个配置文件。
  • Generic Access Profile:Profile可以视为一种规范,一个标准的通信协议,它存在于从机中,蓝牙技术联盟规定了一些标准的profile,例如防丢器 ,心率计等。每个profile中会包含多个service,每个service代表从机的一种能力。
  • Service:服务,在BLE从机中,可以有多个服务,例如:电量信息服务,而Service中又有多个Characteristic特征值,而每个具体的特征值才是BLE通信的重点,例如在1电量信息服务中,当前的电量为80%,所以会通过电量的特征值存在从机的profile里,这样主机就可以通过这个特征值来读取80%这个数据
  • Characteristic:特征值,ble主从机通信都是通过特征值实现的,类似于标签key,可以通过这个key值来获取信息和数据
  • UUID:统一识别码,服务和特征值都需要一个唯一的UUID来标识整理,而每个从机都会有一个叫做profile的东西存在,不管是上面的自定义的simpleprofile,还是标准的防丢器profile,他们都是由一些列service组成,然后每个service又包含了多个characteristic,主机和从机之间的通信,均是通过characteristic来实现。

3.初始化配置


讲完了大概的概念之后便是基本的操作了,以下内容会结合代码和流程图进行展示

3.1.权限


想要使用BLE开发,就得先获得蓝牙必要的权限,需要先在AndroidManifest.xml中设置权限

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>



如果想声明你的app只为具有BLE的设备提供,在manifest文件中包括:

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


除此之外,如果是Android 6.0以上的手机仅仅是添加以上的蓝牙权限是不足的,这样会造成无法扫描到其他设备,因而还需要添加位置权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" />



3.2.是否支持蓝牙BLE


required=true只能是让支持BLE的Android设备上安装运行,不支持的则不行,如果想在Java实现上述功能,可以通过下述代码:

// 手机硬件支持蓝牙

if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
    finish();
}


3.3.初始化蓝牙适配器


所有的蓝牙活动都需要蓝牙适配器,BluetoothAdapter代表设备本身的蓝牙适配器。整个系统只有一个蓝牙适配器,而且app需要蓝牙适配器与系统交互。下面的代码片段显示了如何得到适配器。

注意该方法使用getSystemService()返回BluetoothManager,然后将其用于获取适配器的一个实例。Android 4.3(API 18)引入BluetoothManager

final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
else
    mBluetoothAdapter = bluetoothManager.getAdapter();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();



3.4.开启蓝牙


要操作蓝牙,必须先在设备中开启蓝牙。如果当前未启用蓝牙,则可以通过触发一个Intent调用系统显示一个对话框来要求用户启用蓝牙权限// 打开蓝牙权限

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



3.5.初始化ListView列表适配器

/**
  * @Description: TODO<自定义适配器Adapter,作为listview的适配器>
  */
private class LeDeviceListAdapter extends BaseAdapter {
    private ArrayList<BluetoothMessage> mLeDevices;
    
    private LayoutInflater mInflator;
    
    public LeDeviceListAdapter()
    {
        super();
        //rssis = new ArrayList<Integer>();
        mLeDevices = new ArrayList<BluetoothMessage>();
        mInflator = getLayoutInflater();
     }
    public void addDevice(BluetoothMessage device)
    {
        for (BluetoothMessage mLeDevice : mLeDevices) {
            
            if(mLeDevice.getDevice().getAddress().equals(device.getDevice().getAddress())){
                return;    
            }    
        }    
        mLeDevices.add(device);
        //rssis.add(rssi);
    }
    public BluetoothMessage getDevice(int position)
    {
        return mLeDevices.get(position);
    }
    public void clear()
    {
        mLeDevices.clear();
        //rssis.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;
    }

    /**  
      * 重写getview
      *
      * **/
   @Override
    public View getView(int i, View view, ViewGroup viewGroup)
    {
        // General ListView optimization code.
        // 加载listview每一项的视图
        BluetoothMessage bluetoothMessage = mLeDevices.get(i);
        return view;
    }
}


3.6.发现BLE设备(扫描设备)


如果要发现BLE设备,使用startLeScan()方法进行扫描,扫描的话就要传入true执行scanLeDvice(true)方法,然后蓝牙适配器就调用startLeScan()方法进行扫描,LeScanCallback是扫描回调,也就是返回扫描结果。

3.6.1.扫描结果:

private void scanLeDevice(final boolean enable) {
    if (mBluetoothAdapter == null){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        else {
            BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();
        }
      }
    if (mBluetoothLeScanner == null){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        }
    if (enable) {
        // Stops scanning after a pre-defined scan period.
        mHandler.postDelayed(new Runnable()
        {
            @Override
            public void run()
            {
                mScanning = false;
                scan_flag = true;
                scan_btn.setText("扫描设备");
                Log.i("SCAN", "stop.....................");
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                    mBluetoothLeScanner.stopScan(mScanCallback);
                else
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
             }
         }, SCAN_PERIOD);
         /* 开始扫描蓝牙设备,带mLeScanCallback 回调函数 */
            Log.i("SCAN", "begin.....................");
            mScanning = true;
            scan_flag = false;
            scan_btn.setText("停止扫描");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                mBluetoothLeScanner.startScan(mScanCallback);
            else
                mBluetoothAdapter.startLeScan(mLeScanCallback);
     } else {
            Log.i("Stop", "stoping................");
            mScanning = false;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                mBluetoothLeScanner.stopScan(mScanCallback);
            else
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            scan_flag = true;
      }
}


3.6.2.回调方法:
在这里回家上面的扫描方法的扫描结果回调,也就是传回来。其中在onLeScan方法是重点,蓝牙扫描成功后的结果会返回此方法中,然后就可以处理BluetoothDevice拿到设备信息,最后展示到前面初始化的ListView列表中:

第一个参数device,表示一个远程蓝牙设备,里面有它独有的蓝牙地址Address和Name等,所以后续需要进行连接蓝牙操作也需要用到这里获取的蓝牙Address
第二个参数rssi表示扫描到的设备信号强度,这里应该可以用来判断距离的远近。
第三个参数scanRecord表示远程设备提供的广告记录的内容。

// 这个是官方demo的源码
// 是扫描的Callback的回调,其中的onLeScan方法,蓝牙扫描成功之后会将结果会返回此方法中
// 然后就可以处理BluetoothDevice拿到设备信息 最后展示到前面初始化的listview列表中
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
{
    @Override
    public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord)
    {
        // TODO Auto-generated method stub
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                // 讲扫描到设备的信息输出到listview的适配器
                BluetoothMessage bluetoothMessage = new BluetoothMessage(device);
                mleDeviceListAdapter.addDevice(bluetoothMessage);
                mleDeviceListAdapter.notifyDataSetChanged();
             }
         });
    }
};


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值