用鸿蒙的分布式助力七夕 原创 精华
丨张明亮丨
 发布于 2021-8-13 13:08
 浏览
 13收藏
2021年8月13日@亮子力
明天就是情人节了,首先祝在座的各位都能得偿所愿,其次在情人节前,为之前的B站卡片项目增加一个隐藏功能。如果升级了最新的B站服务卡片,那么当桌面上添加头像卡片时,只要点击头像,就会看到下图的效果。一个应用鸿蒙分布式能力的小功能。

视频预览地址:https://harmonyos.51cto.com/show/7762
完整项目地址:https://gitee.com/liangzili/bilibili-cards
1.添加一个播放页
比如PlayerSlice,这个页面用来实现视频的播放。

2.为头像卡片添加点击事件
当点击卡片上的头像时实现页面跳转,代码如下
src/main/js/fans/pages/index/index.hml
<div class="card_root_layout" else>
    <div class="div_left_container">
        <stack class="stack-parent" onclick="sendRouterEvent">
            <image src="{{src}}" class="image_src"></image>
            <image src="{{vip}}" class="image_vip"></image>
        </stack>
    </div>
    <text class="item_title">{{follower}}</text>
</div>
actions中设置跳转到刚才新建的播放页面。
src/main/js/fans/pages/index/index.json
  "actions": {
    "sendRouterEvent": {
      "action": "router",
      "abilityName": "com.liangzili.demos.Player",
      "params": true
    }
  }
3.在播放页判断拉起方式
从intent中提取参数params,如果播放页是服务卡片拉起的,得到true。如果是分布式拉起的得到false。
params = intent.getStringParam("params");//从intent中获取 跳转事件定义的params字段的值
if(params.equals("true")){
    Intent intent0 = new Intent();
    Operation op = new Intent.OperationBuilder()
        .withDeviceId(DistributedUtils.getDeviceId())//参数1.是否跨设备,空,不跨设备
        .withBundleName("com.liangzili.demos")//参数2.在config.json中的bundleName
        .withAbilityName("com.liangzili.demos.Player")//参数3.要跳转的ability名
        .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
        .build();
    intent0.setOperation(op);
    intent0.setParam("params","false");
    startAbility(intent0);
    videoSource = "resources/base/media/right.mp4";
}else{
    videoSource = "resources/base/media/left.mp4";
}
4.申请分布式拉起页面权限
如果params就调用分布式拉起页面,得提前为应用获取权限。
| 权限名 | 说明 | 
|---|---|
| ohos.permission.DISTRIBUTED_DATASYNC | 必选(分布式数据管理权限,允许不同设备间的数据交换) | 
| ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE | 必选(允许获取分布式组网内设备的状态变化) | 
| ohos.permission.GET_DISTRIBUTED_DEVICE_INFO | 必选(允许获取分布式组网内的设备列表和设备信息) | 
| ohos.permission.GET_BUNDLE_INFO | 必选(查询其他应用信息的权限) | 
在app首次启动时提醒用户获取分布式权限。
src/main/java/com/liangzili/demos/MainAbility.java
requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"},0);
5.获取远端设备ID
要拉起远端设备上的页面,得先获取设备的ID。
public class DistributedUtils {
    public static String getDeviceId(){
        //获取在线设备列表,getDeviceList拿到的设备不包含本机。
        List<DeviceInfo> deviceList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
        if(deviceList.isEmpty()){
            return null;
        }
        int deviceNum = deviceList.size();
        List<String> deviceIds = new ArrayList<>(deviceNum);    //提取设备Id
        List<String> deviceNames = new ArrayList<>(deviceNum);  //提取设备名
        deviceList.forEach((device)->{
            deviceIds.add(device.getDeviceId());
            deviceNames.add(device.getDeviceName());
        });
        String devcieIdStr = deviceIds.get(0);
        return devcieIdStr;
    }
}
6.获取资源地址播放视频
视频播放参考的是软通动力HarmonyOS学院的拜年视频代码,官方的demo和CadeLabs还没跑通,时间有点来不及了,原谅我大段复制。
//设置沉浸式状态栏
getWindow().addFlags(WindowManager.LayoutConfig.MARK_TRANSLUCENT_STATUS);
initPlayer();
//需要重写两个回调:VideoSurfaceCallback 、VideoPlayerCallback
private void initPlayer() {
    sfProvider=(SurfaceProvider) findComponentById(ResourceTable.Id_surfaceProvider);
    //        image=(Image) findComponentById(ResourceTable.Id_img);
    sfProvider.getSurfaceOps().get().addCallback(new VideoSurfaceCallback());
    // sfProvider.pinToZTop(boolean)--如果设置为true, 视频控件会在最上层展示,但是设置为false时,虽然不在最上层展示,却出现黑屏,
    // 需加上一行代码:WindowManager.getInstance().getTopWindow().get().setTransparent(true);
    sfProvider.pinToZTop(true);
    //WindowManager.getInstance().getTopWindow().get().setTransparent(true);
    player=new Player(getContext());
    //sfProvider添加监听事件
    sfProvider.setClickedListener(new Component.ClickedListener() {
        @Override
        public void onClick(Component component) {
            if(player.isNowPlaying()){
                //如果正在播放,就暂停
                player.pause();
                //播放按钮可见
                image.setVisibility(Component.VISIBLE);
            }else {
                //如果暂停,点击继续播放
                player.play();
                //播放按钮隐藏
                image.setVisibility(Component.HIDE);
            }
        }
    });
}
private class VideoSurfaceCallback implements SurfaceOps.Callback {
    @Override
    public void surfaceCreated(SurfaceOps surfaceOps) {
        HiLog.info(logLabel,"surfaceCreated() called.");
        if (sfProvider.getSurfaceOps().isPresent()) {
            Surface surface = sfProvider.getSurfaceOps().get().getSurface();
            playLocalFile(surface);
        }
    }
    @Override
    public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {
        HiLog.info(logLabel,"surfaceChanged() called.");
    }
    @Override
    public void surfaceDestroyed(SurfaceOps surfaceOps) {
        HiLog.info(logLabel,"surfaceDestroyed() called.");
    }
}
private void playLocalFile(Surface surface) {
    try {
        RawFileDescriptor filDescriptor = getResourceManager().getRawFileEntry(videoSource).openRawFileDescriptor();
        Source source = new Source(filDescriptor.getFileDescriptor(),filDescriptor.getStartPosition(),filDescriptor.getFileSize());
        player.setSource(source);
        player.setVideoSurface(surface);
        player.setPlayerCallback(new VideoPlayerCallback());
        player.prepare();
        sfProvider.setTop(0);
        player.play();
    } catch (Exception e) {
        HiLog.info(logLabel,"playUrl Exception:" + e.getMessage());
    }
}
参考文章:
【软通动力】SurfaceProvider实现视频播放Demo-热乎乎的拜年视频-鸿蒙HarmonyOS技术社区-鸿蒙官方合作伙伴-51CTO.COM
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
    已于2021-8-13 15:27:19修改
 
        赞
        23
 
        收藏 13
      
 回复
  相关推荐
 




















这也太浪漫了~
了解更多HarmonyOS相关产品~请戳:【华为开发者联盟生态市场HarmonyOS专区https://developer.huawei.com/consumer/cn/market/prod-list?categoryIdL1=1fc1b638cf8d4e93a6542a505f916ad6】
ヾ(o◕∀◕)ノヾ码农方式
给哥打call!
为创意点赞
感谢支持啊
感谢支持啊 分布式的小应用
66666 给力
感谢支持啊
好浪漫啊,亮哥的女朋友/老婆是不是被惊呆了。