积分1493 / 贡献20

提问16答案被采纳59文章38

[经验分享] 写一个简单的OpenHarmony蓝牙应用 原创

深开鸿_王石 显示全部楼层 发表于 2023-12-18 16:26:11

此文件就是介绍OpenHarmony中的蓝牙接口和如何自己开发一个简单的蓝牙应用程序。

OpenHarmony蓝牙接口简介

接口名称 参数 返回值 作用
enableBluetooth () boolean 开启蓝牙
disableBluetooth () boolean 关闭蓝牙
getState () BluetoothState:enum 获取蓝牙状态
setLocalName (name: string) boolean 设置蓝牙名称
getLocalName () string 获取蓝牙名称
setBluetoothScanMode (mode: ScanMode, duration: number) boolean 设置蓝牙扫描模式
startBluetoothDiscovery () boolean 发现蓝牙
pairDevice (deviceId: string) boolean 配对设备
on.pinRequired (type: "pinRequired", callback: Callback<PinRequiredParam>) void 侦听配对请求事件
disableBluetooth () boolean 关闭蓝牙
  • getState
enum BluetoothState {
   /** Indicates the local Bluetooth is off */
   STATE_OFF = 0,
   /** Indicates the local Bluetooth is turning on */
   STATE_TURNING_ON = 1,
   /** Indicates the local Bluetooth is on, and ready for use */
   STATE_ON = 2,
   /** Indicates the local Bluetooth is turning off */
   STATE_TURNING_OFF = 3,
   /** Indicates the local Bluetooth is turning LE mode on */
   STATE_BLE_TURNING_ON = 4,
   /** Indicates the local Bluetooth is in LE only mode */
   STATE_BLE_ON = 5,
   /** Indicates the local Bluetooth is turning off LE only mode */
   STATE_BLE_TURNING_OFF = 6
  • setBluetoothScanMode
enum ScanMode {
   /** Indicates the scan mode is none */
   SCAN_MODE_NONE = 0,
   /** Indicates the scan mode is connectable */
   SCAN_MODE_CONNECTABLE = 1,
   /** Indicates the scan mode is general discoverable */
   SCAN_MODE_GENERAL_DISCOVERABLE = 2,
   /** Indicates the scan mode is limited discoverable */
   SCAN_MODE_LIMITED_DISCOVERABLE = 3,
   /** Indicates the scan mode is connectable and general discoverable */
   SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE = 4,
   /** Indicates the scan mode is connectable and limited discoverable */
   SCAN_MODE_CONNECTABLE_LIMITED_DISCOVERABLE = 5
}

OpenHarmony典蓝牙配对流程

<pre class="md-fences md-end-block md-diagram md-fences-advanced ty-contain-cm modeLoaded" spellcheck="false" lang="mermaid" cid="n72" mdtype="fences" mermaid-type="graph"><div class="md-diagram-panel md-fences-adv-panel"><div class="md-diagram-panel-header"></div><div class="md-diagram-panel-preview"><svg id="mermaidChart0" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="61.59375" viewBox="0 0 587.921875 61.59375" class="in-text-selection"><g><g class="output"><g class="clusters"></g><g class="edgePaths"><g class="edgePath LS-开启蓝牙 LE-设置发现模式" id="L-开启蓝牙-设置发现模式"><path class="path" d="M92,30.796875L117,30.796875L142,30.796875" marker-end="url(#arrowhead17)"></path><defs><marker id="arrowhead17" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath"></path></marker></defs></g><g class="edgePath LS-设置发现模式 LE-注册pinRequest" id="L-设置发现模式-注册pinRequest"><path class="path" d="M258,30.796875L283,30.796875L308,30.796875" marker-end="url(#arrowhead18)"></path><defs><marker id="arrowhead18" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath"></path></marker></defs></g><g class="edgePath LS-注册pinRequest LE-配对设备" id="L-注册pinRequest-配对设备"><path class="path" d="M445.921875,30.796875L470.921875,30.796875L495.921875,30.796875" marker-end="url(#arrowhead19)"></path><defs><marker id="arrowhead19" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath"></path></marker></defs></g></g><g class="edgeLabels"><g class="edgeLabel" transform=""><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml"><span id="L-L-开启蓝牙-设置发现模式" class="edgeLabel L-LS-开启蓝牙' L-LE-设置发现模式"></span></div></foreignObject></g></g><g class="edgeLabel" transform=""><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml"><span id="L-L-设置发现模式-注册pinRequest" class="edgeLabel L-LS-设置发现模式' L-LE-注册pinRequest"></span></div></foreignObject></g></g><g class="edgeLabel" transform=""><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml"><span id="L-L-注册pinRequest-配对设备" class="edgeLabel L-LS-注册pinRequest' L-LE-配对设备"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="flowchart-开启蓝牙-4" transform="translate(50,30.796875)"><rect rx="0" ry="0" x="-42" y="-22.796875" width="84" height="45.59375" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-32,-12.796875)"><foreignObject width="64" height="25.59375"><div xmlns="http://www.w3.org/1999/xhtml">开启蓝牙</div></foreignObject></g></g></g><g class="node default" id="flowchart-设置发现模式-5" transform="translate(200,30.796875)"><rect rx="0" ry="0" x="-58" y="-22.796875" width="116" height="45.59375" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-48,-12.796875)"><foreignObject width="96" height="25.59375"><div xmlns="http://www.w3.org/1999/xhtml">设置发现模式</div></foreignObject></g></g></g><g class="node default" id="flowchart-注册pinRequest-6" transform="translate(376.9609375,30.796875)"><rect rx="0" ry="0" x="-68.9609375" y="-22.796875" width="137.921875" height="45.59375" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-58.9609375,-12.796875)"><foreignObject width="117.921875" height="25.59375"><div xmlns="http://www.w3.org/1999/xhtml">注册pinRequest</div></foreignObject></g></g></g><g class="node default" id="flowchart-配对设备-7" transform="translate(537.921875,30.796875)"><rect rx="0" ry="0" x="-42" y="-22.796875" width="84" height="45.59375" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-32,-12.796875)"><foreignObject width="64" height="25.59375"><div xmlns="http://www.w3.org/1999/xhtml">配对设备</div></foreignObject></g></g></g></g></g></g></svg></div><div class="md-diagram-panel-error"></div></div></pre>

  1. 开启蓝牙
    //开蓝牙
    ListItem() {
        TitleComponent({ 
            title: "enableBluetooth",                                                            //显示功能的名称
            bgColor: this.currentClick === 0 ? $r('app.color.font_color_007DFF') :  $r('app.color.white_bg_color')
        });                                                                                     //点击后颜色变化
    }
    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })   
        .onClick(() => {                                                                        //点击事件                
        if (this.btEnable) {                                                                    //判断蓝牙是否已经打开
            this.message = '蓝牙已经使能';                                                  
            return;
        }
        let ret = BluetoothModel.enableBluetooth();                                             //打开蓝牙
        this.btEnable = ret;                                                               //如果启用了蓝牙,则返回true,否则返回false
        AppStorage.SetOrCreate('bluetoothIsOn', this.btEnable);                                 //存储蓝牙打开的结果,方便调用
        AppStorage.SetOrCreate('currentClick', this.currentClick);
        this.message = "蓝牙使能执行结果:" + ret;                                                   //输出结果
    })
  2. 设置发现模式
    ListItem() {
        TitleComponent({
            title: "setBluetoothScanMode",                                                       //显示功能的名称
            bgColor: this.currentClick === 6 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
        });                                                                                      //点击后颜色变化
    }
    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
        .onClick(() => {                                                                         //点击事件   
        this.currentClick = 6;
        if (this.btEnable) {                                                                     //判断蓝牙是否已经打开 
            retObj = {mod: 0, duration: -1}                                  //mode表示要设置的蓝牙扫描模式{@link ScanMode}。                                                                                  //*@param duration指示主机可发现的持续时间(秒)。
            setLocalNameRet = BluetoothModel.setBluetoothScanMode(mode, dur);
            if (setLocalNameRet) {
                AppStorage.SetOrCreate('setScanModeRet', setLocalNameRet);
                retObj.mod = mode;
                retObj.duration = dur; 
            } else {                                                          //如果设置了蓝牙扫描模式,返回true,否则返回false。
                console.info("BluetoothModel.setBluetoothScanMode failed!")
                onsole.info("BluetoothModel.setBluetoothScanMode success!", retObj)             
                this.message = "setBluetoothScanMode执行" + this.setLocalNameRet ? '成功' : '失败';
            } 
        }else {
            this.message = "蓝牙未使能";
        }
    })
  3. 注册pinRequest
    ListItem() {
        TitleComponent({
            title: "btPinRequired"                                                                //显示功能的名称
            bgColor: this.currentClick === 18 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
        });                                                                                       //点击后颜色变化
    }
    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
        .onClick(() => {                                                                            //点击事件
        if (!this.btEnable) {                                                                   //判断蓝牙是否已经打开 
            this.message = "蓝牙未使能"; 
            return;
        }
        if (this.isPinRequiredClick) {                                                //判断监听是否开启,即为一个“开关”,并存储数据
            bluetooth.off('pinRequired', () => {                                   
            })
            this.message = 'on:pinRequired监听已关闭,再次点击将开启监听';
            this.isPinRequiredClick = false;
            AppStorage.SetOrCreate('on_pinRequired', this.btPinRequired);
            return;
        }
        this.isPinRequiredClick = true;
        AppStorage.SetOrCreate('on_pinRequired', this.btPinRequired);                //type要侦听的配对请求事件的类型为:pinRequired
        this.pinMessage = 'PIN: ';
        bluetooth.on('pinRequired', (data) => {                                           //callback回调用于侦听配对请求事件。
            this.pinMessage = 'PIN: ';
            this.pinMessage += data.pinCode;
        })
        this.message = 'on:pinRequired监听已启动,再次点击将关闭监听。';
    })
  4. 配对设备
    ListItem() {
        TitleComponent({ 
            title: "pairDevice",                                                                   //显示功能的名称  
            bgColor: this.currentClick === 10 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
        });                                                                                        //点击后颜色变化
    } 
    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
        .onClick(() => {                                                                         //点击事件
        if (!this.btEnable) {                                                                   //判断蓝牙是否已经打开 
            this.message = '蓝牙未使能';
            return;
        }
        if (this.deviceId == '') {                                                      //deviceId为要配对的远程设备的地址
            this.message = "请输入目标设备的MAC";                                          //若为空,请输入目标MAC
            return;
        } else {
            this.pairDevice(this.deviceId);                                          //如果配对过程已启动,则返回true,否则返回false
        }
    })

