HarmonyOS 分布式之仿抖音应用

开发 分布式 OpenHarmony
使用Java UI开发分布式仿抖音应用,上下滑动切换视频,评论功能,设备迁移功能:记录播放的视频页和进度、评论数据。

[[430075]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

项目介绍

使用Java UI开发分布式仿抖音应用,上下滑动切换视频,评论功能,设备迁移功能:记录播放的视频页和进度、评论数据。

效果演示

1.上下滑动切换视频、点击迁移图标,弹框选择在线的设备,完成视频数据的迁移。

2.点击评论图标查看评论,编辑评论内容并发送。点击迁移图标,弹框选择在线的设备,完成评论数据的迁移。

项目结构

主要代码

1、上下滑动页面

页面切换用到系统组件PageSlider,默认左右切换,设置为上下方向:setOrientation(Component.VERTICAL);

import ohos.aafwk.ability.AbilitySlice; 
import ohos.aafwk.content.Intent; 
import ohos.agp.components.*; 
 
import java.util.ArrayList; 
import java.util.List; 
 
public class MainAbilitySlice extends AbilitySlice { 
    @Override 
    public void onStart(Intent intent) { 
        super.onStart(intent); 
        super.setUIContent(ResourceTable.Layout_ability_main); 
        // 查找滑动页面组件 
        PageSlider pageSlider = (PageSlider) findComponentById(ResourceTable.Id_pageSlider); 
        // 设置滑动方向为上下滑动 
        pageSlider.setOrientation(Component.VERTICAL); 
        // 集合测试数据 
        List<String> listData=new ArrayList<>(); 
        listData.add("第一页"); 
        listData.add("第二页"); 
        listData.add("第三页"); 
         
        // 设置页面适配器 
        pageSlider.setProvider(new PageSliderProvider() { 
            /** 
             * 获取当前适配器中可用视图的数量 
             */ 
            @Override 
            public int getCount() { 
                return listData.size(); 
            } 
            /** 
             * 创建页面 
             */ 
            @Override 
            public Object createPageInContainer(ComponentContainer container, int position) { 
                // 查找布局 
                Component component = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_item_page, nullfalse); 
                Text textContent = (Text) component.findComponentById(ResourceTable.Id_text_item_page_content); 
                // 设置数据 
                textContent.setText(listData.get(position)); 
                // 添加到容器中 
                container.addComponent(component); 
                return component; 
            } 
            /** 
             * 销毁页面 
             */ 
            @Override 
            public void destroyPageFromContainer(ComponentContainer container, int position, Object object) { 
                // 从容器中移除 
                container.removeComponent((Component) object); 
            } 
            /** 
             * 检查页面是否与对象匹配 
             */ 
            @Override 
            public boolean isPageMatchToObject(Component page, Object object) { 
                return true
            } 
        }); 
 
        // 添加页面改变监听器 
        pageSlider.addPageChangedListener(new PageSlider.PageChangedListener() { 
            /** 
             * 页面滑动时调用 
             */ 
            @Override 
            public void onPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {} 
            /** 
             * 当页面滑动状态改变时调用 
             */ 
            @Override 
            public void onPageSlideStateChanged(int state) {} 
            /** 
             * 选择新页面时回调 
             */ 
            @Override 
            public void onPageChosen(int itemPos) { 
                // 在此方法下,切换页面获取当前页面的视频源,进行播放 
                String data = listData.get(itemPos); 
            } 
        }); 
    } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.

2、播放视频

视频播放使用Player,视频画面窗口显示使用SurfaceProvider。

import ohos.aafwk.ability.AbilitySlice; 
import ohos.aafwk.content.Intent; 
import ohos.agp.components.surfaceprovider.SurfaceProvider; 
import ohos.agp.graphics.SurfaceOps; 
import ohos.global.resource.RawFileDescriptor; 
import ohos.media.common.Source; 
import ohos.media.player.Player; 
 
import java.io.IOException; 
 
public class MainAbilitySlice extends AbilitySlice { 
    // 视频路径 
    private final String videoPath = "resources/rawfile/HarmonyOS.mp4"
    // 播放器 
    private Player mPlayer; 
 
    @Override 
    public void onStart(Intent intent) { 
        super.onStart(intent); 
        super.setUIContent(ResourceTable.Layout_ability_main); 
        // 初始化播放器 
        mPlayer = new Player(getContext()); 
        // 查找视频窗口组件 
        SurfaceProvider surfaceProvider = (SurfaceProvider) findComponentById(ResourceTable.Id_surfaceProvider); 
        // 设置视频窗口在顶层 
        surfaceProvider.pinToZTop(true); 
        // 设置视频窗口操作监听 
        if (surfaceProvider.getSurfaceOps().isPresent()) { 
            surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceOps.Callback() { 
                /** 
                 * 创建视频窗口 
                 */ 
                @Override 
                public void surfaceCreated(SurfaceOps holder) { 
                    try { 
                        RawFileDescriptor fileDescriptor = getResourceManager().getRawFileEntry(videoPath).openRawFileDescriptor(); 
                        Source source = new Source(fileDescriptor.getFileDescriptor(), 
                                fileDescriptor.getStartPosition(), 
                                fileDescriptor.getFileSize() 
                        ); 
                        // 设置媒体文件 
                        mPlayer.setSource(source); 
                        // 设置播放窗口 
                        mPlayer.setVideoSurface(holder.getSurface()); 
                        // 循环播放 
                        mPlayer.enableSingleLooping(true); 
                        // 准备播放环境并缓冲媒体数据 
                        mPlayer.prepare(); 
                        // 开始播放 
                        mPlayer.play(); 
                    } catch (IOException e) { 
                        e.printStackTrace(); 
                    } 
 
                } 
                /** 
                 * 视频窗口改变 
                 */ 
                @Override 
                public void surfaceChanged(SurfaceOps holder, int format, int width, int height) {} 
                /** 
                 * 视频窗口销毁 
                 */ 
                @Override 
                public void surfaceDestroyed(SurfaceOps holder) {} 
            }); 
        } 
    } 
 
    @Override 
    protected void onStop() { 
        super.onStop(); 
        // 页面销毁,释放播放器 
        if (mPlayer != null) { 
            mPlayer.stop(); 
            mPlayer.release(); 
        } 
    } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.

3、跨设备迁移示例

跨设备迁移使用IAbilityContinuation接口。

1、在entry下的config.json配置权限

"reqPermissions": [ 
      { 
        "name""ohos.permission.DISTRIBUTED_DATASYNC" 
      }, 
      { 
        "name""ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" 
      }, 
      { 
        "name""ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" 
      } 
    ] 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

2、实现IAbilityContinuation接口,说明:一个应用可能包含多个Page,仅需要在支持迁移的Page中通过以下方法实现IAbilityContinuation接口。同时,此Page所包含的所有AbilitySlice也需要实现此接口。

import ohos.aafwk.ability.AbilitySlice; 
import ohos.aafwk.ability.IAbilityContinuation; 
import ohos.aafwk.content.Intent; 
import ohos.aafwk.content.IntentParams; 
import ohos.agp.components.Button; 
import ohos.agp.components.Text; 
import ohos.bundle.IBundleManager; 
import ohos.distributedschedule.interwork.DeviceInfo; 
import ohos.distributedschedule.interwork.DeviceManager; 
 
import java.util.List; 
 
public class MainAbilitySlice extends AbilitySlice implements IAbilityContinuation { 
    private String data = ""
    String PERMISSION = "ohos.permission.DISTRIBUTED_DATASYNC"
 
    @Override 
    public void onStart(Intent intent) { 
        super.onStart(intent); 
        super.setUIContent(ResourceTable.Layout_ability_main); 
        // 申请权限 
        if (verifySelfPermission(PERMISSION) != IBundleManager.PERMISSION_GRANTED) { 
            requestPermissionsFromUser(new String[]{PERMISSION}, 0); 
        } 
        Button button = (Button)findComponentById(ResourceTable.Id_button); 
        Text text = (Text)findComponentById(ResourceTable.Id_text); 
         
        // 点击迁移 
        button.setClickedListener(component -> { 
            // 查询分布式网络中所有在线设备(不包括本地设备)的信息。 
            List<DeviceInfo> deviceList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE); 
            if (deviceList.size()>0) { 
                // 启动迁移,指定的设备ID 
                continueAbility(deviceList.get(0).getDeviceId()); 
            } 
        }); 
        // 显示迁移的数据 
        text.setText("迁移的数据:"+data); 
    } 
    /** 
     * 启动迁移时首次调用此方法 
     * @return 是否进行迁移 
     */ 
    @Override 
    public boolean onStartContinuation() { 
        return true
    } 
    /** 
     * 迁移时存入数据 
     */ 
    @Override 
    public boolean onSaveData(IntentParams intentParams) { 
        intentParams.setParam("data","测试数据"); 
        return true
    } 
    /** 
     * 获取迁移存入的数据,在生命周期的onStart之前执行 
     */ 
    @Override 
    public boolean onRestoreData(IntentParams intentParams) { 
        data= (String) intentParams.getParam("data"); 
        return true
    } 
    /** 
     * 迁移完成 
     */ 
    @Override 
    public void onCompleteContinuation(int i) {} 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.

根据上面的核心代码示例,了解实现原理,接下来便可以结合实际需求完善功能了。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-11-16 09:38:10

鸿蒙HarmonyOS应用

2018-07-17 08:14:22

分布式分布式锁方位

2021-12-13 11:07:10

鸿蒙HarmonyOS应用

2021-01-21 09:45:36

鸿蒙HarmonyOS分布式

2021-05-28 09:52:00

鸿蒙HarmonyOS应用

2022-03-06 21:43:05

Citus架构PostgreSQL

2020-11-06 12:12:35

HarmonyOS

2019-09-26 15:43:52

Hadoop集群防火墙

2019-02-13 13:41:07

MemCache分布式HashMap

2018-12-14 10:06:22

缓存分布式系统

2021-12-10 15:06:56

鸿蒙HarmonyOS应用

2021-12-02 10:11:44

鸿蒙HarmonyOS应用

2019-10-10 09:16:34

Zookeeper架构分布式

2021-07-22 10:20:21

鸿蒙HarmonyOS应用

2019-06-19 15:40:06

分布式锁RedisJava

2023-05-29 14:07:00

Zuul网关系统

2017-09-01 05:35:58

分布式计算存储

2023-01-09 11:23:03

系统

2021-07-23 08:57:32

鸿蒙HarmonyOS应用

2011-04-01 14:28:58

zabbix应用proxy
点赞
收藏

51CTO技术栈公众号