【HarmonyOS】纯血鸿蒙真实项目开发---经验总结贴
项目场景:
将已有的Web网页接入到原生App。
涉及到一些网页回退、webviewController执行时机报错1710000001、位置定位数据获取、拉起呼叫页面、系统分享能力使用等。
问题描述
- 我们在选项卡组件中,在每个TabContent内容页中使用web组件加载网页。
在最开始接入操作时,出现了Web组件加载某个页面,出现白屏、页面显示不出来。
解决方案:
经过对问题定位,发现需要设置是否开启文档对象模型存储接口(DOM Storage API)权限,默认未开启。
Web({ src: this.webSrc, controller: this.webviewController }).domStorageAccess(true);
问题描述
- 每个TabContent内容页中使用web组件加载的网页,会涉及到一些页面的返回。如果是用户点击返回,网页端会进行回退操作,若用户使用侧滑返回网页端无法检测,会直接退出应用。
解决方案:
为了解决这个问题,我查阅到了有关侧滑返回或点击返回按钮时触发的自定义组件生命周期onBackPress(仅@Entry装饰的自定义组件生效)
@Entry
@Component
struct IndexComponent {@State textColor: Color = Color.Black;onBackPress() {this.textColor = Color.Red;console.info('IndexComponent onBackPress');}build() {Column() {Text('Hello World').fontColor(this.textColor).fontSize(30).margin(30)}.width('100%')}
}
返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。
重点:在每个TabContent内容页加载的@Entry页面里,使用onBackPress是不生效的。我们只能在Tab所在的@Entry页面里,使用onBackPress才会生效。
为了控制TabContent中的Web页面回退,我们需要在Tab所在的页面里创建webviewController并将它传递给子组件。
父组件示例代码:
import { Page1, Page2 } from './Page1'@Entry
@Component
struct demo {//controller创建@Provide webcontroller1: webview.WebviewController = new webview.WebviewController();@Provide webcontroller2: webview.WebviewController = new webview.WebviewController();//返回逻辑onBackPress() {if (this.webcontroller1.accessStep(-1)) {this.webcontroller1.backward()// 执行用户自定义返回逻辑return true;} else if (this.webcontroller2.accessStep(-1)) {this.webcontroller2.backward();// 执行用户自定义返回逻辑return true;} else {//执行系统默认返回逻辑,返回上一个page页return false;}}build() {Tabs(){TabContent(){Page1()}.tabBar('示例一')TabContent(){Page2()}.tabBar('示例二')}}
}
子组件示例代码:
import { webview } from '@kit.ArkWeb'@Entry
@Component
export struct Page1/2 {@Consume webcontroller1/2:webview.WebviewControllerbuild() {RelativeContainer() {Web({src:'https://www.baidu.com',controller:this.webcontroller1/2}).domStorageAccess(true)}.height('100%').width('100%')}
}
问题描述
- 因为每个Web页面的控制器是由父组件传入的,我们在使用时可能会出现710000001的报错,经查阅论坛发现,该报错原因是Web组件还未创建,我们的WebviewController控制器先执行了。
高发于在emitter中调用WebviewController控制器,尽量避免在emitter中使用,若必须使用参照下面的解决方案
解决方案:
解决这个问题,我并没有发现可以统一解决各种情况的方法。以下有多种解决方法:
- [1] 在web组件的生命周期onPageEnd中使用控制器
- [2]在onControllerAttached()这一回调方法中使用控制器
- [3]在onDisAppear中使用控制器
问题描述
- 我们在一些场景下可能会需要用户的具体位置,以下是关于用户授权和逆地址编码转化,获取地址位置描述的方案总结。
解决方案:
获取用户位置授权onClickGetLocation = async () => {//首次权限请求if (this.step == 0) {const steps = await abilityAccessCtrl.createAtManager().requestPermissionsFromUser(getContext(),['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'])this.step++}// 二次请求用户同意权限await this.checkPermissions()//获取当前位置let Location = await geoLocationManager.getCurrentLocation();await this.locationChange(Location)return JSON.stringify(this.returnInfor)}
若用户拒绝定位权限二次拉起async checkPermissions() {let grantStatus1: boolean = await WebUtils.checkPermissionGrant('ohos.permission.LOCATION') ===abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED; // 获取精确定位权限状态let grantStatus2: boolean = await WebUtils.checkPermissionGrant('ohos.permission.APPROXIMATELY_LOCATION') ===abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED; // 获取模糊定位权限状态// 精确定位权限只能跟模糊定位权限一起申请,或者已经有模糊定位权限才能申请精确定位权限if (!grantStatus2 && !grantStatus1) {// 用户拒绝二次拉起弹窗let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();let context: Context = getContext(this) as common.UIAbilityContext;await atManager.requestPermissionsFromUser(context,['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'])await atManager.requestPermissionOnSetting(context, ['ohos.permission.APPROXIMATELY_LOCATION']).then((data: Array<abilityAccessCtrl.GrantStatus>) => {console.info('data:' + JSON.stringify(data));}).catch((err: BusinessError) => {console.error('data:' + JSON.stringify(err));});} else {// 已经授权,可以继续访问目标操作return}}
/** * 定位回调 *///获取用户位置信息private async locationChange(location: geoLocationManager.Location) {if (location) {let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest = {'latitude': location.latitude, // 表示纬度信息,正值表示北纬,负值表示南纬。取值范围为-90到90。仅支持WGS84坐标系。'longitude': location.longitude, // 表示经度信息,正值表示东经,负值表是西经。取值范围为-180到180。仅支持WGS84坐标系。// 指定返回位置信息的最大个数。取值范围为大于等于0,推荐该值小于10。默认值是1。'maxItems': 1};// 逆地址编码转化,获取地址位置描述let data = await geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest);if (data) {if (data[0].locality !== undefined) {let res = data[0] as DeatilPositionViewPagelet placeName = res.placeNamelet countryName = res.countryNamelet provience = placeName.slice(0, placeName.indexOf('省') + 1)let city = placeName.slice(placeName.indexOf('省') + 1, placeName.indexOf('市') + 1)let area = placeName.slice(placeName.indexOf('市') + 1, placeName.indexOf('区') + 1)let deatil = placeName.slice(placeName.indexOf('区') + 1)let address = `${countryName} ${provience} ${city} ${area} ${deatil}`this.returnInfor = {address: address,longitude: res.longitude,latitude: res.latitude}}}}};
运行使用代码块
@Entry
@Component
export struct Page1 {@State returnInfor: returnDeatilPosition = {address: '',longitude: 0,latitude: 0}//判断是否为首次请求step = 0//写入上面三个方法build() {RelativeContainer() {Button(this.returnInfor).onclick(async()=>{await this.onClickGetLocation()})}.height('100%').width('100%')}
}
问题描述
- 我们在一些场景下可能会需要拉起用户的拨号界面,以下是关于拉起拨号的方案总结。
值得注意的是如果这里是混合开发需要的功能,我们可以把该方法写在.onLoadIntercept((event) => {})这个方法里面。具体相关使用自行查阅官方文档,较为简单不做赘述。
解决方案:
import { call, observer } from '@kit.TelephonyKit';
import { BusinessError } from '@kit.BasicServicesKit';// 调用查询能力接口@Entry
@Component
struct callphone {build() {Text('1111').onClick(()=>{let isSupport = call.hasVoiceCapability();if (isSupport) {// 如果设备支持呼叫能力,则继续跳转到拨号界面,并显示拨号的号码call.makeCall("4009609206", (err: BusinessError) => {});}})}
}
问题描述
- 我们在一些场景下可能会需要用到系统分享能力,以下是关于系统分享的方案总结。
解决方案:
async share(ctx: Context, url: string, title: string) {let shareData: systemShare.SharedData = new systemShare.SharedData({utd: uniformTypeDescriptor.UniformDataType.HYPERLINK,content: url,title: title,description: '分享此链接',});
相关文章:
【HarmonyOS】纯血鸿蒙真实项目开发---经验总结贴
项目场景: 将已有的Web网页接入到原生App。 涉及到一些网页回退、webviewController执行时机报错1710000001、位置定位数据获取、拉起呼叫页面、系统分享能力使用等。 问题描述 我们在选项卡组件中,在每个TabContent内容页中使用web组件加载网页。 在…...

kettle做增量同步,出现报错:Unrecognized VM option ‘MaxPermSize-256m‘
本文内容来自YashanDB官网,原文内容请见:https://yashandb.com/newsinfo/7863039.html?templateId1718516 问题现象 kettle在增量同步过程,出现报错:Unrecognized VM option ‘MaxPermSize256m’ 问题的风险及影响 无法使用ke…...
网络安全、Web安全、渗透测试之笔经面经总结(三)
本篇文章涉及的知识点有如下几方面: 1.什么是WebShell? 2.什么是网络钓鱼? 3.你获取网络安全知识途径有哪些? 4.什么是CC攻击? 5.Web服务器被入侵后,怎样进行排查? 6.dll文件是什么意思,有什么…...

计算机的错误计算(二百零五)
摘要 基于一位读者的问题,提出题目:能用数值计算证明 吗?请选用不同的点(即差别大的数)与不同的精度。实验表明,大模型理解了题意。但是,其推理能力值得商榷。 例1. 就摘要中问题࿰…...

Vue3(一)
1.Vue3概述 Vue3的API由Vue2的选项式API改为了组合式API。但是,也是Vue2中的选项式API也是兼容的。 2.创建Vue3项目 create-vue 是 Vue 官方新的脚手架工具,底层切换到了 vite。使用create-vue创建项目的步骤如下: 安装 create-vue npm i…...

【项目】修改远程仓库地址、报错jdk
一、修改远程仓库地址 进入你刚刚克隆到本地的仓库目录,执行以下命令来修改远程仓库的 URL,将其指向你自己的新仓库: cd 原仓库名 git remote set-url origin <你自己的新仓库的 Git 地址>补充: 错误分析: wa…...

实训云上搭建集群
文章目录 1. 登录实训云1.1 实训云网址1.2 登录实训云 2. 创建网络2.1 网络概述2.2 创建步骤 3. 创建路由器3.1 路由器名称3.1 创建路由器3.3 查看网络拓扑 4. 连接子网5. 创建虚拟网卡5.1 创建原因5.2 查看端口5.3 创建虚拟网卡 6. 管理安全组规则6.1 为什么要管理安全组规则6…...

豆包ai 生成动态tree 增、删、改以及上移下移 html+jquery
[豆包ai 生成动态tree 增、删、改以及上移下移 htmljquery) 人工Ai 编程 推荐一Kimi https://kimi.moonshot.cn/ 推荐二 豆包https://www.doubao.com/ 实现效果图 html 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF…...

【网络协议】IPv4 地址分配 - 第二部分
前言 在第 1 部分中,我们学习了 IPv4 地址的分配方式,了解了各种类型的 IPv4 地址,并进行了基础的子网划分(Subnetting)。在第 2 部分中,我们将继续学习子网划分,并引入一些新的概念。 【网络…...

攻防世界 bug
发现有Register界面,先去注册 登录以后发现以下界面,点击Manage显示you are not admin,并且在注册界面用admin为注册名时显示用户名已存在。初步推测是设法改变admin的密码取得权限。 在主界面一通操作并没有什么发现,去findpw…...
Flink如何设置合理的并行度
一个Flink程序由多个Operator组成(source、transformation和 sink)。 一个Operator由多个并行的Task(线程)来执行, 一个Operator的并行Task(线程)数目就被称为该Operator(任务)的并行度(Parallel)。即并行度就是相对于Operator来说的。 合理设置并行度可以有效提高Flink作业…...

小兔鲜儿:生鲜区域,最新专题
生鲜区域: 生鲜区域标题部分: 生鲜区域内容部分: 分左右两个部分 右边区域是8个 li 标签区域,li中嵌套 a ,上部分是图片,下部分是内容;与 a 并列的是cover,定位在 li 之外,设置是溢出隐藏&…...
TypeScript语言的网络编程
基于 TypeScript 的网络编程探索 随着互联网技术的发展,网络编程已成为软件开发中不可或缺的一部分。尤其是在构建现代 Web 应用程序时,网络编程的各个方面,包括 HTTP 请求、WebSocket、API 交互等,都扮演着至关重要的角色。Type…...

复合机器人助力手机壳cnc加工向自动化升级
在当今竞争激烈的制造业领域,如何提高生产效率、降低成本、提升产品质量,成为众多企业面临的关键挑战。尤其是在手机壳 CNC 加工这一细分行业,随着市场需求的持续增长,对生产效能的要求愈发严苛。而复合机器人的出现,正…...

在 C# 中显示动画 GIF 并在运行时更改它们
您可以通过将按钮、图片框、标签或其他控件的Image属性设置为 GIF 文件 来显示动画 GIF 。(如果您在窗体的BackgroundImage属性中显示一个,则不会获得动画。) 有几种方法可以在运行时更改 GIF。 首先,您可以将 GIF 添加为资源。…...

个人博客搭建(二)—Typora+PicGo+OSS
个人博客站—运维鹿: http://www.kervin24.top CSDN博客—做个超努力的小奚: 做个超努力的小奚-CSDN博客 一、前言 博客搭建完一直没有更新,因为WordPress自带的文档编辑器不方便,以前用CSDN写作的时候,习惯了Typora。最近对比了…...

Cloudflare IP 优选工具:轻松找到最快的 CDN 节点
Cloudflare IP 优选工具:轻松找到最快的 CDN 节点 在线体验地址:https://cf-ip.cdtools.click 功能介绍 Cloudflare IP 优选工具是一个专门用于测试和筛选 Cloudflare CDN 节点的在线服务。它能够帮助用户找到最适合自己的 Cloudflare IP 地址ÿ…...

HTB:Ransom[WriteUP]
目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用ffuf对靶机80端口进行路径FUZZ 访问/regist…...

Eclipse配置Tomcat服务器(最全图文详解)
前言: 本章使用图文讲解如何在Eclipse开发工具中配置Tomcat服务器、如何创建和启动JavaWeb工程,欢迎童鞋们互相交流。觉得不错可以三连订阅喔。 目标: 一、配置Tomcat服务器 1. 切换Eclipse视图 2. 打开菜单 3. 找到服务选项 4. 选择…...

STM32烧写失败之Contents mismatch at: 0800005CH (Flash=FFH Required=29H) !
一)问题:用ULINK2给STM32F103C8T6下载程序,下载方式设置如下: 出现下面两个问题: 1)下载问题界面如下: 这个错误的信息大概可以理解为,在0x08000063地址上读取到flash存储为FF&am…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...