0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于HarmonyOS Player类实现的应用程序——Codelab技术

鸿蒙系统HarmonyOS 来源:鸿蒙社区 作者:attitude 2021-03-17 15:59 次阅读

1. 介绍

本篇Codelab将实现的内容

本篇Codelab旨在让开发者了解手机HarmonyOS应用开发,常用布局、典型控件、FA组件、媒体-视频、跨设备协同的体验以及从工程创建到代码和布局的编写,再到编译构建、部署和运行全过程。

您将构建一个基于HarmonyOSPlayer类实现的应用程序,该应用程序功能为播放本地视频资源或从Internet获得的视频资源。效果图如下:

您将会学到什么

●如何使用Player类播放视频
●如何使用自定义控件来控制视频播放
●如何添加并使用媒体事件的事件侦听器和回调

硬件要求

操作系统:Windows10 64位
●内存:8GB及以上
●硬盘:100GB及以上
●分辨率:1280*800像素及以上

软件要求

●安装Huawei DevEco Studio,详情请参考下载和安装软件
●设置Huawei DevEco Studio开发环境,Huawei DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境
1.如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作
2.如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境

说明

如需要在手机中运行程序,则需要提前申请证书,如使用模拟器可忽略

●生成秘钥和申请证书,详情请参考准备签名文件

技能要求

●具备DevEco Studio中创建、构建和运行应用经验
●熟悉Ability和AbilitySlice生命周期及使用PA/FA的能力

2. 代码结构

本篇Codelab只对核心代码进行讲解,对于完整代码,我们在参考提供下载方式。接下来我们会讲解整个工程的代码结构,如下图:

●api:视频播放状态改变及屏幕状态变化监听。
●constant:定义视频状态、进度条和控制器状态。

●factoty:创建SourceFactory类来根据视频来源创建视频源。
●manager:创建HmPlayerLifecycle来处理Player类的生命周期。
●view:创建PlayerLoading、SimplePlayerController类分别为视频加载状态及进度条控制类文件。
●HmPlayer:封装播放器的主要功能方法。
●slice:创建MainAbilitySlice、SimplePlayerAbilitySlice分别为进入应用的主程序页面和视频播放页面。
●utils:存放所有封装好的公共方法,如DateUtils,LogUtils等。
●resources:存放工程使用到的资源文件,其中resourcesaselayout下存放xml布局文件;resourcesasemedia下存放视频文件。
●config.json:Ability声明及权限配置。

3. 创建视频播放业务逻辑

该应用程序可播放的视频格式包括mp4、mov、3gp、mkv,首先准备一份视频文件并复制到"resources/base/layout/media"文件目录。下面将会介绍视频列表布局及播放逻辑。

创建视频播放页面文件及布局

Step 1 -创建simple_video_play_layout.xml布局文件展示视频列表。

    xmlns:ohos="http://schemas.huawei.com/res/ohos" 
    ohos:id="$+id:parent" 
    ohos:height="match_parent" 
    ohos:width="match_parent"> 
     

该布局文件有两个id,parent是整个播放页面的布局id,parent_layout是视频画面的布局id。

Step 2- 创建SimplePlayerAbilitySlice类,初次创建该页面进行初始化。

@Override 
public void onStart(Intent intent) { 
    super.onStart(intent); 
    super.setUIContent(ResourceTable.Layout_simple_video_play_layout); 
    // 在Constants中定义视频播放的起始位置 
    startMillisecond = intent.getIntParam(Constants.INTENT_STARTTIME_PARAM, 0); 
    // 初始化surface布局 
    initView(); 
    player.getLifecycle().onStart(); 
}

将预置的视频资源初始化为url对象,并通过initView方法对视频播放的控件进行初始化及赋值。

private String url = "entry/resources/base/media/gubeishuizhen.mp4"; 
private void initView() { 
    DependentLayout playerLayout = (DependentLayout) findComponentById(ResourceTable.Id_parent_layout); 
    player = new HmPlayer.Builder(this).setStartMillisecond(mStartMillisecond).setFilePath(url).create(); 
    playerLayout.addComponent(player.getPlayerView()); 
    player.play(); 
}

