• android ble蓝牙开发略解


    Android 蓝牙4.0开发

     

    1、  权限和相关属性

    “android:required="true"表示apk只有在具有bluetooth_le属性的系统里运行,这个4.3之前android系统没有

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

      

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

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

     

    2、  程序开妈操作蓝牙之前,先判断ble是否支持

    if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {

                Toast.makeText(this,R.string.ble_not_supported, Toast.LENGTH_SHORT).show();

                finish();

            }

    3、  打开、关闭蓝牙

    先获取蓝牙的一个代理

    final BluetoothManager bluetoothManager =

                    (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);

           mBluetoothAdapter = bluetoothManager.getAdapter();

     

    发intent通知系统打开蓝牙

    if(!mBluetoothAdapter.isEnabled()) {

                if (!mBluetoothAdapter.isEnabled()){

                    Intent enableBtIntent = newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

                   startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

                }

            }

     

    也可以使用 enable 和disable函数来打开关闭

    4、  搜索ble设备

    mHandler.postDelayed(newRunnable() {

                    @Override

                    public void run() {

                        mScanning = false;

                       mBluetoothAdapter.stopLeScan(mLeScanCallback);

                       

                    }

                }, SCAN_PERIOD);

     

                mScanning = true;

               mBluetoothAdapter.startLeScan(mLeScanCallback);

     

    //SCAN_PERIOD是10000,表示每次的搜索时间为10秒

    需要注意的是mLeScanCallback,在4.3之前的api是通过注册广播来处理搜索时发生的一些事件,而支持ble的新的api中,是通过回调的方式来处理的,mLeScanCallback就是一个接口对象,看一下实现:

    privateBluetoothAdapter.LeScanCallback mLeScanCallback =

                newBluetoothAdapter.LeScanCallback() {

     

            @Override

            public void onLeScan(finalBluetoothDevice device, int rssi, byte[] scanRecord) {

                runOnUiThread(new Runnable() {

                    @Override

                    public void run() {

                        mLeDeviceListAdapter.addDevice(device);

                       mLeDeviceListAdapter.notifyDataSetChanged();

                    }

                });

            }

    };

    5、  连接

    4.3之前的api是通过socket方式在蓝牙之间互相通信,连接的结果是返回一个socket对象

    在支持4.0蓝牙的新的api中,返回的是BluetoothGatt对象

    可以将BluetoothGatt对象看成是远程设备的一个代理

    mBluetoothGatt = device.connectGatt(this, false,mGattCallback);

     

    mGattCallback是一个抽象类对象,之前的广播形式,在新的api中都改成了回调

    BluetoothGattCallback抽象类,只有9个方法,字面意思就都可以看懂,在处理连接事件上,需要处理方法:

    public voidonConnectionStateChange(BluetoothGatt gatt, int status,

                                            intnewState)

     

    条件:if (newState ==BluetoothProfile.STATE_CONNECTED)

    else if (newState ==BluetoothProfile.STATE_DISCONNECTED)分别表示已连接和已断开

    6、 通讯

    这一点与之前形式上完全不一样了

    BLE分为三部分Service、Characteristic、Descriptor,这三部分都由UUID作为唯一标示符。一个蓝牙4.0的终端可以包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。

    在连接上某个终端后,可以将其每个结点的UUID全部打印出来,但每个结点不是都能读写。

    一般来说,Characteristic是手机与BLE终端交换数据的关键,Characteristic有较多的跟权限相关的字段,例如PERMISSION和PROPERTY,而其中最常用的是PROPERTY,本文所用的BLE蓝牙模块竟然没有标准的Characteristic的PERMISSION。Characteristic的PROPERTY可以通过位运算符组合来设置读写属性,例如READ|WRITE、READ|WRITE_NO_RESPONSE|NOTIFY,因此读取PROPERTY后要分解成所用的组合

    我是这么去和ble终端通信的:

    得到某个service的对象

    BluetoothGattService linkLossService =mBluetoothGatt

                                          .getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));

    一般说来,ble设备都带有几个标准的服务,其UUID已经定义好了,这些结点里的值只能读了,因为我一个一个试过了,终于找到了我的设备里可以读写的服务,其中49535343-fe7d-4ae5-8fa9-9fafd205e455就是对应这个服务的

     

    获取此服务结点下的某个Characteristic对象

    BluetoothGattCharacteristic alertLevel =linkLossService.getCharacteristic(UUID.fromString("49535343-8841-43f4-a8d4-ecbe34729bb3"));

    一般供应商会给出多个Characteristic,你需要找到到底哪个才是让你去写的,怎么找需要看对应的终端的一些开发文档之类的,在这里我经过测试已经找到我要的了

     

    设置要写的值

    alertLevel.setValue(values_on);

    这里的values_on是一个byte数组

     

    status = mBluetoothGatt.writeCharacteristic(alertLevel);

    status如果为true,表示写操作已经成功执行,BluetoothGattCallback抽象类的一个方法会被执行,如果刚好你又重写了这个方法,就可以打印一些消息了

    public void onCharacteristicWrite(BluetoothGatt gatt,

               BluetoothGattCharacteristiccharacteristic, int status)

     

    读某个Characteristic

    public void readCharacteristic(BluetoothGattCharacteristiccharacteristic) {

            if (mBluetoothAdapter == null || mBluetoothGatt == null) {

                Log.w(TAG, "BluetoothAdapter not initialized");

                return;

            }

            mBluetoothGatt.readCharacteristic(characteristic);

    }

     

    如果成功,数据会在下面的方法回调中传进来

    public voidonCharacteristicRead(BluetoothGatt gatt,

                                            BluetoothGattCharacteristic characteristic,

                                             int status)

     

    当终端有数据要传过来的时候,表面上正常的话,手机这边下面的方法会被调用

    public voidonCharacteristicRead(BluetoothGatt gatt,

                                            BluetoothGattCharacteristic characteristic,

                                             intstatus)

    这个也是可以控制的,设置descriptor的value不同,可以控制这个重写的方法是否会被调用,没有测试其他的设备,感觉这个应该是会对应不同的设备,具体设置的地方会有不同,在我这边是这么操作的:

    public void enableNotification(boolean b)

        {

        if(b)

        {

                   BluetoothGattService service =mBluetoothGatt

                                 .getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));

                 BluetoothGattCharacteristicale =service.getCharacteristic(UUID.fromString("49535343-1E4D-4BD9-BA61-23C647249616"));

                 booleanset = mBluetoothGatt.setCharacteristicNotification(ale, true);

                 Log.d(TAG," setnotification = " + set);

                 BluetoothGattDescriptordsc =ale.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));

                 byte[]bytes = {0x01,0x00};

            dsc.setValue(bytes);

            boolean success =mBluetoothGatt.writeDescriptor(dsc);

            Log.d(TAG, "writing enabledescriptor:" + success);

        }

        else

        {

                   BluetoothGattService service =mBluetoothGatt

                                 .getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));

                 BluetoothGattCharacteristicale =service.getCharacteristic(UUID.fromString("49535343-1E4D-4BD9-BA61-23C647249616"));

                 booleanset = mBluetoothGatt.setCharacteristicNotification(ale, false);

                 Log.d(TAG," setnotification = " + set);

                 BluetoothGattDescriptordsc =ale.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));

                 byte[]bytes = {0x00, 0x00};

            dsc.setValue(bytes);

            boolean success =mBluetoothGatt.writeDescriptor(dsc);

            Log.d(TAG, "writing enabledescriptor:" + success);

        }

       

        }

    7、 总结

    网上的一些资料大都以上面的命名来标识自己的文档,有必要解释一下,应该分开来看这个命题:

    android指的安装的4.3及以上版本的android系统的设备

    4.0蓝牙指的蓝牙芯片使用4.0协议的设备

    这种开发的一种标准用处是:用4.3以上android版本的手机,与4.0蓝牙穿戴式设备进行通信

    按网上的一种中央与周边的说法,手机就是中央,4.0蓝牙设备就中周边

    如果要开发4.0蓝牙,应该知道4.0蓝牙具有高速、低功耗的优点,这些优点对手机的提升不大,但对其他一些终端设备的提升就比较大。

    有意思的是,android对与4.0蓝牙通信的封装,不需要本身设备的蓝牙芯片是4.0协议的蓝牙芯片

    于是android 蓝牙4.0开发的这么一个“大环境”下的真实情景就是:一个没有必要拥有蓝牙4.0协议的蓝牙芯片的android4.3以上系统的手机,与一些4.0蓝牙协议的蓝牙芯片设备终端的故事

    以上是一些事实,以下是一些猜想

    1、 蓝牙4.0与之前版本协议之间可以通讯,说明:4.0蓝牙协议并不是修改的无线波的调制与解调,而是修改的数据的组成

    2、 对蓝牙4.0协议的支持,是由google提出的,而不是各个手机厂商提出的,说明:android系统在软件上可以一致对待不同的蓝牙芯片,不同的蓝牙芯片对同一段数据的调制解调结果是一样的,于是在这段数据通过串口传到手机主控的时候,也是一样的,在这个环境里,蓝牙芯片只是一个调制解调器,android封装了对数据全部的处理。

  • 相关阅读:
    什么时候应该使用C#的属性
    Unicode和字符集小结
    C#编译器怎么检查代码是否会执行
    C#中如何操作2个list
    用Windbg来看看CLR的JIT是什么时候发生的
    bzoj-1579: [Usaco2009 Feb]Revamping Trails 道路升级
    次小生成树
    bzoj-3687: 简单题
    bzoj-3669: [Noi2014]魔法森林
    uva 11732 (trie树)
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4683685.html
Copyright © 2020-2023  润新知