HarmonyOS鸿蒙Next中09-自然壁纸实战教程-视频下载

HarmonyOS鸿蒙Next中09-自然壁纸实战教程-视频下载

09-自然壁纸实战教程-视频下载

前言

视频下载页面的功能主要提供了视频的播放,和下载,因为下载比较耗时,所以这里还用到了多线程taskpoll来实现。

image

构造视频播放结构

视频组件初始化:

  • 使用 Video 组件,绑定视频资源 src、视频控制器 controller 和预览图片 previewUri
  • 设置视频播放器的宽度和高度,根据是否全屏显示调整高度。
  • 设置视频的适应模式为 contain,确保视频内容完整显示。
  • 启用自动播放和系统默认控件。

事件监听:

  • onStart:当视频开始播放时,将 isPlaying 状态设置为 true
  • onPause:当视频暂停时,将 isPlaying 状态设置为 false
  • onFinish:当视频播放结束时,将 isPlaying 状态设置为 false,并将当前时间 currentTime 重置为 0
  • onUpdate:实时更新当前播放时间 currentTime
  • onPrepared:当视频准备就绪后,立即开始播放,并将 isPlaying 状态设置为 true

快捷键和点击事件:

  • enableAnalyzer:设置组件支持AI分析,当前支持主体识别、文字识别和对象查找等功能,支持attributeModifier动态设置属性方法。
  • enableShortcutKey:启用快捷键功能,允许用户通过键盘快捷键控制视频播放。
  • 点击视频区域时,如果视频正在播放,则暂停播放;如果视频未播放,则开始播放。
Video({
      src: this.videoPlayerViewModel.videoUrl,
      controller: this.videoPlayerViewModel.controller,
      previewUri: this.videoPlayerViewModel.videoData?.videos?.medium?.thumbnail
    })
      .width('100%')
      .height(this.videoPlayerViewModel.isFullScreen ? '100%' : '240vp')
      .objectFit(ImageFit.Contain)
      .autoPlay(true)
      .controls(true)  // 使用系统默认控件
      .onStart(() => {
        this.videoPlayerViewModel.isPlaying = true
      })
      .onPause(() => {
        this.videoPlayerViewModel.isPlaying = false
      })
      .onFinish(() => {
        this.videoPlayerViewModel.isPlaying = false
        this.videoPlayerViewModel.currentTime = 0
      })
      .onUpdate((event) => {
        this.videoPlayerViewModel.currentTime = event.time
      })
      .onPrepared((event) => {
        this.videoPlayerViewModel.duration = event.duration
        // 视频准备好后立即开始播放
        this.videoPlayerViewModel.controller.start()
        this.videoPlayerViewModel.isPlaying = true
      })
      .enableAnalyzer(true)
      .enableShortcutKey(true)
      .onClick(() => {
        if (this.videoPlayerViewModel.isPlaying) {
          this.videoPlayerViewModel.controller.pause()
        } else {
          this.videoPlayerViewModel.controller.start()
        }
      })

下载视频

image

下载视频是这个项目中比较有意思的功能,因为是使用了多线程+下载的+保存到相册的能力,这里的主要逻辑是

下载视频的主要逻辑

主要逻辑:

  1. 检查下载状态:首先检查是否已有下载任务正在进行中,如果有则提示用户已有下载任务正在进行中并返回。
  2. 获取上下文和路径:获取应用的上下文对象和缓存目录路径,用于保存下载的视频文件。
  3. 配置下载任务:设置下载任务的配置信息,包括下载动作、视频URL、保存路径、进度条显示、覆盖文件、网络类型和任务标题等。
  4. 创建下载任务:使用request.agent.create方法创建下载任务,并处理创建成功或失败的情况。
  5. 开始下载任务:在下载任务创建成功后,调用task.start方法开始下载,并处理下载开始、进度更新、下载完成和下载失败的情况。
  6. 更新进度:在下载过程中,通过task.on('progress', ...)事件更新下载进度。
  7. 下载完成后的操作:在下载完成后,调用task.on('completed', ...)事件,将视频文件保存到相册,并更新下载状态和进度。
  8. 错误处理:在创建下载任务或下载过程中出现错误时,通过task.on('failed', ...)事件和catch块处理错误,并更新下载状态和进度。
  9. 重置进度条:在下载完成后,设置一个延迟后重置下载进度的操作,以确保用户界面能够正确反映下载状态。