结束

创建HmPlayer

HmPlayer类是继承自对HarmonyOS Player封装的ImPlayer。如果您还不了解HarmonyOS Player,请参考视频播放开发指导。

需要注意的是当页面初始化Player类执行play方法时,视频并没有出现画面。图像渲染在屏幕上需要使用SurfaceProvider,该类控制surface的尺寸和格式,修改surface的像素,监视surface的变化等等。当底层显示系统第一次创建surface之后会调用surfaceCreated(SurfaceOps surfaceOps)回调函数。HmPlayer中通过设置回调增加对视频的播放开始或停止控制。

private SurfaceOps.Callback surfaceCallback = new SurfaceOps.Callback() { 
    @Override 
    public void surfaceCreated(SurfaceOps surfaceOps) { 
        // 标记surfaceView状态 
        isSurfaceViewCreated = true; 
        surface = surfaceOps.getSurface(); 
        start(); 
    } 
  
    @Override 
    public void surfaceChanged(SurfaceOps surfaceOps, int i, int width, int height) { 
        LogUtil.info(TAG, "surfaceChanged i is " + i + ",width is " + width + ",height is " + height); 
    } 
  
    @Override 
    public void surfaceDestroyed(SurfaceOps surfaceOps) { 
        LogUtil.info(TAG, "surfaceDestroyed"); 
        isSurfaceViewCreated = false; 
    } 
};

surfaceView的初始化在HmPlayer构造函数中:
private HmPlayer(Builder builder) {

    ... 
    surfaceView = new SurfaceProvider(playerBuilder.mContext); 
    DependentLayout.LayoutConfig layoutConfig = new DependentLayout.LayoutConfig(); 
    layoutConfig.addRule(DependentLayout.LayoutConfig.CENTER_IN_PARENT); 
    // 设置surfaceView布局 
    surfaceView.setLayoutConfig(layoutConfig); 
    surfaceView.setVisibility(Component.VISIBLE); 
    surfaceView.setFocusable(Component.FOCUS_ENABLE); 
    surfaceView.setTouchFocusable(true); 
    surfaceView.requestFocus(); 
    // 设置surfaceView是否在最上方 
    surfaceView.pinToZTop(playerBuilder.isTopPlay); 
    surfaceView.getSurfaceOps().get().addCallback(surfaceCallback); 
}

在执行surfaceCreated回调时会执行HarmonyOS中Player的play方法。

private void start() { 
    if (isSurfaceViewCreated) { 
        threadPoolExecutor.execute(() -> { 
            player.setVideoSurface(surface); 
            player.prepare(); 
            if (playerBuilder.startMillisecond > 0) { 
                int microsecond = playerBuilder.startMillisecond * MICRO_MILLI_RATE; 
                player.rewindTo(microsecond); 
            } else { 
                player.play(); 
            } 
        }); 
    } 
}

编译运行该应用程序

应用启动后,视频文件将被打开并开始播放,持续播放到最后。效果如下图:

4. 创建视频控制业务逻辑

上面的章节实现了视频播放的基本功能,本小节将创建一个控制器,包含基本的媒体控制UI元素如播放、暂停、恢复、重新加载按钮以及进度条。该控制器将与HmPlayer类一起提供一个基本功能全面且可操作的视频播放器。

创建SimpleVideoPlayerController

SimplePlayerController类为自定义组件,包括控制视频的播放、暂停、恢复以及进度条等控件。此处使用HarmonyOS EventHandler来进行UI更新,请参考HarmonyOS开发者文档线程间通信

public SimplePlayerController(Context context, ImplPlayer player) { 
    super(context); 
    this.context = context; 
    implPlayer = player; 
    // 创建子线程给自己发消息来及时更新UI 
    createHandler(); 
    initView(); 
    initListener(); 
}

其中initView方法初始化播放控制的控件。

Component playerController = LayoutScatter.getInstance(context).parse( 
        ResourceTable.Layout_simple_player_controller_layout, null, false); 
