diff --git "a/HarmonyOS\345\272\224\347\224\250\345\274\200\345\217\221-\350\247\206\351\242\221\346\222\255\346\224\276.md" "b/HarmonyOS\345\272\224\347\224\250\345\274\200\345\217\221-\350\247\206\351\242\221\346\222\255\346\224\276.md" new file mode 100644 index 0000000000000000000000000000000000000000..15a7ef31bdcd767dd7408f0f2a5a5eb748e1030c --- /dev/null +++ "b/HarmonyOS\345\272\224\347\224\250\345\274\200\345\217\221-\350\247\206\351\242\221\346\222\255\346\224\276.md" @@ -0,0 +1,271 @@ +# 一、介绍 +**本篇 Codelab 将实现的内容** +HarmonyOS 是面向全场景多终端的分布式操作系统,使得应用程序的开发打破了智能终端互通的性能和数据壁垒,业务逻辑原子化开发,适配多端。通过一个简单应用开发,体验 HarmonyOS 的视频播放能力 + +**您将建立什么** +在这个 Codelab 中,你将创建 Demo Project,并将 Demo 编译成 Hap,此示例应用程序展示了如何播放视频。 + +**您将会学到什么** +1. 如何创建一个 HarmonyOS Demo Project +2. 如何构建一个 Hap 并且将其部署到智慧屏真机 +3. 通过此示例应用体验如何播放本地或者在线视频 + + +# 二、您需要什么 +## 1. 硬件要求 +操作系统:Windows10 64 位 +内存:8G 及以上。 +硬盘:100G 及以上。 +分辨率:1280*800 及以上 + + +## 2. 软件要求 + +需手动下载安装,详细步骤请参考《DevEco Studio 使用指南》2.1.2 +JDK:DevEco Studio 自动安装。 +Node.js:请手动下载安装,详细步骤请参考《DevEco Studio 使用指南》2.1.3 下载和安装 Node.js。 +HarmonyOS SDK:待 DevEco Studio 安装完成后,利用 DevEco Studio 来加载 HarmonyOS SDK。详细步骤请参考《DevEco Studio 使用指南》2.1.6 加载 HarmonyOS SDK。 +Maven 库依赖包:如需手动拷贝和配置,详细步骤请参考《DevEco Studio 使用指南》2.3 离线方式配置 Maven 库。 + + +## 3. 需要的知识点 +Java 基础开发能力。 + +# 三、能力接入准备 + +实现 HarmonyOS 应用开发,需要完成以下准备工作: +1. 环境准备。 +2. 环境搭建。 +3. 创建项目 +4. 申请调试证书 +5. 应用开发 + +具体操作,请按照《DevEco Studio 使用指南》中详细说明来完成。 +**提示:需要通过注册成开发者才能完成集成准备中的操作。** + +# 四、代码片段 +## 1. 布局: +创建播放视频的 Ability + +```go +public class VedioPlayAbilitySlice extends AbilitySlice implements SurfaceOps.Callback + +``` +布局截图: +![在这里插入图片描述](https://img-blog.csdnimg.cn/20200907162513148.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80ODMwNDU3Mw==,size_16,color_FFFFFF,t_70#pic_center) + +布局代码: + +```go +//设置页面背景透明 +WindowManager windowManager = WindowManager.getInstance(); +Window window = windowManager.getTopWindow().get(); +window.setTransparent(true); + +//页面父布局 +DependentLayout myLayout = new DependentLayout(this); +DependentLayout.LayoutConfig params = new DependentLayout.LayoutConfig(MATCH_PARENT, MATCH_PARENT); +myLayout.setLayoutConfig(params); +//显示视频的自定义 videoView +DependentLayout.LayoutConfig lpVideo = new DependentLayout.LayoutConfig(MATCH_PARENT, MATCH_PARENT); +videoView = new VideoView(this, this); +videoView.setHandler(handler); +myLayout.addComponent(videoView, lpVideo); + +DependentLayout rlParent = new DependentLayout(this); +DependentLayout.LayoutConfig lpParent = new DependentLayout.LayoutConfig(MATCH_PARENT, WRAP_CONTENT); +lpParent.addRule(DependentLayout.ALIGN_PARENT_BOTTOM); +lpParent.leftMargin = ConvertUtils.dp2Px(40); +lpParent.rightMargin = ConvertUtils.dp2Px(40); +lpParent.bottomMargin = ConvertUtils.dp2Px(40); +myLayout.addComponent(rlParent, lpParent); +//显示播放暂停按钮 +playBtn = new Image(this); +DependentLayout.LayoutConfig lpPlayBtn = new DependentLayout.LayoutConfig(ConvertUtils.dp2Px(40), ConvertUtils.dp2Px(40)); +lpPlayBtn.addRule(DependentLayout.ALIGN_PARENT_RIGHT); +playBtn.setLayoutConfig(lpPlayBtn); +playBtn.setId(1112); +playBtn.setPixelMap(ResourceTable.Media_pause); +playBtn.setScaleType(Image.ScaleType.SCALE_TO_FULL); +playBtn.invalidate(); +playBtn.setClickedListener(new Component.ClickedListener() { +@Override +public void onClick(Component component) { + if (videoView.getPlayState() == VideoView.STATE_PLAYING) { + videoView.pause(); + playBtn.setPixelMap(ResourceTable.Media_play); + } else { + videoView.start(); + playBtn.setPixelMap(ResourceTable.Media_pause); + } +} +}); +rlParent.addComponent(playBtn); +//显示当前视频播放时间 +timePlay = new Text(this); +DependentLayout.LayoutConfig lpTimePlay = new DependentLayout.LayoutConfig(WRAP_CONTENT, WRAP_CONTENT); +lpTimePlay.addRule(DependentLayout.CENTER_VERTICAL); +timePlay.setLayoutConfig(lpTimePlay); +timePlay.setId(1111); +timePlay.setText("00:00/00:00"); +timePlay.setTextSize(40); +timePlay.setTextColor(Color.WHITE); +rlParent.addComponent(timePlay); +// 显示播放进度条 +roundProgressBar = new ProgressBar(this); +roundProgressBar.setProgressWidth(ConvertUtils.dp2Px(5)); +roundProgressBar.setProgressColor(Color.RED); +roundProgressBar.setMax(100); +roundProgressBar.setProgress(0); +DependentLayout.LayoutConfig lpProgressBar = new DependentLayout.LayoutConfig(MATCH_PARENT, ConvertUtils.dp2Px(40)); +lpProgressBar.addRule(DependentLayout.RIGHT_OF, timePlay.getId()); +lpProgressBar.leftMargin = ConvertUtils.dp2Px(20); +lpProgressBar.rightMargin = ConvertUtils.dp2Px(60); +rlParent.addComponent(roundProgressBar, lpProgressBar); + +``` +## 2. 自定义 VideoView +继承父类 SurfaceProvider: + +```go +public class VideoView extends SurfaceProvider implements Player.IPlayerCallback +``` + +初始化: + +```go +public VideoView(Context context, SurfaceOps.Callback callback) { +super(context); +player = new Player(getContext()); +player.setPlayerCallback(this); +Optional surfaceHolderOptional = getSurfaceOps(); +SurfaceOps surfaceHolder = surfaceHolderOptional.get(); +surfaceHolder.addCallback(callback); +setZOrderOnTop(false); +state = STATE_INIT; +} + +``` +播放视频 +如果播放的是在线视频,需要申请网络权限: + +```go +"reqPermissions": [ + { + "name": "harmonyos.permission.INTERNET" + } +] + + +public void playAssets(String fileName, boolean isLooping, SurfaceOps holder) { + try { +//播放本地视频: //player.setSource(getContext().getResourceManager().getRawFileEntry(fileName).openRawFileDescriptor()); +//播放在线视频: + player.setSource(new Source("https://media.w3.org/2010/05/sintel/trailer.mp4")); + player.setVideoSurface(holder.getSurface()); + player.enableSingleLooping(isLooping); + player.enableScreenOn(true); + player.prepare(); + initPlayViewSize(); + player.play(); + if (state != STATE_INIT) { + player.rewindTo(currentTime * 1000); + } + state = STATE_PLAYING; + handler.sendEvent(InnerEvent.get(MESSAGE_UPDATE_PLAY_TIME)); + } catch (Exception e) { + e.printStackTrace(); + Log.hiLog(e.toString()); + } +} + +private void initPlayViewSize() { + int videoWidth = player.getVideoWidth(); + int videoHeight = player.getVideoHeight(); + Log.hiLog("videoWidth:" + videoWidth + ", videoHeight:" + videoHeight); + if (videoWidth < videoHeight) { + double scale = screenHeight * 1.f / videoHeight; + double currHeight = videoHeight * scale; + double currWidth = videoWidth * scale; + setHeight(((int) currHeight)); + setWidth(((int) currWidth)); + } else { + double scale = screenWidth * 1.f / videoWidth; + double currHeight = videoHeight * scale; + double currWidth = videoWidth * scale; + setHeight(((int) currHeight)); + setWidth(((int) currWidth)); + } +} + +``` +暂停: + +```go +public void pause() { +if (state == STATE_PLAYING) { + player.pause(); + state = STATE_PAUSE; +} +} + +``` +在 AbilitySlice 启动自动播放: + +```go +@Override +public void surfaceCreated(SurfaceOps surfaceOps) { +Log.hiLog("surfaceCreated"); +videoView.playAssets("resources/rawfile/VID_20200613_204240.mp4", true, surfaceOps); +} + +@Override +public void surfaceDestroyed(SurfaceOps surfaceOps) { +Log.hiLog("surfaceDestroyed"); +videoView.stop(); +} + +``` + +## 3. 响应遥控器点击 +```go +@Override +public boolean onKeyUp(int keyCode, KeyEvent keyEvent) { + switch (keyCode) { + case KeyEvent.KEY_DPAD_CENTER: + case KeyEvent.KEY_ENTER: + playBtn.performClick(); + return true; + default: + break; + } + return false; +} + +``` + +## 4. 编译运行该应用 +通过 hdc 连接大屏设备 +先查看智慧屏 IP: + +```go +大屏设置->"网络与连接"->"网络"->"有线网络" + +``` +在 cmd 或者 IDE 的 Terminal 输入命令: + +```go +hdc tconn 192.168.3.9:5555 + +``` +运行 hap +![](https://img-blog.csdnimg.cn/20200907163042484.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80ODMwNDU3Mw==,size_16,color_FFFFFF,t_70#pic_center) +# 五、恭喜你 +干得好,你已经成功完成了 HarmonyOS 应用开发 E2E 体验,学到了: + +1. 如何创建一个 HarmonyOS Demo Project +2. 如何构建一个 Hap 并且将其部署到真机 +3. 在 HarmonyOS 上如何使用 HarmonyOS 的视频播放的能力 + + +[【如果您想学习 HarmonyOS 应用开发基础教程 请猛戳】](https://codechina.csdn.net/huawei/harmonyos/HarmonyOS-Guide) \ No newline at end of file