在 OpenHarmony 生态持续演进的过程中,API 版本的迭代升级为应用开发带来了更多新特性与性能优化,但同时也对存量项目的适配工作提出了挑战。梅科尔工作室近期完成了 “滑动视频自动播放” 示例项目从 API9 到 API20 的全流程升级适配,本文将从环境搭建、代码改造、问题排查、功能解析等多个维度,完整分享本次升级实践的全过程,为开发者提供可复用的适配思路与实战经验。

一、项目背景与升级价值

本次适配的 “滑动视频自动播放” 项目,核心实现了视频列表滑动至屏幕中间自动播放、滑动返回续播的典型短视频场景,基于 OpenHarmony 的 List 组件、LazyForEach 懒加载、XComponent+AVPlayer 等核心能力开发。原项目基于 API9 构建,而 API20 作为 OpenHarmony 的高版本 SDK,在性能优化、组件能力、开发体验上均有显著提升:

  • 对 LazyForEach 的缓存机制做了精细化优化,降低大列表场景的内存占用;
  • XComponent 组件的 surfaceId 绑定逻辑更稳定,提升视频渲染的流畅度;
  • Stage 模型的工程配置更规范,适配多设备部署的兼容性。升级至 API20 不仅能解决原项目在高版本系统上的兼容性问题,还能充分利用新版本的特性优化视频播放体验。

二、升级前的环境准备

1. 基础环境搭建

首先需完成适配的基础环境配置,确保开发工具与系统环境满足 API20 的要求:

  • DevEco Studio 版本升级:原项目使用的低版本 DevEco Studio 不支持 API20 编译,需升级至 DevEco Studio 6.0.0 Release 及以上版本,该版本对 API20 的 Stage 模型提供了完善的编译、调试支持;
  • 系统镜像与 HDC 工具配置:烧录支持 API20 的 OpenHarmony 标准系统镜像,安装最新版 HDC 工具并完成环境变量配置,确保设备与开发工具的正常连接;
  • 开机不熄屏设置:为避免调试过程中屏幕熄灭影响视频播放测试,需修改设备的电源设置,配置开机后屏幕常亮。

2. AtomGit 平台协同配置(可选)

若项目基于 AtomGit 托管,需完成开源配置与协同操作适配:

  • 新建 API20 分支:在 AtomGit 仓库中创建api20-adaptation分支,避免直接修改主分支代码;
  • 开源权限配置:确保仓库的开源协议(如 Apache 2.0)适配 OpenHarmony 生态要求,配置分支保护规则,防止误提交;
  • 协同提交流程:制定 “开发 - 自测 - 提 MR - 代码评审 - 合并” 的协同流程,确保升级过程中代码的可追溯性。

三、核心代码改造流程

1. 工程配置文件修改

API9 与 API20 的工程配置结构存在显著差异,核心修改build-profile.json5文件:

  • 原 API9 配置问题:原配置中products节点直接包含compileSdkVersioncompatibleSdkVersion等字段,且runtimeOS存在语法错误(中文逗号),同时缺少targets节点,不符合 API20 的工程规范;
  • API20 适配修改
    // 新增targets节点,指定运行时系统
    "targets":[
      {
        "name":"default",
        "runtimeOS":"OpenHarmony"
      }
    ]
    // 调整products节点字段
    "products":[
      {
        "name": "default",
        "signingConfig":"default",
        "compileSdkVersion":20, // 升级为API20
        "targetSdkVersion":20,  // 新增targetSdkVersion,与compileSdkVersion一致
        "compatibleSdkVersion":9, // 保留向下兼容API9
        "runtimeos":"OpenHarmony",
      }
    ]

    此处需注意字段名的大小写(如runtimeOS修正为runtimeos),以及新增targetSdkVersion字段,这是 API20 Stage 模型的强制要求。

2. 核心功能代码适配

项目的核心逻辑基于 List 组件的onScrollIndex、LazyForEach 懒加载、XComponent+AVPlayer 视频渲染,升级过程中需针对 API20 的特性调整核心逻辑:

(1)List 组件与 LazyForEach 适配

API20 对 LazyForEach 的cachedCount参数解析逻辑做了优化,原代码中cachedCount(CACHE_COUNT)的配置无需修改,但需确认onScrollIndex的回调参数类型:

List() {
  LazyForEach(this.newsList, (news: NewsItem, index: number) => {
    ListItem() {
      XComponentVideo({
        centerIndex: this.centerIndex,
        news: news,
        index: index
      })
    }
    .backgroundColor('#fff6f6f6')
    .borderRadius(30)
    .margin({ bottom: 20 })
  }, (item: string) => item)
}
.cachedCount(CACHE_COUNT) 
// API20中onScrollIndex的参数类型更严格,需显式指定number类型
.onScrollIndex((firstIndex: number, lastIndex: number, centerIndex: number) => {
  this.centerIndex = centerIndex; // 获取中间索引,核心逻辑无变化
})

此处需注意,API20 对类型推导的要求更严格,需显式声明回调参数的类型,避免编译报错。

(2)XComponent 与 AVPlayer 视频渲染适配