addComponent(playerController); 
if (playerController.findComponentById(ResourceTable.Id_play_controller) instanceof Image) { 
    // 播放或者暂停按钮 
    playToogle = (Image) playerController.findComponentById(ResourceTable.Id_play_controller); 
} 
if (playerController.findComponentById(ResourceTable.Id_play_forward) instanceof Image) { 
    // 前进按钮 
    imageForward = (Image) playerController.findComponentById(ResourceTable.Id_play_forward); 
} 
if (playerController.findComponentById(ResourceTable.Id_play_backward) instanceof Image) { 
    // 后退按钮 
    imageBackward = (Image) playerController.findComponentById(ResourceTable.Id_play_backward); 
} 
if (playerController.findComponentById(ResourceTable.Id_progress) instanceof Slider) { 
    // 进度条 
    progressBar = (Slider) playerController.findComponentById(ResourceTable.Id_progress); 
}

initListener方法是对HmPlayer和播放控制器相互之间状态变化的监听处理。

implPlayer.addPlayerStatusCallback(statusChangeListener);

添加HmPlayer状态变化的监听,例如当视频播放完毕时,回调StatusChangeListener的statusCallback来刷新对控制器中各种组件的状态和显示值。HmPlayer中HmPlayerCallback中通过底层播放回调onPlayBackComplete来对界面视频状态进行更改。

@Override

public void onPlayBackComplete() { 
    for (StatusChangeListener callback : statusChangeCallbacks) { 
        status = PlayerStatus.COMPLETE; 
        callback.statusCallback(PlayerStatus.COMPLETE); 
    } 
    stop(); 
}

在SimplePlayerController的statusCallback中更新控制按钮状态。

if (status == PlayerStatus.STOP || status == PlayerStatus.COMPLETE) {

    controllerHandler.sendEvent(Constants.PLAYER_PROGRESS_RUNNING, EventHandler.Priority.IMMEDIATE); 
    playToogle.setPixelMap(ResourceTable.Media_ic_update); 
    progressBar.setEnabled(false); 
}

此时播放按钮更新成待刷新图标,进度条不可拖拽。

创建PlayerLoading

在视频画面缓冲没有完成时,播放界面如果提供加载进度信息,用户体验更好。创建的PlayerLoading类设置一个布局并且添加StatusChangeListener监听回调,使得该控件可以根据状态显示或隐藏。

public PlayerLoading(Context context, ImplPlayer player) {

    super(context); 
    this.player = player; 
    initView(context); 
    initListener(); 
} 
private void initListener() { 
    player.addPlayerStatusCallback(new StatusChangeListener() { 
        @Override 
        public void statusCallback(PlayerStatus status) { 
            //获取主线程更新UI 
            mContext.getUITaskDispatcher().delayDispatch( 
                    new Runnable() { 
                        @Override 
                        public void run() { 
                            if (status == PlayerStatus.PREPARING || status == PlayerStatus.BUFFERING) { 
                                show(); 
                            } else if (status == PlayerStatus.PLAY) { 
                                hide(); 
                            } else { 
                                LogUtil.info(PlayerLoading.class.getName(), "statuCallback else message"); 
                            } 
                        } 
                    }, 0); 
        } 
    }); 
}

编译运行该应用程序

经过上面的步骤,此时运行程序就可以看到一个有前进、后退、播放、暂停的界面,用户可以自主控制该视频播放,效果如下图:


编辑:hfy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • HarmonyOS
    +关注

    关注

    79

    文章

    1968

    浏览量

    30058
