OpenHarmony实战开发-

567 篇文章 4 订阅
555 篇文章 0 订阅

场景说明

对可用的WLAN列表进行扫描,连接、断开WLAN网络是设备常见的功能,本例将为大家介绍如何实现上述功能。

效果呈现

本例效果如下:

扫描WLAN	连接WLAN	断开WLAN
contactlist	contactlist	contactlist

运行环境

本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发。

  • IDE:DevEco Studio 4.0.0.201 Beta1
  • SDK:Ohos_sdk_public 4.0.7.5 (APIVersion 10 Beta1)

实现思路
本例主要通过@ohos.wifiManager 相关API实现WLAN激活和关闭、扫描和连接WLAN等功能。

  • WLAN功能的激活和关闭:点击首页的切换按钮,如果是打开,使用wifi.enableWifi()开启WLAN功能;如果是关闭,则使用wifi.disconnect()断开WLAN功能,然后使用wifi.disableWifi()关闭WLAN。
  • WLAN的连接:点击WLAN列表中加密的WLAN,并在弹窗中输入密码后,会在AvailableWifi.ets中通过WifiModule.connectNetwork()调用wifi.connectToDevice()连接WLAN。
  • WLAN的扫描:进入Index.ets后就会间歇性的调用wifi.scan()开启扫描,然后通过WifiModel模块中的getScanInfos()调用wifi.getScanResults()来获取扫描的结果.

开发步骤

1.申请所需权限

在model.json5中添加以下配置:

"requestPermissions": [
  {
    "name": "ohos.permission.GET_WIFI_INFO"//允许应用获取WLAN信息
  },
  {
    "name": "ohos.permission.GET_WIFI_INFO_INTERNAL"//允许应用获取WLAN信息
  },
  {
    "name": "ohos.permission.SET_WIFI_INFO"//允许应用配置WLAN设备
  },
  {
    "name": "ohos.permission.GET_WIFI_PEERS_MAC"//允许应用获取对端WLAN或者蓝牙设备的MAC地址
  },
  {
    "name": "ohos.permission.GET_WIFI_LOCAL_MAC"//允许应用获取本机WLAN或者蓝牙设备的MAC地址
  },
  {
    "name": "ohos.permission.GET_WIFI_CONFIG"//允许应用获取WLAN配置信息
  },
  {
    "name": "ohos.permission.SET_WIFI_CONFIG"//允许应用配置WLAN信息
  },
  {
    "name": "ohos.permission.MANAGE_WIFI_CONNECTION"//允许应用管理WLAN连接
  },
  {
    "name": "ohos.permission.MANAGE_WIFI_HOTSPOT"//允许应用开启或者关闭WLAN热点
  },
  {
    "name": "ohos.permission.LOCATION"//允许应用获取设备位置信息
  },
  {
    "name": "ohos.permission.APPROXIMATELY_LOCATION"//允许应用获取设备模糊位置信息
  }
]

2.准备工作

定义boolean变量isSwitchOn作为WLAN开关是否打开的标志。

import wifi from '@ohos.wifiManager'
aboutToAppear() {
    // 如果WLAN是开的,就记录下状态,然后扫描WLAN,并获取连接信息
    if (wifi.isWifiActive()) {//查询WLAN是否已使能
      Logger.log(TAG, 'wifi is active')
      this.isSwitchOn = true//已使能说明WLAN开关已被打开,那么让isSwitchOn为true
      wifi.scan()//@ohos.wifiManager的接口,对WLAN进行扫描
      this.scan()//自定义的scan函数,确保扫描的持续性
      this.getLinkedInfo()
    }
    // 启动监听
    this.addListener()//监听连接状态的变化
  }

3.持续地扫描可用WLAN

scan方法不断地自我调用以实现对WLAN的不停扫描。

async getLinkedInfo() {
    try {
      //调用getLinkedInfo接口得到是否已连接WLAN的信息 
      let wifiLinkedInfo = await wifi.getLinkedInfo()
      if (wifiLinkedInfo === null || wifiLinkedInfo.bssid === '') {
          //如果结果为空,则说明未连接
        this.isLinked = false
        this.linkedInfo = null
        return
      }
      this.isLinked = true
      this.linkedInfo = wifiLinkedInfo
    } catch (err) {
      Logger.info(`getLinkedInfo failed err is ${JSON.stringify(err)}`)
    }
  }
async scan() {
    // 获取有关WLAN连接的信息,存入linkedInfo
    await this.getLinkedInfo()
    // 不停地扫描WLAN
    let result: Array<WifiType> = await this.wifiModel.getScanInfos()//调用model/WifiModel.ets中的getScanInfos得到扫描结果
    if (this.isSwitchOn) {
        //如果WLAN功能已打开,则要进行不停地扫描
      AppStorage.SetOrCreate('wifiList', result)//将扫描结果存至全局
        //每3000毫秒调用一次scan(),实现不停扫描可用WLAN
      setTimeout(async () => {
        await this.scan()
      }, 3000)
    }
  }
addListener() {
    // WLAN连接状态改变事件发生时,修改连接信息
    wifi.on('wifiConnectionChange', async state => {
      Logger.log(TAG, `wifiConnectionChange: ${state}`)
      await this.getLinkedInfo()//WLAN连接状态改变,重新获取WLAN连接信息
    })
    // WLAN状态改变时,先清空WLAN列表,然后判断是否是开启状态,如果是就扫描
    wifi.on('wifiStateChange', state => {
      Logger.log(TAG, `wifiStateLisener state: ${state}`)
      AppStorage.SetOrCreate('wifiList', [])
      if (state === 1) { // 1: wifi is enable, 0:wifi is disable
        this.scan()
      }
    })
  }
...
//model/WifiModel.ets
async getScanInfos(): Promise<Array<WifiType>> {
    Logger.log(TAG, 'scanWifi begin')
    let wifiList: Array<WifiType> = []
    let result: Array<wifi.WifiScanInfo> = []
    try {
      result = await wifi.getScanResults()//因为在abouttoappear()中执行了wifi.scan(),所以这里直接调用getScanResults接口得到扫描结果
    } catch (err) {
      Logger.log(TAG, `scan info err: ${JSON.stringify(err)}`)
      return wifiList
    }
    Logger.log(TAG, `scan info call back: ${result.length}`)
    for (var i = 0; i < result.length; ++i) {
      wifiList.push({
        ssid: result[i].ssid,
        bssid: result[i].bssid,
        securityType: result[i].securityType,
        rssi: result[i].rssi,
        band: result[i].band,
        frequency: result[i].frequency,
        timestamp: result[i].timestamp
      })
    }
    return wifiList
  }

4.构建UI框架、通过关闭按钮实现断开WLAN连接。

TitleBar组件呈现了标题框。WLAN开关按钮由一个Toggle组件呈现,其绑定的onChange事件在按钮被打开时开始扫描可用WLAN,在被关闭时断开当前连接WLAN并且关闭WLAN功能。当前已连接的WLAN由两个Text组件分别显示其ssid与连接状态。

build() {
    Column() {
      TitleBar()//引入自component/TitleBar.ets,负责标题框的具体呈现
      Row() {
        Text($r('app.string.wlan'))
          .fontSize(22)
          .fontWeight(FontWeight.Bold)
          .height(40)
        Column() {
          Toggle({ type: ToggleType.Switch, isOn: this.isSwitchOn })//切换按钮
            .id('switch')
            .onChange((isOn: boolean) => {
              Logger.log(`LSQ: wifi swtich is: ${isOn}`)
              AppStorage.SetOrCreate('wifiList', [])
              try {
                // 如果按钮被打开了,记录状态,打开网络,开始扫描可用WLAN
                if (isOn) {
                  this.isSwitchOn = true
                  wifi.enableWifi()//使WLAN功能可用
                  return
                } else {
                  // 如果按钮被关闭了记录状态,断开网络禁用网络
                  this.isSwitchOn = false
                  this.isLinked = false
                  wifi.disconnect()//断开当前WLAN连接
                  wifi.disableWifi()//使WLAN功能不可用
                }
              } catch (error) {
                Logger.error(TAG, `failed,code:${JSON.stringify(error.code)},message:${JSON.stringify(error.message)}`)
              }
            })
        }
      }
      .width('100%')
      .padding({ left: 16, right: 16 })
      if (this.isLinked && this.isSwitchOn) {
          //如果当前按钮处于打开状态,且WLAN是已连接状态
        Column() {
          Text($r('app.string.connected'))
            .fontSize(22)
            .width('100%')
          Row() {
            Text(this.linkedInfo.ssid)//展示当前已连接的WLAN
              .fontSize(20)
              .fontColor(Color.Black)
              .layoutWeight(1)
            Text($r('app.string.connected'))
              .fontSize(18)
              .fontColor(Color.Black)
          }
          .width('100%')
          .padding(10)
          .margin({ left: 16, right: 16 })
          .border({ radius: 15, color: Color.Gray, width: 1 })
          .backgroundColor(Color.White)
        }
        .width('100%')
        .padding({ left: 16, right: 16 })
      }
      if (this.isSwitchOn) {
          //如果按钮处于打开状态,展示所有可用WLAN
        AvailableWifi({ linkedInfo: this.linkedInfo })//AvailableWifi引入自component/AvailableWifi.ets
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.index_bg'))
  }

5.展示可用WLAN列表及WLAN的连接。

使用List组件呈现可用WLAN列表,ListItem由一个呈现WLANssid的Text组件,一个表示其是否被加密的Text组件和一个展示其加密与否图像的Image组件组成。

//component/AvailableWifi.ets
build() {
    List() {
      ListItem() {
        Row() {
          Text($r('app.string.available_wlan'))
            .fontSize(22)
            .layoutWeight(1)
        }
        .id('validWlan')
        .width('100%')
      }
		//通过数据懒加载的方式从数据源中每次迭代一个可用WLAN进行展示,可用列表被放置在滚动容器中,被划出可视区域外的资源会被回收
      LazyForEach(this.wifiDataResource, (item, index) => {
        ListItem() {
          WifiView({ wifi: item })//WifiView引入自Component/WifiView.ets,负责可用WLAN信息展示的具体实现
        }
        .id(`Wifi${index}`)
        //对可用WLAN点击时触发事件
        .onClick(() => {
          Logger.info(TAG, 'wifi click')
          this.scanInfo = item
          if (this.linkedInfo !== null && item.ssid === this.linkedInfo.ssid) {
            prompt.showToast({ message: 'this wifi is connected' })//如果当前已连接WLAN并且点击的就是这个WLAN,创建并显示文本提示框
            return
          }
          if (item.securityType === 0 || item.securityType === 1) {
            //如果点击的这个WLAN的加密类型是无效加密类型或者开放加密类型,调用model/Wifimodel.ets中的connectNetwork方法连接此WLAN
            this.wifiModel.connectNetwork(item, '')
            return
          }
          //如果点击的这个WLAN的加密类型是其他加密类型,则需要输入密码,调用component/PswDialog.ets中的方法进行弹窗的生成
          this.pswDialogController.open()
        })
      }, item => JSON.stringify(item))
    }
    .width('100%')
    .height('100%')
    .padding({ left: 16, right: 16 })
    .layoutWeight(1)
    .divider({ strokeWidth: 1, color: Color.Gray, startMargin: 10, endMargin: 10 })
    .margin({ top: 10 })
  }
//pswDialogController回调的action函数,将传回的WLAN信息与密码传入model/Wifimodel.ets中的connectNetwork方法中
onAccept(scanInfo, psw) {
    Logger.info(TAG, 'connect wifi')
    self.wifiModel.connectNetwork(scanInfo, psw)
  }
...
//Component/WifiView.ets
aboutToAppear() {
    Logger.debug(TAG, `aboutToAppear ${JSON.stringify(this.wifi)}`)
    if (this.wifi) {
      if (this.wifi.securityType) {
        if (this.wifi.securityType === 0 || this.wifi.securityType === 1) {
            //WLAN的加密类型是无效加密类型或者开放加密类型
          this.securityString = $r('app.string.open')
          this.isLock = false
        }
      }
    }
  }
build() {
    Row() {
      Column() {
        if (this.wifi) {
          if (this.wifi.ssid) {
            Text(this.wifi.ssid)
              .fontSize(20)
              .width('100%')
          }
        }
          //如果WLAN的加密类型是无效加密类型或者开放加密类型,显示“开放”,反之显示“加密”
        Text(this.securityString)
          .fontSize(18)
          .fontColor(Color.Gray)
          .width('100%')
      }
      .layoutWeight(1)

      Stack({ alignContent: Alignment.BottomEnd }) {
          //如果WLAN的加密类型是无效加密类型或者开放加密类型,显示不带锁的图标,反之显示带锁的图标
        Image($r('app.media.wifi'))
          .height(30)
          .width(30)
          .objectFit(ImageFit.Contain)
        if (this.isLock) {
          Image($r('app.media.lock'))
            .objectFit(ImageFit.Contain)
            .width(15)
            .height(15)
        }
      }
      .width(40)
      .height(40)
      .margin({ right: 10 })
    }
    .backgroundColor(Color.White)
    .width('100%')
    .padding(10)
  }
}
...
//model/Wifimodel.ets
connectNetwork(scanInfo: wifi.WifiScanInfo, psw) {
    prompt.showToast({ message: 'connecting', duration: 5000 })
    Logger.debug(TAG, `connectNetwork bssid=${scanInfo.bssid}`)
    // 这里因为api问题,需要声明为any,已提单
    let deviceConfig: any = {
      ssid: scanInfo.ssid,
      bssid: scanInfo.bssid,
      preSharedKey: psw,
      isHiddenSsid: false,
      securityType: scanInfo.securityType
    }
    try {
      wifi.connectToDevice(deviceConfig)//连接到指定网络
      Logger.debug(TAG, `connectToDevice success`)
    } catch (err) {
      Logger.debug(TAG, `connectToDevice fail err is ${JSON.stringify(err)}`)
    }
    try {
      wifi.addDeviceConfig(deviceConfig)//添加网络配置
    } catch (err) {
      Logger.debug(TAG, `addDeviceConfig fail err is ${JSON.stringify(err)}`)
    }
  }
...
//component/PswDialog.ets
 build() {
    Column() {
      Text(this.scanInfo.ssid)
        .fontSize(20)
        .width('95%')

      TextInput({ placeholder: 'input password' })//密码的输入框
        .id('input')
        .type(InputType.Password)
        .placeholderColor(Color.Gray)
        .fontSize(19)
        .margin({ top: 15 })
        .width('95%')
        .height(36)
        //每当输入框中的内容变化,它就赋值给psw
        .onChange((value: string) => {
          this.psw = value
        })

      Row() {
         //确认按钮
        Button() {
          Text($r('app.string.sure'))
            .fontColor(Color.Blue)
            .fontSize(17)
        }
        .id('sure')
        .layoutWeight(7)
        .backgroundColor(Color.White)
        .margin(5)
        .onClick(() => {
          this.controller.close()
          this.action(this.scanInfo, this.psw)
        })

        Text()
          .width(1)
          .height(35)
          .backgroundColor($r('app.color.text_color'))
		//取消按钮
        Button() {
          Text($r('app.string.cancel'))
            .fontColor(Color.Red)
            .fontSize(17)
        }
        .layoutWeight(7)
        .backgroundColor(Color.White)
        .margin(5)
        .onClick(() => {
          this.controller.close()
        })
      }
      .width('100%')
      .margin({ top: '3%' })
    }
    .padding(15)
  }

全部代码

本例完整代码sample示例链接:WLAN

我这边特意整理了《鸿蒙语法ArkTS、TypeScript、ArkUI、实战开发视频教程》以及《鸿蒙生态应用开发白皮书V2.0PDF》《鸿蒙开发学习手册》(共计890页)鸿蒙开发资料等…希望对大家有所帮助:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

OpenHarmony APP开发教程步骤:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

鸿蒙生态应用开发白皮书V2.0PDF:https://docs.qq.com/doc/DZVVkRGRUd3pHSnFG

在这里插入图片描述

应用开发中级就业技术:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

应用开发中高级就业技术:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

南北双向高工技能基础:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

全网首发-工业级 南向设备开发就业技术:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

《鸿蒙开发学习手册》:

如何快速入门:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.基本概念
2.构建第一个ArkTS应用
3.……

在这里插入图片描述

开发基础知识:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值