新聞中心
DistributedVideoPlayer 分布式視頻播放器(一)
作者:Buty9147 2021-10-19 14:27:07
開(kāi)發(fā)
前端
分布式 本示例是在官方Video Play Ability 模板基礎(chǔ)上做了擴(kuò)展開(kāi)發(fā),官方模板提供基本的視頻播放功能,并允許您在手機(jī)和電視之間傳輸視頻.

成都創(chuàng)新互聯(lián)公司主要從事成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)涼州,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):18980820575
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
介紹
本示例是在官方Video Play Ability 模板基礎(chǔ)上做了擴(kuò)展開(kāi)發(fā),官方模板提供基本的視頻播放功能,并允許您在手機(jī)和電視之間傳輸視頻.
應(yīng)用分為手機(jī)端(entry)和TV端(entrytv),以及一個(gè)依賴模塊(commonlib).
在示例的基礎(chǔ)之上,手機(jī)端增加了視頻播放列表功能,以及播放詳情頁(yè)和評(píng)論功能;手機(jī)端播放的視頻可以流轉(zhuǎn)到TV端,并實(shí)現(xiàn)遠(yuǎn)端遙控的功能。
內(nèi)容比較多,會(huì)分兩期給大家講解,本期文章主要講解的內(nèi)容是手機(jī)端部分:
1.實(shí)現(xiàn)一個(gè)視頻播放器 2.實(shí)現(xiàn)一個(gè)播放列表 3.實(shí)現(xiàn)一個(gè)評(píng)論功能.
[本文正在參與優(yōu)質(zhì)創(chuàng)作者激勵(lì)]
效果展示
搭建環(huán)境
安裝DevEco Studio,詳情請(qǐng)參考DevEco Studio下載。
設(shè)置DevEco Studio開(kāi)發(fā)環(huán)境,DevEco Studio開(kāi)發(fā)環(huán)境需要依賴于網(wǎng)絡(luò)環(huán)境,需要連接上網(wǎng)絡(luò)才能確保工具的正常使用,可以根據(jù)如下兩種情況來(lái)配置開(kāi)發(fā)環(huán)境:
如果可以直接訪問(wèn)Internet,只需進(jìn)行下載HarmonyOS SDK操作。
如果網(wǎng)絡(luò)不能直接訪問(wèn)Internet,需要通過(guò)代理服務(wù)器才可以訪問(wèn),請(qǐng)參考配置開(kāi)發(fā)環(huán)境。
下載源碼后,使用DevEco 打開(kāi)項(xiàng)目。
代碼結(jié)構(gòu)
Java代碼
- │ config.json
- │
- ├─java
- │ └─com
- │ └─buty
- │ └─distributedvideoplayer
- │ │ MainAbility.java
- │ │ MyApplication.java
- │ │
- │ ├─ability
- │ │ DevicesSelectAbility.java
- │ │ MainAbilitySlice.java #視頻播放列表頁(yè)
- │ │ SyncControlServiceAbility.java
- │ │ VideoPlayAbility.java #視頻播放Ability
- │ │ VideoPlayAbilitySlice.java #視頻播放詳情和評(píng)論頁(yè)
- │ │
- │ ├─components
- │ │ EpisodesSelectionDialog.java
- │ │ RemoteController.java
- │ │ VideoPlayerPlaybackButton.java #播放按鈕組件
- │ │ VideoPlayerSlider.java #播放時(shí)間進(jìn)度條
- │ │
- │ ├─constant
- │ │ Constants.java #常量
- │ │ ResolutionEnum.java #分辨率枚舉
- │ │ RouteRegister.java #自定義路由
- │ │
- │ ├─data
- │ │ VideoInfo.java #視頻基礎(chǔ)信息
- │ │ VideoInfoService.java #視頻信息服務(wù),用于模擬數(shù)據(jù)
- │ │ Videos.java #視頻列表
- │ │
- │ ├─model
- │ │ CommentModel.java #評(píng)論模型
- │ │ DeviceModel.java
- │ │ ResolutionModel.java #解析度模型
- │ │ VideoModel.java #視頻模型
- │ │
- │ ├─provider
- │ │ CommentItemProvider.java #評(píng)論數(shù)據(jù)提供程序
- │ │ DeviceItemProvider.java
- │ │ ResolutionItemProvider.java #解析度數(shù)據(jù)提供程序
- │ │ VideoItemProvider.java #視頻數(shù)據(jù)提供程序
- │ │
- │ └─utils
- │ AppUtil.java #工具類
- │ DateUtils.java
資源文件
- └─resources
- ├─base
- │ ├─element
- │ │ color.json
- │ │ float.json
- │ │ strarray.json
- │ │ string.json
- │ │
- │ ├─graphic
- │ │ background_ability_control_bg.xml
- │ │ background_ability_control_middle.xml
- │ │ background_ability_control_ok.xml
- │ │ background_ability_devices.xml
- │ │ background_ability_episodes.xml
- │ │ background_button_click.xml
- │ │ background_button_clicked.xml
- │ │ background_episodes_item.xml
- │ │ background_episodes_quality.xml
- │ │ background_episodes_trailer.xml
- │ │ background_slide_thumb.xml
- │ │ background_switch_checked.xml
- │ │ background_switch_empty.xml
- │ │ background_switch_thumb.xml
- │ │ background_switch_track.xml
- │ │ list_divider.xml
- │ │ shape_slider_thumb.xml
- │ │
- │ ├─layout
- │ │ ability_main.xml #播放列表布局
- │ │ comments_item.xml #單條評(píng)論布局
- │ │ dialog_playlist.xml
- │ │ dialog_resolution_list.xml
- │ │ dialog_table_layout.xml
- │ │ hm_sample_ability_video_box.xml #視頻播放組件頁(yè)
- │ │ hm_sample_ability_video_comments.xml #播放詳情布局頁(yè)
- │ │ hm_sample_view_video_box_seek_bar_style1.xml #播放進(jìn)度條布局
- │ │ hm_sample_view_video_box_seek_bar_style2.xml
- │ │ remote_ability_control.xml
- │ │ remote_ability_episodes.xml
- │ │ remote_ability_select_devices.xml
- │ │ remote_ability_sound_equipment.xml
- │ │ remote_device_item.xml
- │ │ remote_episodes_item.xml
- │ │ remote_video_quality_item.xml
- │ │
- │ ├─media
- │ │ comments.png
- │ │ great.png
- │ │ icon.png
- │ │ ic_anthology.png
- │ │
- │ └─profile
- ├─en
- │ └─element
- │ string.json
- │
- ├─rawfile
- │ videos.json #模擬數(shù)據(jù)JSON文件
- │
- └─zh
- └─element
- string.json
實(shí)現(xiàn)步驟
1.實(shí)現(xiàn)一個(gè)視頻播放器
引入對(duì)commonlib的依賴后,實(shí)現(xiàn)一個(gè)視頻播放器就很容易了.
entry的build.gradle 增加對(duì)commonlib的依賴
- dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
- testImplementation 'junit:junit:4.13'
- ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.200'
- //引用commonlib 依賴
- implementation project(path: ':commonlib')
- }
1.1.頁(yè)面布局 hm_sample_ability_video_comments.xml
添加一個(gè)VideoPlayerView組件
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:id="$+id:root_layout"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:background_element="#FFFFFFFF"
- ohos:orientation="vertical">
- ohos:id="$+id:video_view"
- ohos:height="250vp"
- ohos:width="match_parent"/>
- ...
1.2.Java代碼
獲取視頻組件對(duì)象后,只需要2步就可以了: 1.設(shè)置視頻資源路徑和描述; 2.設(shè)置播放器核心組件和自定義組件.幾行關(guān)鍵代碼 VideoPlayAbilitySlice.java
- /**
- * 初始化播放器
- */
- private void initPlayer() {
- HiLog.debug(LABEL, "initPlayer");
- //自定義視頻播放視圖組件
- player = (VideoPlayerView) findComponentById(ResourceTable.Id_video_view);
- if (player != null) {
- //獲取視頻信息服務(wù)
- videoService = new VideoInfoService(getContext());
- //獲取當(dāng)前播放視頻的路徑
- String path = videoService
- .getVideoInfoByIndex(currentPlayingIndex)
- .getResolutions()
- .get(currentPlayingResolutionIndex)
- .getUrl();
- //視頻描述
- String videoDesc = videoService.getVideoInfoByIndex(currentPlayingIndex).getVideoDesc();
- HiLog.debug(LABEL, "videoDesc = " + videoDesc + " path = " + path);
- if (path != null) {
- //設(shè)置路徑和描述
- player.setVideoPathAndTitle(path, videoDesc);
- //視頻準(zhǔn)備完畢就播放并設(shè)置播放進(jìn)度條
- player.setPlayerOnPreparedListener(
- () -> {
- player.start();
- //設(shè)置播放位置
- player.seekTo(currentPlayingPosition);
- });
- //雙擊播放或暫停
- player.setDoubleClickedListener(
- component -> {
- //是否在控制TV端
- if (remoteController != null && remoteController.isShown()) {
- return;
- }
- HiLog.debug(LABEL, "VideoPlayView double-click event");
- if (player.isPlaying()) {
- player.pause();
- } else {
- player.start();
- }
- });
- //監(jiān)聽(tīng)播放錯(cuò)誤
- player.setErrorListener(
- (errorType, errorCode) -> {
- ToastDialog toast = new ToastDialog(getContext());
- switch (errorType) {
- case HmPlayerAdapter.ERROR_LOADING_RESOURCE:
- toast.setText(
- AppUtil.getStringResource(
- getContext(), ResourceTable.String_media_file_loading_error));
- break;
- case HmPlayerAdapter.ERROR_INVALID_OPERATION:
- toast.setText(
- AppUtil.getStringResource(
- getContext(), ResourceTable.String_invalid_operation));
- break;
- default:
- toast.setText(
- AppUtil.getStringResource(
- getContext(), ResourceTable.String_undefined_error_type));
- break;
- }
- getUITaskDispatcher().asyncDispatch(toast::show);
- });
- }
- //添加核心組件,播放時(shí)間進(jìn)度滑塊
- addCoreComponent();
- //添加自定義組件
- addCustomComponent();
- HiLog.debug(LABEL, "initPlayer finish");
- }
- }
2.實(shí)現(xiàn)一個(gè)視頻播放列表功能
2.1.頁(yè)面布局 ability_main.xml
使用了DirectionalLayout布局組件,還有ScrollView和ListContainer組件
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:id="$+id:ability_main_root"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- ohos:id="$+id:ability_main_titlebar"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:background_element="#B0B0B0"
- ohos:orientation="horizontal"
- ohos:padding="10vp">
- ohos:height="match_parent"
- ohos:width="match_content"
- ohos:weight="1">
- ohos:id="$+id:tag_favorite"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:text="關(guān)注"
- ohos:text_size="$float:normal_text_size_15"
- />
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:weight="1">
- ohos:id="$+id:tag_support"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="推薦"
- ohos:text_size="$float:normal_text_size_15"
- />
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:weight="1">
- ohos:id="$+id:tag_movie"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:element_end="$id:favorite"
- ohos:text="電影"
- ohos:text_color="#1C6AE9"
- ohos:text_size="$float:normal_text_size_15"
- ohos:text_weight="600"/>
- ohos:id="$+id:device_item_divider"
- ohos:height="2vp"
- ohos:width="30vp"
- ohos:background_element="$graphic:list_divider"/>
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:weight="1">
- ohos:id="$+id:tag_live"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:text="直播"
- ohos:text_size="$float:normal_text_size_15"
- />
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:weight="1">
- ohos:id="$+id:tag_tv"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:text="電視"
- ohos:text_size="$float:normal_text_size_15"
- />
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:id="$+id:video_list_scroll" >
- ohos:id="$+id:videos_container"
- ohos:height="match_parent"
- ohos:width="match_parent">
2.2.Java代碼
申請(qǐng)用戶敏感權(quán)限授權(quán) MainAbility.java
- /**
- * Entry to the main interface of the program
- */
- public class MainAbility extends Ability {
- private static final int REQUEST_CODE = 1;
- //讀寫(xiě)媒體權(quán)限
- private final String[] permissionLists
- = new String[]{"ohos.permission.READ_MEDIA", "ohos.permission.WRITE_MEDIA"};
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_main);
- super.setMainRoute(MainAbilitySlice.class.getName());
- //申請(qǐng)授權(quán)
- verifyPermissions();
- }
- private void verifyPermissions() {
- for (String permissionList : permissionLists) {
- int result = verifySelfPermission(permissionList);
- if (result != IBundleManager.PERMISSION_GRANTED) {
- requestPermissionsFromUser(permissionLists, REQUEST_CODE);
- }
- }
- }
- ...
通過(guò)VideoInfoService讀取videos.json文件初始化視頻容器列表MainAbilitySlice.java
- public class MainAbilitySlice extends AbilitySlice {
- public static final HiLogLabel LABEL = new HiLogLabel(0, 0, "=>MainAbilitySlice");
- private VideoInfoService videoService;
- @Override
- protected void onStart(Intent intent) {
- super.onStart(intent);
- //加載視頻播放器頁(yè)面
- super.setUIContent(ResourceTable.Layout_ability_main);
- initVideoContainer();
- }
- /**
- * 模擬數(shù)據(jù)
- * 初始化視頻容器列表
- */
- private void initVideoContainer() {
- HiLog.debug(LABEL, "initVideoContainer");
- List
videos = new ArrayList<>(); - //獲取視頻信息服務(wù)
- videoService = new VideoInfoService(getContext());
- for (int i = 0; i < 7; i++) {
- VideoModel video = new VideoModel();
- video.setComments(new Random().nextInt(1000));
- video.setFavorites(new Random().nextInt(1000));
- video.setGreats(new Random().nextInt(10000));
- VideoInfo videoInfo = videoService.getVideoInfoByIndex(i);
- videoInfo.setIndex(i);
- video.setVideoInfo(videoInfo);
- videos.add(video);
- }
- ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_videos_container);
- //容器綁定數(shù)據(jù)提供程序
- VideoItemProvider provider = new VideoItemProvider(this, videos, this);
- listContainer.setItemProvider(provider);
- }
- }
視頻容器列表數(shù)據(jù)提供程序 VideoItemProvider.java
- public class VideoItemProvider extends BaseItemProvider {
- private static final HiLogLabel LABEL = new HiLogLabel(0, 0, "=>VideoItemProvider");
- private final Context context;
- private final List
list; - private AbilitySlice abilitySlice;
- //當(dāng)前播放視頻分辨率索引
- private int currentPlayingResolutionIndex = 0;
- /**
- * Initialization
- */
- public VideoItemProvider(Context context, List
list, AbilitySlice abilitySlice) { - HiLog.debug(LABEL, "VideoItemProvider");
- this.context = context;
- this.list = list;
- this.abilitySlice = abilitySlice;
- }
- public Context getContext() {
- return context;
- }
- @Override
- public int getCount() {
- return list == null ? 0 : list.size();
- }
- @Override
- public Object getItem(int position) {
- if (list != null && position >= 0 && position < list.size()) {
- return list.get(position);
- }
- return new VideoModel();
- }
標(biāo)題名稱:DistributedVideoPlayer分布式視頻播放器(一)
鏈接URL:http://m.5511xx.com/article/cdoopeh.html


咨詢
建站咨詢