收藏 人收藏

    评论

    相关推荐

    HarmonyOS应用开发-视频播放

    一、介绍本篇Codelab实现的内容HarmonyOS是面向全场景多终端的分布式操作系统,使得应用程序的开发打破了智能终端互通的性能和数据壁垒,业务逻辑原子化开发,适配多端。通过一个
    发表于 09-11 17:25

    HarmonyOS应用开发-元程序交互

    1. 介绍本篇CodeLab实现的内容HarmonyOS是面向全场景多终端的分布式操作系统,使得应用程序的开发打破了智能终端互通的性能和数据壁垒,业务逻辑原子化开发,适配多端。通过一
    发表于 09-21 15:23

    应用程序开发

    应用程序开发不少开发者还针对AI Camera、手表做一些应用和前端展示,这里给到的应用程序开发资料可能有所帮助,主要内容有:鸿蒙OS应用程序开发HarmonyOS开发文档(一)
    发表于 11-24 11:58

    这次华为HarmonyOS Developer Day ,社区给我们放出了什么?

    `4月17日,HarmonyOS开发者日将在上海与广大开发者见面。本次活动设主论坛、新技术论坛、专家面对面交流会、及全天的Codelab和8大场景体验展区。这是一场技术硬核、有趣好玩的
    发表于 04-15 14:00

    【线上】华为 HarmonyOS Codelab 挑战赛,你过关来我发奖【第二期】

    礼品与勋章。 4月16日~4月21日,新一轮福利又㕛叒来啦!挑战赛Round②正式开启,无论你是技术大佬还是入门小白,完成三步,即可参与抽奖领取HarmonyOS限量精美礼品。三步完成挑战第一步 下载
    发表于 04-16 09:50

    【基于HarmonyOS开发购物应用】SetllatWood Codelab第二期记录帖

    【基于HarmonyOS开发购物应用】SetllatWood Codelab第二期记录帖图片在附件
    发表于 04-21 14:44

    HarmonyOS技术社区HDD期间Codelab活动获奖人名单公布

    HDD期间,HarmonyOS技术社区举办了2期的Codelab活动,主题分别有:第一期1、HarmonyOS JAVA通用组件(模块-Java 布局)2、基于图像模块
    发表于 04-22 10:02

    基于HarmonyOS Player实现音频的播放、管理控制和采集

    收集和系统音量控制的用法。本篇Codelab实现的内容您将构建一个应用程序实现以下内容:基于HarmonyOS
    发表于 09-16 15:07

    基于HarmonyOS Player实现视频文件的播放

    和布局的编写,再到编译构建、部署和运行全过程。您将构建一个基于HarmonyOS Player实现应用程序,该
    发表于 09-18 13:51

    VC++程序开发范例宝典MP3Player

    VC++程序开发范例宝典MP3Player
    发表于 09-06 16:42 2次下载

    HarmonyOS Codelabs软件应用视频操作指南

    HarmonyOS 是面向全场景多终端的分布式操作系统,使得应用程序的开发打破了智能终 端互通的性能和数据壁垒,业务逻辑原子化开发,适配多端。通过一个简单应用开发,体 验 HarmonyOS
    发表于 10-14 14:24 0次下载
    <b class='flag-5'>HarmonyOS</b> Codelabs软件应用视频操作指南

    HarmonyOS应用程序Ability的作用

    什么是Ability Ability意为能力,是HarmonyOS应用程序提供的抽象功能。在Android应用程序中,Activity是整个应用程序的核心,其意为活动。无论是活动还是能
    的头像 发表于 03-17 15:46 2485次阅读

    华为开发者分论坛HarmonyOS学生公开课-照着做Codelab操作步骤

    2021华为开发者分论坛HarmonyOS学生公开课-照着做Codelab操作步骤
    的头像 发表于 10-24 09:53 1686次阅读
    华为开发者分论坛<b class='flag-5'>HarmonyOS</b>学生公开课-照着做<b class='flag-5'>Codelab</b>操作步骤

    华为开发者分论坛HarmonyOS学生公开课-基于开发样例Codelab进行改装

    2021华为开发者分论坛HarmonyOS学生公开课-基于开发样例Codelab进行改装 推荐链接:http://t.elecfans.com/live/1713.html 责任编辑:pj
    的头像 发表于 10-24 09:56 1344次阅读
    华为开发者分论坛<b class='flag-5'>HarmonyOS</b>学生公开课-基于开发样例<b class='flag-5'>Codelab</b>进行改装

    泰凌微电子| OpenThread组Telink Codelab正式上线

    。而通过Telink Codelab,开发人员可以更轻松地集成OpenThread到其应用程序中,从而实现与泰
    的头像 发表于 08-17 08:40 801次阅读
    泰凌微电子| OpenThread组Telink <b class='flag-5'>Codelab</b>正式上线