API20 对媒体服务的 API 做了兼容性调整,核心修改在于 AVPlayer 的状态监听与 surfaceId 绑定:

  • 状态监听优化:原 API9 中 AVPlayer 的initialized状态回调可能存在延迟,API20 中新增了状态防抖机制,需调整setSurfaceID的调用时机:
case 'initialized':
  logger.info('state initialized called');
  // API20中需等待XComponent完全加载后再绑定surfaceId
  setTimeout(() => {
    this.setSurfaceID(); 
    this.avPlayer.prepare(); 
  }, 100);
  break;

音频中断模式适配:API20 中InterruptMode.INDEPENDENT_MODE的枚举值路径调整,需修正导入路径:

// API9导入路径
import { InterruptMode } from '@ohos.multimedia.audio';
// API20导入路径
import { audio } from '@kit.MultimediaKit';
this.avPlayer.audioInterruptMode = audio.InterruptMode.INDEPENDENT_MODE;

(3)UI 显隐控制适配

API20 对Visibility枚举的兼容性做了调整,原代码中Visibility.Visible/None的使用需确认导入路径:

Image(news.newsImage)
  .borderRadius(30)
  .visibility(this.startOrEnd || !this.flag || this.imageChange ?
  Visibility.Visible :
  Visibility.None)
  .zIndex(1)

需确保导入@ohos.arkui.advanced中的Visibility,而非旧版的@ohos.arkui

四、升级过程中的典型问题与解决方案

问题 1:编译报错 “targets 节点缺失”

现象:升级后编译工程时,提示 “Stage 模型必须配置 targets 节点”;原因:API20 强制要求 Stage 模型的工程配置包含targets节点,原 API9 配置中无该节点;解决方案:按前文所述,在build-profile.json5中新增targets节点,指定nameruntimeOS

问题 2:视频滑动后无法自动播放

现象:滑动列表后,中间位置的视频无法触发播放;原因:API20 中onScrollIndex的回调时机延迟,centerIndex更新不及时,导致onIndexChange中判断逻辑失效;解决方案:新增centerIndex的监听机制,使用@Watch装饰器实时监听值变化:

@State @Watch('onIndexChange') centerIndex: number = 0;

onIndexChange() {
  if (this.isLoadingVideo) {
    if (this.centerIndex === this.index) {
      this.isPlaying = true;
      this.getPlay();
    } else {
      this.isPlaying = false;
      this.getPause();
    }
  }
}

问题 3:XComponent 渲染黑屏

现象:视频加载后 XComponent 区域黑屏,仅显示封面图;原因:API20 中 XComponent 的surfaceId获取时机提前,在 XComponent 未完全加载时调用getXComponentSurfaceId返回空值;解决方案:在onLoad回调中确保 XComponent 加载完成后再获取surfaceId

XComponent({
  type: XComponentType.SURFACE,
  controller: this.xComponentController
})
.onLoad(() => {
  // 增加延迟,确保XComponent初始化完成
  this.xComponentController.on('ready', () => {
    this.surfaceID = this.xComponentController.getXComponentSurfaceId();
    this.videoSrc = news.newsVideoSrc;
    this.init();
  });
})

五、升级后项目的使用与二次开发指南

1. 项目下载与部署

开发者可通过以下命令从开源仓库下载升级后的项目:

git init
git config core.sparsecheckout true
echo code/UI/VideoListAutoPlay/ > .git/info/sparse-checkout
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
git pull origin master

部署步骤:

  • 打开 DevEco Studio 6.0.0+,导入下载的项目;
  • 配置 API20 的 SDK(File > Project Structure > SDK Location);
  • 连接支持 API20 的 OpenHarmony 设备,点击 “Run” 编译运行。

2. 功能使用说明

  • 首次启动应用后,首页中间的视频会自动加载并播放;
  • 上下滑动列表,当视频滑动至屏幕中间位置时,会自动触发播放,离开中间位置则暂停;
  • 滑动返回已播放过的视频,会从暂停位置继续播放。

3. 二次开发建议

  • 扩展视频源:修改NewsItemModel.ets中的newsList数据,可替换为自定义的视频 URL 和封面图;
  • 调整缓存数量:修改CACHE_COUNT常量,可根据设备性能调整懒加载的缓存数量,建议值为 3-5;
  • 新增播放控制:在XComponentVideo.ets中新增暂停 / 播放按钮,实现手动控制视频播放状态。

六、总结与展望

本次从 API9 到 API20 的升级适配,不仅解决了原项目的兼容性问题,还借助 API20 的新特性优化了视频播放的流畅度和稳定性。核心的适配要点包括工程配置的调整、组件 API 的兼容性修改、状态监听逻辑的优化。在适配过程中,我们发现 API20 对类型安全、生命周期管理的要求更严格,这也符合 OpenHarmony 生态向规范化、高性能演进的趋势。

未来,梅科尔工作室将继续跟进 OpenHarmony 的版本迭代,针对更多典型场景完成 API 升级适配,并将适配经验同步至开源仓库(https://gitcode.com/MakerStudio/video_player)。同时,也建议开发者在升级过程中,优先做好环境准备和代码备份,分模块逐步验证适配效果,确保项目的平稳过渡。

 

 

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