// 下载视频
downFile() {
  if (this.isDownloading) {
    promptAction.showToast({ message: '已有下载任务进行中' });
    return;
  }
  //上下文对象
  let context = getContext(this) as common.UIAbilityContext
  let filesDir = context.cacheDir
  //保存到的沙箱路径
  let filePath = `${filesDir}/${Date.now()}.mp4`;
  this.filePath = filePath
  //下载任务的配置信息
  let config: request.agent.Config = {
    action: request.agent.Action.DOWNLOAD,
    url: this.videoUrl,
    saveas: filePath,
    gauge: true,
    overwrite: true,
    network: request.agent.Network.WIFI,
    title: this.videoData?.tags.split(',')[0] || 'video_download' // 添加下载任务标题
  }
  //创建下载任务
  request.agent.create(context, config)
    .then(async (task: request.agent.Task) => {
      this.isDownloading = true; // 开始下载
      this.downloadProgress = 0; // 重置进度
      //创建成功之后,开始下载任务
      task.start((err: BusinessError) => {
        if (err) {
          request.agent.remove(task.tid)
          promptAction.showToast({ message: '下载失败' })
          this.isDownloading = false; // 下载失败
          this.downloadProgress = 0;
        } else {
          promptAction.showToast({ message: '开始下载...' })
        }
      })
      task.on('progress', (progressInfo: request.agent.Progress) => { // Explicitly type progressInfo
        if (progressInfo.sizes[0] > 0) {
          this.downloadProgress =
            Math.floor((progressInfo.sizes[0] / progressInfo.sizes[0]) * 100);
        }
      })
      task.on('completed', async () => {
        //下载完成--->保存到相册
        this.isDownloading = false; // 下载完成
        this.downloadProgress = 100; // 确保进度为100%
        promptAction.showToast({ message: '下载完成,正在保存到相册...' });
        this.save(filePath)
        // 可以在这里稍作延迟后重置进度条,或者在保存成功后
        setTimeout(() => {
          this.downloadProgress = 0;
        }, 2000);
      })
      task.on('failed', () => {
        promptAction.showToast({ message: '下载任务失败' });
        this.isDownloading = false;
        this.downloadProgress = 0;
      })
    })
    .catch((err: BusinessError) => {
      promptAction.showToast({ message: `创建下载任务失败: ${err.message}` });
      this.isDownloading = false;
      this.downloadProgress = 0;
    })
}

保存到相册

该功能在之前的教程中已经出现过了,

  1. 获取当前应用的上下文(context)。
  2. 创建一个photoAccessHelper对象,用于访问和管理设备的照片和视频库。
  3. 定义一个包含源文件URI的数组srcFileUris,这里只包含一个URI,即要保存的视频文件。
  4. 定义一个photoCreationConfigs数组,其中包含了保存视频时的配置信息,如文件名后缀、照片类型(这里是视频)、标题和子类型等。
  5. 调用showAssetsCreationDialog方法,弹出授权对话框,让用户选择保存视频的目标位置,并返回目标URI。
  6. 使用fileIo.open方法以读写模式打开源文件和目标文件。
  7. 使用fileIo.copyFile方法将源文件的内容复制到目标文件中。
  8. 关闭源文件和目标文件。
  9. 如果保存成功,显示成功提示信息;如果失败,显示失败提示信息。
// 保存到相册
async save(srcFileUri: string) {
  let context = getContext(this)
  let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
  try {
    let srcFileUris: Array<string> = [
      srcFileUri
    ];
    // 指定待保存照片的创建选项,包括文件后缀和照片类型,标题和照片子类型可选
    let photoCreationConfigs: Array<photoAccessHelper.PhotoCreationConfig> = [
      {
        title: `${Date.now()}`, // 可选
        fileNameExtension: 'mp4',
        photoType: photoAccessHelper.PhotoType.VIDEO,
        subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选
      }
    ];
    // 基于弹窗授权的方式获取媒体库的目标uri
    let desFileUris: Array<string> = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
    // 将来源于应用沙箱的内容写入媒体库的目标uri
    let desFile: fileIo.File = await fileIo.open(desFileUris[0], fileIo.OpenMode.WRITE_ONLY);
    let srcFile: fileIo.File = await fileIo.open(srcFileUri, fileIo.OpenMode.READ_ONLY);
    await fileIo.copyFile(srcFile.fd, desFile.fd);
    fileIo.closeSync(srcFile);
    fileIo.closeSync(desFile);
    promptAction.showToast({ message: '保存成功' })
  } catch (error) {
    promptAction.showToast({ message: '保存失败' })
  }
}

如何获取资料

获取资料的途径,可以关注我们 官网的公众号 青蓝逐码 ,输入 项目名称 《自然壁纸》 即可获得以上资料。

image

为什么需要关注公众号

如果我们的资源,网友连关注公众号的欲望都没有,说明我们的这个资料和资源也没有什么太大价值,那么不要也罢,可以让用户付出一些成本的,才是能证明有真正价值的东西。

关于我们

关于青蓝逐码组织

如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯甚至你想要做出一款属于自己的应用!欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。

image


更多关于HarmonyOS鸿蒙Next中09-自然壁纸实战教程-视频下载的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

插眼:视频下载

更多关于HarmonyOS鸿蒙Next中09-自然壁纸实战教程-视频下载的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中实现09-自然壁纸的视频下载功能,主要涉及以下步骤:

  1. 使用@ohos.net.http模块创建HTTP请求
  2. 配置下载参数(URL、存储路径等)
  3. 通过download方法启动下载任务
  4. 监听下载进度和状态变化

关键代码示例:

let downloadTask = request.download(
  context, 
  {
    url: '视频URL',
    filePath: '本地存储路径'
  }
);
downloadTask.on('progress', (received, total) => {
  // 处理进度
});

注意:需申请ohos.permission.INTERNETohos.permission.WRITE_MEDIA权限。

这是一个关于HarmonyOS Next中实现视频下载功能的详细教程。主要包含以下几个关键点:

  1. 视频播放功能实现:
  • 使用Video组件实现视频播放器
  • 通过controller控制播放状态
  • 添加了onStart/onPause/onFinish等事件监听
  1. 视频下载功能:
  • 使用request.agent创建下载任务
  • 支持进度显示和错误处理
  • 下载完成后自动保存到相册
  1. 多线程处理:
  • 通过taskpool实现后台下载
  • 避免阻塞UI线程
  1. 相册保存:
  • 使用photoAccessHelper API
  • 需要用户授权

代码示例清晰展示了如何实现这些功能,包括视频播放控制、下载进度监控和文件保存等关键逻辑。这个实现方案充分利用了HarmonyOS的API能力,是一个典型的多媒体处理案例。

回到顶部