OpenHarmony经典蓝牙设备发现流程

<pre class="md-fences md-end-block md-diagram md-fences-advanced ty-contain-cm modeLoaded" spellcheck="false" lang="mermaid" cid="n87" mdtype="fences" mermaid-type="graph"><div class="md-diagram-panel md-fences-adv-panel"><div class="md-diagram-panel-header"></div><div class="md-diagram-panel-preview"><svg id="mermaidChart1" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="61.59375" viewBox="0 0 432 61.59375" class="in-text-selection"><g><g class="output"><g class="clusters"></g><g class="edgePaths"><g class="edgePath LS-开启蓝牙 LE-设置发现模式" id="L-开启蓝牙-设置发现模式"><path class="path" d="M92,30.796875L117,30.796875L142,30.796875" marker-end="url(#arrowhead31)"></path><defs><marker id="arrowhead31" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath"></path></marker></defs></g><g class="edgePath LS-设置发现模式 LE-开始蓝牙发现" id="L-设置发现模式-开始蓝牙发现"><path class="path" d="M258,30.796875L283,30.796875L308,30.796875" marker-end="url(#arrowhead32)"></path><defs><marker id="arrowhead32" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath"></path></marker></defs></g></g><g class="edgeLabels"><g class="edgeLabel" transform=""><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml"><span id="L-L-开启蓝牙-设置发现模式" class="edgeLabel L-LS-开启蓝牙' L-LE-设置发现模式"></span></div></foreignObject></g></g><g class="edgeLabel" transform=""><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml"><span id="L-L-设置发现模式-开始蓝牙发现" class="edgeLabel L-LS-设置发现模式' L-LE-开始蓝牙发现"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="flowchart-开启蓝牙-11" transform="translate(50,30.796875)"><rect rx="0" ry="0" x="-42" y="-22.796875" width="84" height="45.59375" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-32,-12.796875)"><foreignObject width="64" height="25.59375"><div xmlns="http://www.w3.org/1999/xhtml">开启蓝牙</div></foreignObject></g></g></g><g class="node default" id="flowchart-设置发现模式-12" transform="translate(200,30.796875)"><rect rx="0" ry="0" x="-58" y="-22.796875" width="116" height="45.59375" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-48,-12.796875)"><foreignObject width="96" height="25.59375"><div xmlns="http://www.w3.org/1999/xhtml">设置发现模式</div></foreignObject></g></g></g><g class="node default" id="flowchart-开始蓝牙发现-13" transform="translate(366,30.796875)"><rect rx="0" ry="0" x="-58" y="-22.796875" width="116" height="45.59375" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-48,-12.796875)"><foreignObject width="96" height="25.59375"><div xmlns="http://www.w3.org/1999/xhtml">开始蓝牙发现</div></foreignObject></g></g></g></g></g></g></svg></div><div class="md-diagram-panel-error"></div></div></pre>

  1. 开启蓝牙(同上)

  2. 设置发现模式(同上)

  3. 开始蓝牙发现

    ListItem() {
        TitleComponent({
            title: "startBluetoothDiscovery",                                                              //显示功能的名称  
            bgColor: this.currentClick === 8 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
        });                                                                                                //点击后颜色变化
    }
    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
        .onClick(() => {//点击事件
        LogUtil.info(this.TAG_PAGE + 'startBluetoothDiscovery 111');
        if (!this.btEnable) {                                                                   //判断蓝牙是否已经打开 
            this.message = '蓝牙未使能';
            return;
        }
        Router.push({ uri: PAGE_URI_DEVICE_FOUND_MODE });                                      //搜索发现蓝牙的分界面
    })
  4. 搜索发现蓝牙的分界面

    Scroll() {
        Column() {
            if (this.isOn) {
                PairedDeviceComponent({                                                      //显示已配对的设备
                    controller: this.deviceController
                })
                AvailableDeviceComponent({                                                   //显示可被配对的设备                      
                    controller: this.deviceController 
                })
            }
        }
        .width(ConfigData.WH_100_100)
    }
    
    //PairedDeviceComponent
    
    build() {
        Column() {
            if (this.pairedDevices && this.pairedDevices.length > 0) {
                // paired devices title
                Row() {
                    Text($r('app.string.bluetooth_paired_devices'))                          //已配对的设备
                        .fontSize($r('app.float.font_14'))
                        .fontColor($r('app.color.font_color_182431'))
                }
                .width(ConfigData.WH_100_100)
                    .padding({
                    left: $r('app.float.distance_24'),
                    top: $r('app.float.distance_19_5'),
                    bottom: $r('app.float.distance_9_5')
                })
                List() {
                    // paired devices list
                    ForEach(this.pairedDevices, (item: BluetoothDevice, index: number) => {
                        ListItem() {
                            Row() {
                                PairedItem({
                                    name: item.deviceName,
                                    type: item.deviceType,
                                    state: item.connectionState.toString(),
                                    mac: item.deviceId
                                })
                            }
                            .width(ConfigData.WH_100_100)
                                .borderRadius($r("app.float.radius_24"))
                                .padding($r('app.float.distance_4'))
                                .backgroundColor($r("app.color.white_bg_color"))
                                .onClick(() => {
                                this.itemClicked(item);
                            })
                        }
                    }, item => JSON.stringify(item));
                }
                .height(200)
                    .divider({
                    strokeWidth: 1,
                    color: $r('app.color.color_E3E3E3_grey'),
                    startMargin: $r('app.float.wh_value_52'),
                    endMargin: $r('app.float.wh_value_12')
                })
                    .backgroundColor($r("app.color.white_bg_color"))
                    .borderRadius($r("app.float.radius_24"))
            }
        }
    }
    
    //AvailableDeviceComponent
    
    build() {
        Column() {
            Row() {
                // available devices title
                Text($r('app.string.bluetooth_available_devices'))                            //可用设备
                    .fontSize($r('app.float.font_14'))
                    .fontColor($r('app.color.font_color_182431'))
                    .width(ConfigData.WH_100_100)
                    .padding({
                    left: $r('app.float.distance_24'),
                    top: $r('app.float.distance_19_5'),
                    bottom: $r('app.float.distance_9_5')
                })
                Blank()
    
                // bluetooth discovering
                if (this.isDeviceDiscovering) {
                    DiscoveringAnimatorComponent()
                }
            }
            .width(ConfigData.WH_100_100)
    
            if (this.availableDevices && this.availableDevices.length >= 1) {
                Scroll() {
                    List() {
                        // paired devices list
                        ForEach(this.availableDevices, (item: BluetoothDevice) => {
                            ListItem() {
                                Row() {
                                    AvailableItem({
                                        name: item.deviceName,
                                        type: item.deviceType,
                                        state: item.connectionState.toString(),
                                        mac: item.deviceId
                                    })
                                }
                                .width(ConfigData.WH_100_100)
                                    .borderRadius($r("app.float.radius_24"))
                                    .padding($r('app.float.distance_4'))
                                    .backgroundColor($r("app.color.white_bg_color"))
                                    .onClick(() => {
                                    LogUtil.info(this.TAG_PAGE + 'item on click : ' + JSON.stringify(item));
                                    AppStorage.SetOrCreate('pairedMac', item.deviceId);
                                    //                AppStorage.SetOrCreate('pairedName', item.deviceName);
                                    this.pairDevice(item)
                                })
                            }
                        }, item => JSON.stringify(item));
                    }
                    .backgroundColor($r("app.color.white_bg_color"))
                        .borderRadius($r("app.float.radius_24"))
                        .height("80%")
                        .divider({
                        strokeWidth: 1,
                        color: $r('app.color.color_E3E3E3_grey'),
                        startMargin: $r('app.float.wh_value_52'),
                        endMargin: $r('app.float.wh_value_12')
                    })
                }
                .scrollBar(BarState.Auto)
                    .scrollBarWidth(20)
            } else {
                Row() {
                    // Scanning...
                    Text($r('app.string.scanning'))
                        .fontSize($r('app.float.font_20'))
                        .textCase(TextCase.UpperCase);
                }
            }
        }
    }

整体代码

├─Component
│   │  └─controller
│   ├─pageTitle.ets
│   ├─headComponent.ets
│   └─titleComponent.ets
├─MainAbility
│  ├─controller
│  ├─model
│      ├─BluetoothDevice.ts
│      └─BluetoothModel.ts
│  └─pages
│      ├─homePage.ets
│      └─deviceFound.ets
└─Utils

page

//homePage
build() {
    Column() {
        GridContainer({
            columns: 12,
            sizeType: SizeType.Auto,
            gutter: vp2px(1) === 2 ? '12vp' : '0vp',
            margin: vp2px(1) === 2 ? '24vp' : '0vp'
        }) {
            Row({}) {
                Column() {
                }
                .width(ConfigData.WH_100_100)
                    .height(ConfigData.WH_100_100)
                    .useSizeType({
                    xs: { span: 0, offset: 0 }, sm: { span: 0, offset: 0 },
                    md: { span: 0, offset: 0 }, lg: { span: 2, offset: 0 }
                });
                Column() {
                    Text(this.message)
                        .fontSize($r("app.float.font_30"))
                        .lineHeight($r("app.float.lineHeight_41"))
                        .fontWeight(FontWeight.Bold)
                        .fontFamily('HarmonyHeiTi')
                        .textAlign(TextAlign.Start)
                        .width(ConfigData.WH_100_100)
                        .padding({
                        left: $r('app.float.distance_26'),
                        top: $r('app.float.distance_12'),
                        bottom: $r('app.float.distance_17')
                    })
                    Column() {
                        HeadComponent({ headName: $r('app.string.test1'), isActive: true })
                        Scroll() {
                            Column({ space: '12vp' }) {
                                List() {
                                    //开蓝牙
                                    ListItem() {
                                        TitleComponent({
                                            title: "enableBluetooth",
                                            bgColor: this.currentClick === 0 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        this.currentClick = 0;
                                        if (this.btEnable) {
                                            this.message = '蓝牙已经使能';
                                            return;
                                        }
                                        let ret = BluetoothModel.enableBluetooth();
                                        this.btEnable = ret;
                                        AppStorage.SetOrCreate('bluetoothIsOn', this.btEnable);
                                        AppStorage.SetOrCreate('currentClick', this.currentClick);
                                        this.message = "蓝牙使能执行结果:" + ret;
                                    })
                                    //设置状态
                                    ListItem() {
                                        TitleComponent({
                                            title: "getState",
                                            bgColor: this.currentClick === 2 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        this.currentClick = 2;
                                        let ret = BluetoothModel.getState();
                                        switch (ret) {
                                            case 0:
                                                this.stateBT = 'STATE_OFF';
                                                break;
                                            case 1:
                                                this.stateBT = 'STATE_TURNING_ON';
                                                break;
                                            case 2:
                                                this.stateBT = 'STATE_ON';
                                                break;
                                            case 3:
                                                this.stateBT = 'STATE_TURNING_OFF';
                                                break;
                                            case 4:
                                                this.stateBT = 'STATE_BLE_TURNING_ON';
                                                break;
                                            case 5:
                                                this.stateBT = 'STATE_BLE_ON';
                                                break;
                                            case 6:
                                                this.stateBT = 'STATE_BLE_TURNING_OFF';
                                                break;
                                            default:
                                                this.stateBT = '未知状态';
                                                break;
                                        }
                                        this.message = "当前蓝牙的状态是:" + this.stateBT;
                                    })
                                    //设置本地名称  
                                    ListItem() {
                                        TitleComponent({
                                            title: "setLocalName",
                                            bgColor: this.currentClick === 4 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        this.currentClick = 4;
                                        if (this.btEnable) {
                                            Router.push({ uri: PAGE_URI_DEVICE_NAME });
                                            this.message = "设置SCAN MODE " + this.setScanModeRet ? '成功' : '失败';
                                        } else {
                                            this.message = "蓝牙未使能";
                                        }
                                    })
                                    //设置扫描模式   
                                    ListItem() {
                                        TitleComponent({
                                            title: "setBluetoothScanMode",
                                            bgColor: this.currentClick === 6 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        this.currentClick = 6;
                                        if (!this.btEnable) {
                                            Router.push({ uri: PAGE_URI_SET_SCAN_MODE });
                                            this.message = "setBluetoothScanMode执行" + this.setLocalNameRet ? '成功' : '失败';
                                        } else {
                                            this.message = "蓝牙未使能";
                                        }
                                    })
                                    // 开始蓝牙发现
                                    ListItem() {
                                        TitleComponent({
                                            title: "startBluetoothDiscovery",
                                            bgColor: this.currentClick === 8 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        LogUtil.info(this.TAG_PAGE + 'startBluetoothDiscovery 111');
                                        if (this.btEnable) {
                                            this.message = '蓝牙未使能';
                                            return;
                                        }
                                        this.currentClick = 8;
                                        Router.push({ uri: PAGE_URI_DEVICE_FOUND_MODE });
                                    })
                                    //监听PinRequired
                                    ListItem() {
                                        TitleComponent({
                                            title: this.btPinRequired,
                                            pinRequiredFlag: true,
                                            bgColor: this.currentClick === 18 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        if (!this.btEnable) {
                                            this.message = "蓝牙未使能";
                                            return;
                                        }
                                        if (this.isPinRequiredClick) {
                                            bluetooth.off('pinRequired', () => {

                                            })
                                            this.message = 'on:pinRequired监听已关闭,再次点击将开启监听';
                                            this.isPinRequiredClick = false;
                                            this.btPinRequired = 'on:pinRequired';
                                            AppStorage.SetOrCreate('on_pinRequired', this.btPinRequired);
                                            return;
                                        }
                                        this.isPinRequiredClick = true;
                                        this.currentClick = 18;
                                        this.btPinRequired = 'off:pinRequired';
                                        AppStorage.SetOrCreate('on_pinRequired', this.btPinRequired);
                                        this.pinMessage = 'PIN: ';
                                        bluetooth.on('pinRequired', (data) => {
                                            this.pinMessage = 'PIN: ';
                                            this.pinMessage += data.pinCode;
                                        })
                                        this.message = 'on:pinRequired监听已启动,再次点击将关闭监听。';
                                    })
                                    //配对设备
                                    ListItem() {
                                        TitleComponent({
                                            title: "pairDevice",
                                            bgColor: this.currentClick === 10 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        this.currentClick = 10;
                                        if (!this.btEnable) {
                                            this.message = '蓝牙未使能';
                                            return;
                                        }
                                        if (this.deviceId == '') {
                                            this.message = "请输入目标设备的MAC";
                                            return;
                                        } else {
                                            this.pairDevice(this.deviceId);
                                        }
                                    })
                                    //关蓝牙
                                    ListItem() {
                                        TitleComponent({
                                            title: "disableBluetooth",
                                            bgColor: this.currentClick === 1 ? $r('app.color.font_color_007DFF') : $r('app.color.white_bg_color')
                                        });
                                    }
                                    .padding({ top: $r('app.float.distance_2'), bottom: $r('app.float.distance_2') })
                                        .onClick(() => {
                                        this.currentClick = 1;
                                        if (!this.btEnable) {
                                            this.message = '蓝牙还未使能';
                                            return;
                                        }
                                        let ret = BluetoothModel.disableBluetooth();
                                        this.btEnable = false;
                                        AppStorage.SetOrCreate('bluetoothIsOn', this.btEnable);
                                        this.message = "蓝牙去使能执行结果:" + ret;
                                    })
                                }
                            }
                            .width(ConfigData.WH_100_100)
                                .height(600)
                        }
                        .scrollable(ScrollDirection.Vertical).scrollBar(BarState.On)
                        .scrollBarColor(Color.Gray).scrollBarWidth(30)
                    }
                    .padding({ left: $r('app.float.distance_2'), right: $r('app.float.distance_2') })
                    .width(ConfigData.WH_100_100)
                    .height(ConfigData.WH_100_100)
                    .useSizeType({
                    xs: { span: 12, offset: 0 }, sm: { span: 12, offset: 0 },
                    md: { span: 12, offset: 0 }, lg: { span: 8, offset: 2 }
                    });
                }
                .padding({ left: $r('app.float.distance_2'), right: $r('app.float.distance_2') })
                .width(ConfigData.WH_100_100)
                .height(ConfigData.WH_100_100)
                .useSizeType({
                xs: { span: 12, offset: 0 }, sm: { span: 12, offset: 0 },
                md: { span: 12, offset: 0 }, lg: { span: 8, offset: 2 }
                });
            }
            .width(ConfigData.WH_100_100)
            .height(ConfigData.WH_100_100);
        }
        .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
        .width(ConfigData.WH_100_100)
        .height(ConfigData.WH_100_100);
    }
}

component:

// titlecomoponent

import ConfigData from '../Utils/ConfigData';
@Component
export struct TitleComponent{
    private title:string | Resource;
    private fontSize:string ='35vp';
    private stateChangeFlag: boolean = false;
    private pinRequiredFlag: boolean = false;
    private bondStateChangeFlag: boolean = false;
    @State isTouched:boolean = false;
    @State bgColor: Resource = $r('app.color.font_color_007DFF');
    @StorageLink('on_stateChange') state: string = 'on:stateChange';
    @StorageLink('on_pinRequired') pin: string = 'on:pinRequired';
    @StorageLink('on_bondStateChange') bondState: string = 'on:bondStateChange';
    build(){
        Column(){
            Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems:ItemAlign.Center }) {
                Text(this.stateChangeFlag ? this.state : (this.pinRequiredFlag ? this.pin : (this.bondStateChangeFlag ? this.bondState : this.title)))
                    .textAlign(TextAlign.Center)
                    .width("100%")
                    .height(100)
                    .fontSize(this.fontSize)
                    .fontColor($r('app.color.font_color_182431'))
                    .fontWeight(FontWeight.Medium)
            }
            .height(ConfigData.WH_100_100)
                .width(ConfigData.WH_100_100)
                .backgroundColor(this.bgColor)
                .linearGradient(this.isTouched ? {
                angle: 90,
                direction: GradientDirection.Right,
                colors: [[$r("app.color.DCEAF9"), 0.0], [$r("app.color.FAFAFA"), 1.0]]
            } : {
                angle: 90, direction: GradientDirection.Right,
                colors: [[$r("sys.color.ohos_id_color_foreground_contrary"), 1], [$r("sys.color.ohos_id_color_foreground_contrary"), 1]]})
                .onTouch((event: TouchEvent) => {
                if (event.type === TouchType.Down) {
                    this.isTouched = true;
                }
                if (event.type === TouchType.Up) {
                    this.isTouched = false;
                }
            })
        }
        .padding($r('app.float.distance_4'))
        .height("100vp")
        .borderRadius($r('app.float.radius_12'))
    }
}

model:

import { DeviceState } from './BluetoothModel'
export class Profile {
    profileId: number = -1;
    profileConnectionState: number = -1
    constructor() {
    }
}
/**
 * Bluetooth device class
 */
export default class BluetoothDevice {
    deviceId: string = '';
    deviceName: string = '';
    deviceType: string = '';
    connectionState: number = 0;
    profiles: Map<number, Profile> = new Map();
    constructor() {
    }
    setProfiles(data: Array<{
        profileId: number;
        profileConnectionState: number;
    }>): void{
            data.forEach((item: {
            profileId: number;
            profileConnectionState: number;
        }) => {
            this.setProfile({
                profileId: item.profileId,
                deviceId: this.deviceId,
                profileConnectionState: item.profileConnectionState
            })
        })
    }
    setProfile(data: {
        profileId: number;
        deviceId: string;
        profileConnectionState: number;
    }): void{
        if (this.deviceId !== data.deviceId) {
            return;
        }
        this.profiles.set(data.profileId, data)
        let countStateDisconnect = 0;
        let countStateConnecting = 0;
        let countStateConnected = 0;
        let countStateDisconnecting = 0;
        this.profiles.forEach((profile, key) => {
            if (profile.profileConnectionState == 0) {
                // 0:the current profile is disconnected
                countStateDisconnect++;
            } else if (profile.profileConnectionState == 1) {
                // 1:the current profile is being connected
             countStateConnecting++;
            } else if (profile.profileConnectionState == 2) {
                // 2:the current profile is connected
            countStateConnected++;
            } else if (profile.profileConnectionState == 3) {
                // 3:the current profile is being disconnected
                countStateDisconnecting++;
            }
        });
        if (countStateConnected > 0 || countStateDisconnecting > 0) {
            this.connectionState = DeviceState.STATE_CONNECTED;
        } else if (countStateConnecting > 0) {
            this.connectionState = DeviceState.STATE_CONNECTING;
        } else {
            this.connectionState = DeviceState.STATE_DISCONNECTED;
        }
    }
}

预览图

image.png

无用

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

精彩评论4

liudongxjtu

沙发 发表于 2024-5-27 10:46:33
是否有该示例代码的下载?

深开鸿_王石

发表于 2024-5-28 10:42  IP属地: - 中国上海市 中国电信IDC

回复 liudongxjtu: https://gitee.com/openharmony/co ... ample/bluetoothtest ,可以参考这里面的应用

【1 条回复】

martin_hu

板凳 发表于 2024-7-22 17:30:44
demo要是有收发文件功能就更好了

martin_hu

发表于 2024-7-30 13:43  IP属地: 湖北省
【1 条回复】

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部