# okble **Repository Path**: chinasoft3_ohos/okble ## Basic Information - **Project Name**: okble - **Description**: BLE实现库 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 2 - **Created**: 2021-05-28 - **Last Updated**: 2024-05-28 ## Categories & Tags **Categories**: harmonyos-communication **Tags**: None ## README # okble #### 项目介绍 - 项目名称:okble - 所属系列:openharmony的第三方组件适配移植 - 功能:简单易用的BLE library - 项目移植状态:主功能完成 - 调用差异:无 - 开发版本:sdk6,DevEco Studio 2.2 Beta1 - 基线版本:okble组件 Releases 1.1.3 #### 效果演示 ![okbleGIF图](https://gitee.com/chinasoft3_ohos/okble/raw/master/img/demo.gif "demo.gif") #### 安装教程 1.在项目根目录下的build.gradle文件中, ``` allprojects { repositories { maven { url 'https://s01.oss.sonatype.org/content/repositories/releases/' } } } ``` 2.在entry模块的build.gradle文件中, ``` dependencies { implementation('com.gitee.chinasoft_ohos:okble:1.0.0') ...... } ``` 在sdk6,DevEco Studio 2.2 Beta1下项目可直接运行 如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件, 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下 #### 使用说明 - 扫描外设 ```java OKBLEScanManager scanManager = new OKBLEScanManager(this); scanManager.setScanCallBack(scanCallBack); DeviceScanCallBack scanCallBack = new DeviceScanCallBack() { @Override public void onBLEDeviceScan(BLEScanResult device, int rssi) { LogUtils.e(" scan:"+device.toString()); } @Override public void onFailed(int code) { switch (code) { case DeviceScanCallBack.SCAN_FAILED_BLE_NOT_SUPPORT: showToast("该设备不支持BLE"); break; case DeviceScanCallBack.SCAN_FAILED_BLUETOOTH_DISABLE: showToast("请打开手机蓝牙"); break; case DeviceScanCallBack.SCAN_FAILED_LOCATION_PERMISSION_DISABLE: showToast("请授予位置权限以扫描周围的蓝牙设备"); break; case DeviceScanCallBack.SCAN_FAILED_LOCATION_PERMISSION_DISABLE_FOREVER: showToast("位置权限被您永久拒绝,请在设置里授予位置权限以扫描周围的蓝牙设备"); break; } } @Override public void onStartSuccess() { } }; ``` - 连接外设 ```java OKBLEDevice okbleDevice=new OKBLEDeviceImp(mContext,bleScanResult); //okbleDevice=new OKBLEDeviceImp(mContext); //okbleDevice.setBluetoothDevice(mBluetoothDevice); okbleDevice.addDeviceListener(this); okbleDevice.connect(true);//true表示连接断开后OKBLE的会自动重连 ``` - APP主动断开连接 ```java okbleDevice.disConnect(false); //false表示断开后不需要OKBLE的自动重连; disConnect断开后,可以使用okbleDevice.connect()重新连接回来 ``` - APP清除连接 ```java okbleDevice.remove(); //remove会清除连接的外设信息; 重新连接前需要重新调用setBleScanResult/setBluetoothDevice 来设置外设信息 ``` - 数据通讯 ```java // Read application.okbleDevice.addReadOperation(characteristicModel.getUuid(), new OKBLEOperation.ReadOperationListener() { @Override public void onReadValue(final byte[] value) { eventHandler.postTask(new Runnable() { @Override public void run() { addLog("onReadValue:" + OKBLEDataUtils.BytesToHexString(value) + " (" + new String(value) + ")"); } }); } @Override public void onFail(int code, final String errMsg) { eventHandler.postTask(new Runnable() { @Override public void run() { addLog("read onFail:" + errMsg); } }); } @Override public void onExecuteSuccess(OKBLEOperation.OperationType type) { } }); ``` ```java // Write application.okbleDevice.addWriteOperation(characteristicModel.getUuid(), value, new OKBLEOperation.WriteOperationListener() { @Override public void onWriteValue(final byte[] byteValue) { eventHandler.postTask(new Runnable() { @Override public void run() { addLog(" onWriteValue:" + byteValue); } }); } @Override public void onFail(int code, final String errMsg) { eventHandler.postTask(new Runnable() { @Override public void run() { addLog("write onFail:" + errMsg); } }); } @Override public void onExecuteSuccess(OKBLEOperation.OperationType type) { eventHandler.postTask(new Runnable() { @Override public void run() { addLog("write value execute success value length:" + OKBLEDataUtils.hexStringToBytes(value).length + " value:" + value); } }); } }); ``` ```java // Notify/Indicate application.okbleDevice.addNotifyOrIndicateOperation(characteristicModel.getUuid(), true, new OKBLEOperation.NotifyOrIndicateOperationListener() { @Override public void onNotifyOrIndicateComplete() { eventHandler.postTask(new Runnable() { @Override public void run() { addLog("onNotifyOrIndicateComplete"); } }); } @Override public void onFail(int code, final String errMsg) { eventHandler.postTask(new Runnable() { @Override public void run() { addLog("NotifyOrIndicate onFail:" + errMsg); } }); } @Override public void onExecuteSuccess(OKBLEOperation.OperationType type) { operationType[0] = type; } }); ``` - 发送大数据(应用场景1:OAD/空中升级) OAD原理其实就是把固件(如.bin文件)加载成byte[]数组,然后把byte[]数据分段发送给设备,以下代码演示了主要分段部分,OAD细节不展示(如每个包的整合),根据需求会有变化 ```java final int sendInterval=50;//每个包之间的发送间隔,有些手机会因为发送太快而导致蓝牙奔溃,OAD失败率很高,可以适当增大,如80-100; okbleDevice.setOperationInterval(sendInterval); byte[] oadValues=loadBytesFromFile(filePath); final int blockSize=20;//表示一个包发送20个字节 final int blockCount= (int) Math.ceil(oadValues.length*1.0f/blockSize);//发送的总包数 percent=0; for (int i=0;i ToastUtil.toast(mContext,"Advertising Success"); configServer();//配置service 和characteristic } @Override public void onStartFailure(int errorCode, String errMsg) { LogUtils.e("---onStartFailure errMsg:" + errMsg); int screenWidht = DisplayManager.getInstance().getDefaultDisplay(mContext).get().getAttributes().width; DirectionalLayout toastLayout = (DirectionalLayout) LayoutScatter.getInstance(mContext) .parse(ResourceTable.Layout_layout_toast, null, false); Text msg_toast = (Text) toastLayout.findComponentById(ResourceTable.Id_msg_toast); msg_toast.setText("Advertising Failed:"+errMsg); new ToastDialog(mContext) .setComponent(toastLayout) .setSize((int) (screenWidht*0.7), DirectionalLayout.LayoutConfig.MATCH_CONTENT).show(); } }); private void configServer() { OKBLEServiceModel serviceModel = new OKBLEServiceModel(CommonUUIDUtils.createCompleteUUIDByShortUUID("fff0")); OKBLECharacteristicModel characteristicModel = new OKBLECharacteristicModel(CommonUUIDUtils.createCompleteUUIDByShortUUID("fff1")); characteristicModel.setCanWrite(true); characteristicModel.setCanNotify(true); characteristicModel.setCanRead(true); OKBLECharacteristicModel characteristicModel_2 = new OKBLECharacteristicModel(CommonUUIDUtils.createCompleteUUIDByShortUUID("fff2")); characteristicModel_2.setCanWriteNoResponse(true); List characteristicModels = new ArrayList<>(); characteristicModels.add(characteristicModel); characteristicModels.add(characteristicModel_2); serverDevice.addCharacteristic(characteristicModels, serviceModel, new OKBLEServerOperation.BLEServerOperationListener() { @Override public void onAddCharacteristicFailed(int errorCode, String errorMsg) { LogUtils.e("onAddCharacteristicFailed:" + errorMsg); } @Override public void onAddCharacteristicSuccess() { LogUtils.e("onAddCharacteristicSuccess"); } }); } ``` - 扫描iBeacon设备 ```java OKBLEBeaconScanManager scanManager; scanManager=new OKBLEBeaconScanManager(this); scanManager.setBeaconScanCallback(scanCallBack); OKBLEBeaconManager.OKBLEBeaconScanCallback scanCallBack = new OKBLEBeaconManager.OKBLEBeaconScanCallback() { @Override public void onScanBeacon(OKBLEBeacon beacon) { refreshBtn.setEnabled(true); int value[] = scanedResults.put(beacon.getIdentifier(), beacon); new EventHandler(EventRunner.getMainEventRunner()).postTask(new Runnable() { @Override public void run() { if (value[1] == 1) { //这是新增数据 provider.notifyDataChanged(); } else { //这是重复数据,刷新rssi int index = value[0]; updatePosition(index); } } }); } }; ``` - APP模拟成iBeacon ```java OKBLEBeBeaconManager beBeaconManager; beBeaconManager = new OKBLEBeBeaconManager(this); beBeaconManager.setOKBLEBeBeaconListener(startBeaconListener); String uuid ="12345678-1234-1234-1234-1234567890ab"; int major=1; int minor=2; beBeaconManager.startIBeacon(uuid, major, minor); OKBLEBeBeaconManager.OKBLEStartBeaconListener startBeaconListener = new OKBLEBeBeaconManager.OKBLEStartBeaconListener() { @Override public void onStartSuccess() { eventHandler.postTask(new Runnable() { @Override public void run() { ToastUtil.toast(mContext,"start success"); } }); } @Override public void onStartFailure(String errMsg) { eventHandler.postTask(new Runnable() { @Override public void run() { ToastUtil.toast(mContext,"start failed:" + errMsg); } }); } }; ``` - 检测进入、退出iBeacon区域 ```java OKBLEBeaconManager beaconManager=new OKBLEBeaconManager(this); beaconManager.setRegionListener(this); String uuid ="12345678-1234-1234-1234-1234567890ab"; int major=1; int minor=2; OKBLEBeaconRegion okbleBeaconRegion=OKBLEBeaconRegion.getInstance(uuid,major,minor); //OKBLEBeaconRegion okbleBeaconRegion=OKBLEBeaconRegion.getInstance(uuid,major); //OKBLEBeaconRegion okbleBeaconRegion=OKBLEBeaconRegion.getInstance(uuid); beaconManager.startMonitoringForRegion(okbleBeaconRegion); @Override public void onEnterBeaconRegion(OKBLEBeaconRegion beaconRegion) { } @Override public void onExitBeaconRegion(OKBLEBeaconRegion beaconRegion) { } ``` #### 测试信息 CodeCheck代码测试无异常 CloudTest代码测试无异常 病毒安全检测通过 当前版本demo功能与原组件基本无差异 #### 版本迭代 - 1.0.0 #### 版权和许可信息 ``` Copyright 2018 a1anwang Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ```