文章目录
- WIFI是大家日常必不可少需求,在OpenHarmony的开发中,系统提供了一系列完整的API,在万物互联的这个概念下,相信涉及到wifi功能操作的需求会越来越多,今日分享的是用ets来实现简单的wifi连接操作,可以实现扫描设备附近的wifi并进行连接,结合一些简单的按钮动画,让体验更加流畅。
- 本组件界面搭建基于ArkUI中TS扩展的声明式开发范式,官网官方文档地址:基于TS扩展的声明式开发范式1、基于TS扩展的声明式开发范式2。 工具版本:DevEco Studio 3.0 Beta4 SDK版本:3.2.2.5(API Version 9 Beta1)
- Wi-Fi指的是Wi-Fi联盟的商标,也是一种基于IEEE 802.11标准的无线网络通信技术,目的是改善基于IEEE 802.11标准的无线网络产品之间的互通性。 WLAN的全称是Wireless Local Area Network,中文含义是无线局域网,WLAN的定义有广义和狭义两种:广义上讲WLAN是以各种无线电波(如激光、红外线等)的无线信道来代替有线局域网中的部分或全部传输介质所构成的网络;WLAN的狭义定义是基于IEEE 802.11系列标准,利用高频无线射频(如2.4GHz或5GHz频段的无线电磁波)作为传输介质的无线局域网。 简单来说就是,WLAN是一个网络系统,而Wi-Fi是这个网络系统中的一种技术。所以,WLAN和Wi-Fi之间是包含关系,WLAN包含了Wi-Fi。
- 点击扫描可用的wifi。 输入密码连接选中的wifi。 点击按钮将连接的wifi密码生成二维码分享。
- |---- wifiScan-example |---- src | |---- main | |------- ets | | |---- components # 组件 | | | |---- ImgDialog.ets # 二维码弹窗组件 | | | |---- ItemView.ets # ListItem组件 | | | |---- PwdDialog.ets # 密码输入弹窗组件 | | |---- pages # 库文件夹 | | | |---- index.ets # 主界面 | | |---- utils # 工具类 | | | |---- Logger.ts # 日志打印封装类
- 获取WLAN信息权限:ohos.permission.GET_WIFI_INFO。 获取WLAN网络信息权限:ohos.permission.GET_WIFI_INFO_INTERNAL。 允许配置WLAN设备权限:ohos.permission.SET_WIFI_INFO。 获取WLAN配置信息权限:ohos.permission.GET_WIFI_CONFIG。 允许配置WLAN配置权限:ohos.permission.SET_WIFI_CONFIG。 允许控制WLAN连接状态权限:ohos.permission.MANAGE_WIFI_CONNECTION。
- 由于WIFI相关的操作是属于OpenHarmony系统核心操作,相应的API对普通权限的应用不开放,所以我们使用这些API时,需要进行单独的配置,如果缺少配置,安装时会报权限错误Failed due to grant request permissions failed。 config.json中添加相应权限,这里添加的是使用到的所有权限,我这边是把所有权限列出来的,方便直接复制,实际部分权限是没有使用到的,大家可以根据自己项目需求来选择。 "reqPermissions": [ { "name": "ohos.permission.GET_WIFI_INFO", "reason": "request permission" }, { "name": "ohos.permission.GET_WIFI_INFO_INTERNAL", "reason": "request permission" }, { "name": "ohos.permission.SET_WIFI_INFO", "reason": "request permission" }, { "name": "ohos.permission.GET_WIFI_PEERS_MAC", "reason": "request permission" }, { "name": "ohos.permission.GET_WIFI_LOCAL_MAC", "reason": "request permission" }, { "name": "ohos.permission.GET_WIFI_CONFIG", "reason": "request permission" }, { "name": "ohos.permission.SET_WIFI_CONFIG", "reason": "request permission" }, { "name": "ohos.permission.MANAGE_WIFI_CONNECTION", "reason": "request permission" }, { "name": "ohos.permission.MANAGE_WIFI_HOTSPOT", "reason": "request permission" }, { "name": "ohos.permission.LOCATION", "reason": "request permission" } ] 找到SDK目录下面toolchains\x.x.x.x\lib下面的UnsgnedReleasedProfileTemplate.json文件,使用记事本打开,在里面添加如下权限(主要是添加权限级别为system_core的相关权限)。 "acls": { "allowed-acls": [ "ohos.permission.GET_SENSITIVE_PERMISSIONS", "ohos.permission.GET_WIFI_INFO_INTERNAL", "ohos.permission.GET_WIFI_PEERS_MAC", "ohos.permission.MANAGE_WIFI_CONNECTION", "ohos.permission.MANAGE_WIFI_HOTSPOT" ] 保存修改以后,再使用DevEco Studio的自动签名功能重新对应用进行签名就可以正常安装了,更多详细的内容,请参考权限定义列表 、访问控制开发概述。
- 接口 描述 getScanInfos(callback: AsyncCallback<Array<WifiScanInfo>>): void; 扫描wifi connectToDevice(config: WifiDeviceConfig): boolean; 连接设备 enableWifi(): boolean 打开WLAN disableWifi(): boolean 关闭WLAN isWifiActive(): boolean 查询WIFI是否可以使用 getScanInfosSync(): Array<[WifiScanInfo] 获取扫描结果,使用同步方式返回结果 addDeviceConfig(config: WifiDeviceConfig, callback: AsyncCallback<number>): void 添加网络配置,使用callback异步回调
-
- build() { Column(){ Scroll() { List() { ForEach(this.wifiList, (item, index) => { ListItem() { ItemView({ wifi: item }) } .onClick(() => { Logger.info(TAG, 'wifi click') this.selectIndex = index this.pswDialogController.open() }) }, item => JSON.stringify(item)) } .layoutWeight(1) .divider({ strokeWidth: 1, color: Color.Gray, startMargin: 10, endMargin: 10 }) .margin(10) } } .height(600) .width('90%') .margin({top:30}) .backgroundColor(Color.White) .borderRadius(15) } .height('100%') .margin({ top: 15, bottom: 100 }) .backgroundColor("#A8A8A8") }
- wifi.getScanInfos((err, result) => { let wifiList = [] if (err) { Logger.log(TAG, `scan err: ${JSON.stringify(err)}`) callback(wifiList) return } Logger.log(TAG, `scan callback: ${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, }) } callback(wifiList) }) }
- Column() { Text(this.scanInfo.ssid) .fontSize(22) .width('95%') TextInput({ placeholder: '请输入密码' }) .type(InputType.Password) .placeholderColor(Color.Gray) .fontSize(19) .margin({ top: 15 }) .width('95%') .onChange((value: string) => { this.passwd = value }) Row() { Button() { Text($r('app.string.sure')) .fontColor(Color.Blue) .fontSize(17) } .layoutWeight(7) .backgroundColor(Color.White) .margin(5) .onClick(() => { this.controller.close() this.action(this.scanInfo, this.passwd) }) Text() .width(1).height(36) .backgroundColor('#8F8F8F') Button() { Text($r('app.string.cancel')) .fontColor(Color.Red) .fontSize(18) } .layoutWeight(8) .backgroundColor(Color.White) .margin(5) .onClick(() => { this.controller.close() }) } .width('70%') .margin({ top: '2%' }) } .padding(15) }
- connectNetwork(scanInfo, psw) { let deviceConfig: any = { ssid: scanInfo.ssid, bssid: scanInfo.bssid, preSharedKey: psw, isHiddenSsid: false, securityType: scanInfo.securityType } if (wifi.connectToDevice(deviceConfig)) { prompt.showToast({ message: 'connect success' }) wifi.addDeviceConfig(deviceConfig) } else { prompt.showToast({ message: 'connect fail' }) }}
- build() { Column() { QRCode(this.passwd) .width(150) .height(this.height) .margin({top:50}) .color(Color.Green) Button() { Text($r('app.string.cancel')) .fontColor(Color.Red) .fontSize(18) } .backgroundColor(Color.White) .margin(20) .onClick(() => { this.controller.close() }) } .width('80%') .alignItems(HorizontalAlign.Center) }
- private animateStart(){ animateTo({ duration: 110, tempo: 1, curve: Curve.Sharp, delay: 50, iterations: 1, playMode: PlayMode.Normal, onFinish: () => { } }, () => { this.height = 150; }); } private animateEnd(){ animateTo({ duration: 300, tempo: 1, curve: Curve.Linear, delay: 200, iterations: 1, playMode: PlayMode.Normal, onFinish: () => { this.wifiModel.getScanInfos((result) => { this.wifiList = result }) this.scanWifi = '扫描WIFI'; } }, () => { this.btnWidth = 120; this.btnHeight = 120; this.borderRadius = 15; }); }
- 以上就是这次的全部内容,最终效果如动图所示。整个布局界面非常简单,但是能够实现WIFI连接的基本功能,其实WIFI功能提供的API中,还有很多能够扩展的地方,后续我也会继续学习,希望能更进一步的完善这一块的功能,写出更加优美流畅的示例。 想了解更多关于开源的内容,请访问: 51CTO 开源基础软件社区 https://ost.51cto.com。

WIFI是大家日常必不可少需求,在OpenHarmony的开发中,系统提供了一系列完整的API,在万物互联的这个概念下,相信涉及到wifi功能操作的需求会越来越多,今日分享的是用ets来实现简单的wifi连接操作,可以实现扫描设备附近的wifi并进行连接,结合一些简单的按钮动画,让体验更加流畅。
本组件界面搭建基于ArkUI中TS扩展的声明式开发范式,官网官方文档地址:基于TS扩展的声明式开发范式1、基于TS扩展的声明式开发范式2。
- 工具版本:DevEco Studio 3.0 Beta4
- SDK版本:3.2.2.5(API Version 9 Beta1)
Wi-Fi指的是Wi-Fi联盟的商标,也是一种基于IEEE 802.11标准的无线网络通信技术,目的是改善基于IEEE 802.11标准的无线网络产品之间的互通性。
WLAN的全称是Wireless Local Area Network,中文含义是无线局域网,WLAN的定义有广义和狭义两种:广义上讲WLAN是以各种无线电波(如激光、红外线等)的无线信道来代替有线局域网中的部分或全部传输介质所构成的网络;WLAN的狭义定义是基于IEEE 802.11系列标准,利用高频无线射频(如2.4GHz或5GHz频段的无线电磁波)作为传输介质的无线局域网。
简单来说就是,WLAN是一个网络系统,而Wi-Fi是这个网络系统中的一种技术。所以,WLAN和Wi-Fi之间是包含关系,WLAN包含了Wi-Fi。
在了解Wi-Fi之前,先来了解两个组织:电气和电子工程师协会(英文全称Institute of Electrical and Electronics Engineers,简称IEEE)和Wi-Fi联盟(英语全称Wi-Fi Alliance,简称WFA)。
IEEE作为标准组织,早在1990年,就已经成立了802.11工作组来制定无线局域网的相关标准,并在1997年发布了第一个标准802.11-1997。之后每过几年,802.11标准就会升级换代一次,至今已有6代。
而另一个组织,Wi-Fi联盟,其实是一个商业组织。这个联盟最初的目的是为了推动802.11b标准的制定,并在全球范围内推行符合IEEE 802.11标准的产品的兼容认证;到了2000年,该组织采用了“Wi-Fi”一词作为其技术工作的专有名称,同时宣布使用Wi-Fi Alliance作为正式名称,即Wi-Fi联盟,“Wi-Fi”实际上就是这个联盟的商标。
那么“Wi-Fi”具体有什么含义呢?目前有两种说法:第一种说法认为,Wi-Fi指的是无线保真(Wireless Fidelity),类似于音频设备分类:长期高保真或Hi-Fi(High Fidelity);另外一种说法认为,Wi-Fi并没有特别的含义,也没有全称。目前,并没有官方组织明确表明Wi-Fi就是指的Wireless Fidelity。另外,很多时候“Wi-Fi”会被写成“WiFi”或“wifi”,实际这些写法并没有被Wi-Fi联盟认可。
- 点击扫描可用的wifi。
- 输入密码连接选中的wifi。
- 点击按钮将连接的wifi密码生成二维码分享。

|---- wifiScan-example
|---- src
| |---- main
| |------- ets
| | |---- components # 组件
| | | |---- ImgDialog.ets # 二维码弹窗组件
| | | |---- ItemView.ets # ListItem组件
| | | |---- PwdDialog.ets # 密码输入弹窗组件
| | |---- pages # 库文件夹
| | | |---- index.ets # 主界面
| | |---- utils # 工具类
| | | |---- Logger.ts # 日志打印封装类
|---- src
| |---- main
| |------- ets
| | |---- components # 组件
| | | |---- ImgDialog.ets # 二维码弹窗组件
| | | |---- ItemView.ets # ListItem组件
| | | |---- PwdDialog.ets # 密码输入弹窗组件
| | |---- pages # 库文件夹
| | | |---- index.ets # 主界面
| | |---- utils # 工具类
| | | |---- Logger.ts # 日志打印封装类
- 获取WLAN信息权限:ohos.permission.GET_WIFI_INFO。
- 获取WLAN网络信息权限:ohos.permission.GET_WIFI_INFO_INTERNAL。
- 允许配置WLAN设备权限:ohos.permission.SET_WIFI_INFO。
- 获取WLAN配置信息权限:ohos.permission.GET_WIFI_CONFIG。
- 允许配置WLAN配置权限:ohos.permission.SET_WIFI_CONFIG。
- 允许控制WLAN连接状态权限:ohos.permission.MANAGE_WIFI_CONNECTION。
由于WIFI相关的操作是属于OpenHarmony系统核心操作,相应的API对普通权限的应用不开放,所以我们使用这些API时,需要进行单独的配置,如果缺少配置,安装时会报权限错误Failed due to grant request permissions failed。
- config.json中添加相应权限,这里添加的是使用到的所有权限,我这边是把所有权限列出来的,方便直接复制,实际部分权限是没有使用到的,大家可以根据自己项目需求来选择。
"reqPermissions": [
{
"name": "ohos.permission.GET_WIFI_INFO",
"reason": "request permission"
},
{
"name": "ohos.permission.GET_WIFI_INFO_INTERNAL",
"reason": "request permission"
},
{
"name": "ohos.permission.SET_WIFI_INFO",
"reason": "request permission"
},
{
"name": "ohos.permission.GET_WIFI_PEERS_MAC",
"reason": "request permission"
},
{
"name": "ohos.permission.GET_WIFI_LOCAL_MAC",
"reason": "request permission"
},
{
"name": "ohos.permission.GET_WIFI_CONFIG",
"reason": "request permission"
},
{
"name": "ohos.permission.SET_WIFI_CONFIG",
"reason": "request permission"
},
{
"name": "ohos.permission.MANAGE_WIFI_CONNECTION",
"reason": "request permission"
},
{
"name": "ohos.permission.MANAGE_WIFI_HOTSPOT",
"reason": "request permission"
},
{
"name": "ohos.permission.LOCATION",
"reason": "request permission"
}
]
- 找到SDK目录下面toolchains\x.x.x.x\lib下面的UnsgnedReleasedProfileTemplate.json文件,使用记事本打开,在里面添加如下权限(主要是添加权限级别为system_core的相关权限)。
"acls": {
"allowed-acls": [
"ohos.permission.GET_SENSITIVE_PERMISSIONS",
"ohos.permission.GET_WIFI_INFO_INTERNAL",
"ohos.permission.GET_WIFI_PEERS_MAC",
"ohos.permission.MANAGE_WIFI_CONNECTION",
"ohos.permission.MANAGE_WIFI_HOTSPOT"
]
- 保存修改以后,再使用DevEco Studio的自动签名功能重新对应用进行签名就可以正常安装了,更多详细的内容,请参考权限定义列表 、访问控制开发概述。
|
接口 |
描述 |
|
getScanInfos(callback: AsyncCallback<Array<WifiScanInfo>>): void; |
扫描wifi |
|
connectToDevice(config: WifiDeviceConfig): boolean; |
连接设备 |
|
enableWifi(): boolean |
打开WLAN |
|
disableWifi(): boolean |
关闭WLAN |
|
isWifiActive(): boolean |
查询WIFI是否可以使用 |
|
getScanInfosSync(): Array<[WifiScanInfo] |
获取扫描结果,使用同步方式返回结果 |
|
addDeviceConfig(config: WifiDeviceConfig, callback: AsyncCallback<number>): void |
添加网络配置,使用callback异步回调 |
build() {
Column(){
Scroll() {
List() {
ForEach(this.wifiList, (item, index) => {
ListItem() {
ItemView({ wifi: item })
}
.onClick(() => {
Logger.info(TAG, 'wifi click')
this.selectIndex = index
this.pswDialogController.open()
})
}, item => JSON.stringify(item))
}
.layoutWeight(1)
.divider({ strokeWidth: 1, color: Color.Gray, startMargin: 10, endMargin: 10 })
.margin(10)
}
}
.height(600)
.width('90%')
.margin({top:30})
.backgroundColor(Color.White)
.borderRadius(15)
}
.height('100%')
.margin({ top: 15, bottom: 100 })
.backgroundColor("#A8A8A8")
}
Column(){
Scroll() {
List() {
ForEach(this.wifiList, (item, index) => {
ListItem() {
ItemView({ wifi: item })
}
.onClick(() => {
Logger.info(TAG, 'wifi click')
this.selectIndex = index
this.pswDialogController.open()
})
}, item => JSON.stringify(item))
}
.layoutWeight(1)
.divider({ strokeWidth: 1, color: Color.Gray, startMargin: 10, endMargin: 10 })
.margin(10)
}
}
.height(600)
.width('90%')
.margin({top:30})
.backgroundColor(Color.White)
.borderRadius(15)
}
.height('100%')
.margin({ top: 15, bottom: 100 })
.backgroundColor("#A8A8A8")
}
wifi.getScanInfos((err, result) => {
let wifiList = []
if (err) {
Logger.log(TAG, `scan err: ${JSON.stringify(err)}`)
callback(wifiList)
return
}
Logger.log(TAG, `scan callback: ${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,
})
}
callback(wifiList)
})
}
let wifiList = []
if (err) {
Logger.log(TAG, `scan err: ${JSON.stringify(err)}`)
callback(wifiList)
return
}
Logger.log(TAG, `scan callback: ${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,
})
}
callback(wifiList)
})
}
Column() {
Text(this.scanInfo.ssid)
.fontSize(22)
.width('95%')
TextInput({ placeholder: '请输入密码' })
.type(InputType.Password)
.placeholderColor(Color.Gray)
.fontSize(19)
.margin({ top: 15 })
.width('95%')
.onChange((value: string) => {
this.passwd = value
})
Row() {
Button() {
Text($r('app.string.sure'))
.fontColor(Color.Blue)
.fontSize(17)
}
.layoutWeight(7)
.backgroundColor(Color.White)
.margin(5)
.onClick(() => {
this.controller.close()
this.action(this.scanInfo, this.passwd)
})
Text()
.width(1).height(36)
.backgroundColor('#8F8F8F')
Button() {
Text($r('app.string.cancel'))
.fontColor(Color.Red)
.fontSize(18)
}
.layoutWeight(8)
.backgroundColor(Color.White)
.margin(5)
.onClick(() => {
this.controller.close()
})
}
.width('70%')
.margin({ top: '2%' })
}
.padding(15)
}
Text(this.scanInfo.ssid)
.fontSize(22)
.width('95%')
TextInput({ placeholder: '请输入密码' })
.type(InputType.Password)
.placeholderColor(Color.Gray)
.fontSize(19)
.margin({ top: 15 })
.width('95%')
.onChange((value: string) => {
this.passwd = value
})
Row() {
Button() {
Text($r('app.string.sure'))
.fontColor(Color.Blue)
.fontSize(17)
}
.layoutWeight(7)
.backgroundColor(Color.White)
.margin(5)
.onClick(() => {
this.controller.close()
this.action(this.scanInfo, this.passwd)
})
Text()
.width(1).height(36)
.backgroundColor('#8F8F8F')
Button() {
Text($r('app.string.cancel'))
.fontColor(Color.Red)
.fontSize(18)
}
.layoutWeight(8)
.backgroundColor(Color.White)
.margin(5)
.onClick(() => {
this.controller.close()
})
}
.width('70%')
.margin({ top: '2%' })
}
.padding(15)
}
connectNetwork(scanInfo, psw) {
let deviceConfig: any = {
ssid: scanInfo.ssid,
bssid: scanInfo.bssid,
preSharedKey: psw,
isHiddenSsid: false,
securityType: scanInfo.securityType
}
if (wifi.connectToDevice(deviceConfig)) {
prompt.showToast({ message: 'connect success' })
wifi.addDeviceConfig(deviceConfig)
} else {
prompt.showToast({ message: 'connect fail' })
}
}
let deviceConfig: any = {
ssid: scanInfo.ssid,
bssid: scanInfo.bssid,
preSharedKey: psw,
isHiddenSsid: false,
securityType: scanInfo.securityType
}
if (wifi.connectToDevice(deviceConfig)) {
prompt.showToast({ message: 'connect success' })
wifi.addDeviceConfig(deviceConfig)
} else {
prompt.showToast({ message: 'connect fail' })
}
}
build() {
Column() {
QRCode(this.passwd)
.width(150)
.height(this.height)
.margin({top:50})
.color(Color.Green)
Button() {
Text($r('app.string.cancel'))
.fontColor(Color.Red)
.fontSize(18)
}
.backgroundColor(Color.White)
.margin(20)
.onClick(() => {
this.controller.close()
})
}
.width('80%')
.alignItems(HorizontalAlign.Center)
}
Column() {
QRCode(this.passwd)
.width(150)
.height(this.height)
.margin({top:50})
.color(Color.Green)
Button() {
Text($r('app.string.cancel'))
.fontColor(Color.Red)
.fontSize(18)
}
.backgroundColor(Color.White)
.margin(20)
.onClick(() => {
this.controller.close()
})
}
.width('80%')
.alignItems(HorizontalAlign.Center)
}
private animateStart(){
animateTo({
duration: 110,
tempo: 1,
curve: Curve.Sharp,
delay: 50,
iterations: 1,
playMode: PlayMode.Normal,
onFinish: () => {
}
}, () => {
this.height = 150;
});
}
private animateEnd(){
animateTo({
duration: 300,
tempo: 1,
curve: Curve.Linear,
delay: 200,
iterations: 1,
playMode: PlayMode.Normal,
onFinish: () => {
this.wifiModel.getScanInfos((result) => {
this.wifiList = result
})
this.scanWifi = '扫描WIFI';
}
}, () => {
this.btnWidth = 120;
this.btnHeight = 120;
this.borderRadius = 15;
});
}
animateTo({
duration: 110,
tempo: 1,
curve: Curve.Sharp,
delay: 50,
iterations: 1,
playMode: PlayMode.Normal,
onFinish: () => {
}
}, () => {
this.height = 150;
});
}
private animateEnd(){
animateTo({
duration: 300,
tempo: 1,
curve: Curve.Linear,
delay: 200,
iterations: 1,
playMode: PlayMode.Normal,
onFinish: () => {
this.wifiModel.getScanInfos((result) => {
this.wifiList = result
})
this.scanWifi = '扫描WIFI';
}
}, () => {
this.btnWidth = 120;
this.btnHeight = 120;
this.borderRadius = 15;
});
}
OpenHarmony -ArkUI(ETS)之WiFi简单的连接操作。
以上就是这次的全部内容,最终效果如动图所示。整个布局界面非常简单,但是能够实现WIFI连接的基本功能,其实WIFI功能提供的API中,还有很多能够扩展的地方,后续我也会继续学习,希望能更进一步的完善这一块的功能,写出更加优美流畅的示例。