HarmonyOS 7 API 26 ArkWeb 兼容性检查流程图

ArkWeb 相关问题最容易被低估。开发时页面能打开,就以为没问题;一到真机、弱网、文件上传、不同系统版本,白屏、上传没反应、错误页空白这些问题就会集中冒出来。

我现在更倾向于把 ArkWeb 当成一个“要验收的能力边界”,而不是只把它当成一个能显示网页的组件。尤其是 HarmonyOS 7 / API 26 之后,工程里如果要继续使用 Web 页面、H5 表单、协议页或内嵌工具页,至少要把这几件事提前查清楚:

  • 当前设备上的 ArkWeb 内核版本是否记录下来;
  • 页面加载失败时有没有本地兜底;
  • 文件选择、拍照上传、只读页面是不是分开处理;
  • 弱网下是一直等,还是超时、重试、展示错误页。

问题通常不是 Web 组件写错了

很多 ArkWeb 问题看起来像页面 Bug,实际是边界没有提前定义。

比如一个上传页面,正常网络下能打开,选择文件也能弹出来。上线后用户反馈“点上传没反应”,可能有几种完全不同的原因:

  • 页面加载失败,但没有错误页,所以用户只看到白屏;
  • 文件选择被权限或场景拦住,但页面没有提示;
  • 弱网请求一直挂着,页面没有超时;
  • 不同内核版本表现不一致,但日志里没有记录版本。

如果这些信息都没有,后面排查会很被动。你只能反复问用户“当时怎么操作的”,但没有办法从日志里直接判断是哪条边界出了问题。

先写一个提交前检查脚本

下面这个脚本用三个场景说明怎么检查:一个坏例子、一个上传页、一个只读 Web 页。

const CASES = [
  {
    name: 'bad-no-kernel-boundary',
    kernelVersion: '',
    allowFilePicker: true,
    hasBlankFallback: false,
    weakNetworkPolicy: 'wait-forever',
    minSdk: 26,
  },
  {
    name: 'good-api26-upload-page',
    kernelVersion: 'M144',
    allowFilePicker: true,
    hasBlankFallback: true,
    weakNetworkPolicy: 'timeout-and-retry',
    minSdk: 26,
  },
  {
    name: 'edge-readonly-webview',
    kernelVersion: 'M144',
    allowFilePicker: false,
    hasBlankFallback: true,
    weakNetworkPolicy: 'local-error-page',
    minSdk: 26,
  },
];

function inspect(item) {
  const errors = [];
  const warnings = [];
  if (!item.kernelVersion) {
    errors.push('ArkWeb kernel version is not recorded. Compatibility reports cannot be compared.');
  }
  if (!item.hasBlankFallback) {
    errors.push('No blank-page fallback. A failed load will look like a dead page.');
  }
  if (item.weakNetworkPolicy === 'wait-forever') {
    errors.push('Weak network policy waits forever. Add timeout, retry, or local error page.');
  }
  if (item.minSdk < 26) {
    warnings.push('This article targets API 26. Keep the demo boundary explicit.');
  }
  return { ...item, passed: errors.length === 0, errors, warnings };
}

const result = CASES.map(inspect);
console.log(JSON.stringify({
  total: result.length,
  passed: result.filter((item) => item.passed).length,
  failed: result.filter((item) => !item.passed).length,
  result,
}, null, 2));

本地跑完以后,结果是 3 个场景里 2 个通过、1 个失败:

{
  "total": 3,
  "passed": 2,
  "failed": 1
}

失败的 bad-no-kernel-boundary 很典型:没有内核版本、没有白屏兜底、弱网一直等。这个场景如果直接上线,用户看到的就是页面卡死,开发侧看到的日志也不够用。

第一类边界:内核版本必须进日志

ArkWeb 问题不能只记录“页面打开失败”,还要记录设备、系统版本、内核版本、页面地址和错误类型。

我会把日志字段拆成这样:

interface ArkWebReport {
  page: string
  scene: 'upload' | 'readonly' | 'agreement' | 'tool'
  kernelVersion: string
  osApi: number
  errorType: 'blank' | 'timeout' | 'file_picker_denied' | 'http_error'
  costMs: number
}

这样做的好处是后面能按版本归类。比如只有某个内核版本白屏,和所有版本都白屏,处理优先级完全不一样。

第二类边界:白屏要有本地兜底

Web 页面加载失败时,不要让用户面对空白区域。更稳的做法是把 Web 状态拆出来:

@State webLoading: boolean = true
@State webErrorText: string = ''

onPageBegin() {
  this.webLoading = true
  this.webErrorText = ''
}

onPageEnd() {
  this.webLoading = false
}

onPageError(message: string) {
  this.webLoading = false
  this.webErrorText = message || '页面暂时打不开,请稍后再试'
}

页面层再根据状态展示骨架或错误页:

if (this.webErrorText) {
  BlankFallback({ text: this.webErrorText })
} else {
  Web({ src: this.url })
}

这里的重点不是组件名,而是状态不能只藏在 Web 内部。页面自己要知道当前是加载中、加载失败还是正常展示。

第三类边界:上传页和只读页不要共用一套判断

上传页要关心文件选择,协议页或帮助页通常不需要。两类页面如果共用一套逻辑,很容易出现误判。

我会直接给场景加配置:

const webSceneConfig = {
  upload: {
    allowFilePicker: true,
    timeoutMs: 5000,
    fallback: '上传页面暂时不可用,请检查网络后重试',
  },
  readonly: {
    allowFilePicker: false,
    timeoutMs: 3000,
    fallback: '内容暂时打不开,已切换到本地说明',
  },
}

上传页失败时,要提示用户“上传能力不可用”;只读页失败时,可以展示本地说明或重试按钮。它们不是一个问题,也不应该用同一句提示糊过去。

方案对比

方案 优点 风险
只在页面失败后提示 改动少 不知道是网络、内核还是文件选择问题
加本地错误页 用户体验更稳 还需要补日志字段
内核版本 + 场景配置 + 超时兜底 排查和复用都更强 初次接入要多写一点配置

我会选第三种。它多写了一些代码,但换来的是可排查、可复用、可回归检查。后面再加新的 Web 页面时,只要按场景配置接入,不需要每个页面重新想一遍边界。

最后怎么验收

我会用这几项验收 ArkWeb 页面:

  • 正常网络下能打开目标页面;
  • 弱网或断网时不会一直白屏;
  • 上传页能区分文件选择失败和页面加载失败;
  • 日志里能看到内核版本、系统 API、页面场景和错误类型;
  • 只读页不误触上传逻辑,上传页不吞掉文件选择错误。

ArkWeb 不是“能打开网页就结束”。真正要稳,是把内核版本、页面场景、失败兜底和日志字段都提前拆开。这样出了问题以后,排查才不会只剩猜。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