通过js方式开发视频播放,分布式设备迁移,评论,通过Java和js交互,获取设备信息,选择设备信息做分布式迁移。
下面通过几点说明:1,视频播放 2,仿抖音视频切换 3,评论功能添加 4,js和Java交互获取设备信息 ,5,分布式迁移
<video id='playerId{{ $idx }}' src='{{ $item.path }}' muted='false' autoplay='true'
controls="false" onprepared='preparedCallback' onstart='startCallback' onpause='pauseCallback'
onfinish='finishCallback' onerror='errorCallback' onseeking='seekingCallback'
onseeked='seekedCallback'
ontimeupdate='timeupdateCallback' style="object-fit : contain; width : 100%;"
onlongpress='change_fullscreenchange' onclick="change_start_pause" loop='true'
starttime="0"
>
</video>
js 代码中视频资源
list: [{
path: "/common/video/video1.mp4"
}
, {
path: "/common/video/video2.mp4"
}
, {
path: "/common/video/video3.mp4"
}
, {
path: "/common/video/video4.mp4"
}
, {
path: "/common/video/video5.mp4"
}
, {
path: "/common/video/video6.mp4"
}],
<swiper class="swiper-content" id="swiper" index="{{ player_index }}"
indicator="false" loop="true" digital="false" vertical="true" onchange="changeVideo">
<stack class="stack-parent" for="list">
<div class="videosource">
<video id='playerId{{ $idx }}' src='{{ $item.path }}' muted='false' autoplay='true'
controls="false" onprepared='preparedCallback' onstart='startCallback' onpause='pauseCallback'
onfinish='finishCallback' onerror='errorCallback' onseeking='seekingCallback'
onseeked='seekedCallback'
ontimeupdate='timeupdateCallback' style="object-fit : contain; width : 100%;"
onlongpress='change_fullscreenchange' onclick="change_start_pause" loop='true'
starttime="0"
>
</video>
</div>
</stack>
</swiper>
index="{{ player_index }}" 设置当前的切换项 onchange="changeVideo" 切换监听 src='{{ $item.path }}' 设置视频资源路径
<div class="pinglun" style="visibility : {{ ifhidden }};">
<div style="height : 32%; background-color : transparent;" onclick="hideenbg">
<text></text>
</div>
<!--列表展示-->
<list class="todo-wrapper" divider="true" style="divider-color : darkgrey;">
<list-item for="{{ todolist }}" class="todo-item">
<div class="photo">
<image class="image-set" src="/common/images/science6.png"></image>
<text class="todo-title" style="font-size : 14fp; margin-left : 10px;">{{ $item.name }}
</text>
</div>
<text class="todo-title" style="font-size : 14fp; margin-top : 5px;">{{ $item.detail }}</text>
</list-item>
</list>
<!--输入框信息发送-->
<div class="butt">
<input id="input" class="input" type="text" value="{{ content }}" maxlength="20" enterkeytype="send"
placeholder="{{ placecontent }}" onchange="change"
onenterkeyclick="enterkeyClick">
</input>
<button class="last" onclick="sendmessage">发送</button>
</div>
</div>
评论功能有两部分 评论列表和评论发送输入框。 onchange="change" 监听输入框信息变化 循环遍历数据 显示item
功能实现逻辑:
change(e) { // 监听输入框 信息变化 获取信息
this.message = e.value;
console.log("message===" + this.message)
},
sendmessage() { // 提交信息后组织数据 刷新界面
this.todolist.push({
name: '王者',
detail: this.message,
})
this.content = "";
this.message = "";
},
js端实现:
initAction(code) {
var actionData = {};
actionData.firstNum = 1024;
actionData.secondNum = 2048;
var action = {};
action.bundleName = "com.corecode.video.videoplayer";
action.abilityName = "com.corecode.video.videoplayer.DeviceInternalAbility";
action.messageCode = code;
action.data = actionData;
action.abilityType = 1;
action.syncOption = 1;
return action;
},
getLevel: async function () {
try {
var action = this.initAction(1001);
var result = await FeatureAbility.callAbility(action);
console.info(" result = " + result);
this.deviceId = JSON.parse(JSON.parse(result).result);
console.log("deviceId==" + this.deviceId)
this.devicelist = "visible";
} catch (pluginError) {
console.error("getBatteryLevel : Plugin Error = " + pluginError);
}
}
通过相应 函数 getLevel 来组织 initAction中的数据 var action = {}; 其中如下几项必不可少 : action.bundleName = "com.corecode.video.videoplayer";// 报名 action.abilityName = "com.corecode.video.videoplayer.DeviceInternalAbility";// 报名+类名 action.messageCode = code;// 消息编码 action.data = actionData;// 传递数据 action.abilityType = 1;// ability类型 action.syncOption = 1;//同步还是异步类型
重点: Ability类型,对应PA端不同的实现方式: 0:Ability 1:Internal Ability
syncOption PA侧请求消息处理同步/异步选项 0:同步方式,默认方式。 1:异步方式。
Java端实现: Java 端需要创建一个 ability 服务 继承 AceInternalAbility 具体是使用哪种类型 看上面的解释。 创建后需要注册,比如我创建的是 InternalAbility 这样注册: DeviceInternalAbility.register(this);
package com.corecode.video.videoplayer;
public class DeviceInternalAbility extends AceInternalAbility {
private static final HiLogLabel TAG = new HiLogLabel(0, 0, "DeviceInternalAbility");
private static final int CONNECT_ABILITY = 2000;
private static final int DISCONNECT_ABILITY = 2001;
private static final int SEND_MSG = 1001;
private static final int SUCCESS_CODE = 0;
private static final int FAIL_CODE = -1;
private static DeviceInternalAbility INSTANCE;
private String selectDeviceId;
/**
* default constructor
*
* @param context ability context
*/
public DeviceInternalAbility(AbilityContext context) {
super("com.corecode.video.videoplayer", "com.corecode.video.videoplayer.DeviceInternalAbility");
}
public DeviceInternalAbility(String bundleName, String abilityName) {
super(bundleName, abilityName);
}
public DeviceInternalAbility(String abilityName) {
super(abilityName);
}
/**
* setInternalAbilityHandler for DistributeInternalAbility instance
*
* @param context ability context
*/
static void register(AbilityContext context) {
INSTANCE = new DeviceInternalAbility(context);
INSTANCE.setInternalAbilityHandler((code, data, reply, option) ->
INSTANCE.onRemoteRequest(code, data, reply, option));
}
/**
* destroy DistributeInternalAbility instance
*/
private static void unregister() {
INSTANCE.destroy();
}
/**
* default destructor
*/
private void destroy() {
}
/**
* hand click request from javascript
*
* @param code ACTION_CODE
* @param data data sent from javascript
* @param reply reply for javascript
* @param option currently excessive
* @return whether javascript click event is correctly responded
*/
private boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
Map<String, Object> replyResult = new HashMap<>();
switch (code) {
// send message to remote device, message contains controller command from FA
case SEND_MSG: {
ZSONObject dataParsed = ZSONObject.stringToZSON(data.readString());
int message = dataParsed.getIntValue("message");
// // SYNC
// if (option.getFlags() == MessageOption.TF_SYNC) {
// reply.writeString(ZSONObject.toZSONString(result));
// }
// ASYNC
// 返回结果当前仅支持String,对于复杂结构可以序列化为ZSON字符串上报
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", MainAbility.getList());
MessageParcel responseData = MessageParcel.obtain();
responseData.writeString(ZSONObject.toZSONString(result));
IRemoteObject remoteReply = reply.readRemoteObject();
try {
remoteReply.sendRequest(0, responseData, MessageParcel.obtain(), new MessageOption());
} catch (RemoteException exception) {
return false;
} finally {
responseData.reclaim();
}
break;
}
// to invoke remote device's newsShare ability and send news url we transfer
case CONNECT_ABILITY: {
ZSONObject dataParsed = ZSONObject.stringToZSON(data.readString());
selectDeviceId = dataParsed.getString("deviceId");
break;
}
// when controller FA went to destroy lifeCycle, disconnect with remote newsShare ability
case DISCONNECT_ABILITY: {
unregister();
break;
}
default:
HiLog.error(TAG, "messageCode not handle properly in phone distributeInternalAbility");
}
return true;
}
private void assembleReplyResult(int code, Map<String, Object> replyResult, Object content, MessageParcel reply) {
replyResult.put("code", code);
replyResult.put("content", content);
reply.writeString(ZSONObject.toZSONString(replyResult));
}
}
js调用后会进入 Java的 onRemoteRequest 函数进行数据解析和组织,然后通过接口: remoteReply.sendRequest(0, responseData, MessageParcel.obtain(), new MessageOption()); 将需要的结果回传给 js做界面展示和操作。
获取设备信息: List deviceInfos = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
onSaveData(saveData) { // 数据保存到savedData中进行迁移。
var data = {
list: this.list,
player_index: this.player_index,
};
Object.assign(saveData, data)
},
onRestoreData(restoreData) { // 收到迁移数据,恢复。
console.info('==== onRestoreData ' + JSON.stringify(restoreData))
this.list = restoreData.list
this.player_index = restoreData.player_index
this.$element('swiper').swipeTo({
index: this.player_index
});
},
onCompleteContinuation(code) { //迁移完成
console.log("onCompleteContinuation===" + code)
},
onStartContinuation() {//迁移开始
return true;
},
迁移: 上面的四个有关函数 设置好后 执行 下面的接口就能实现 分布式迁移了。 continueVideoAbility: async function () { let conti = await FeatureAbility.continueAbility(); }
"reqPermissions": [
{
"reason": "",
"usedScene": {
"ability": [
"MainAbility"
],
"when": "inuse"
},
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
},
{
"name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"
},
{
"name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
},
{
"name": "ohos.permission.GRT_BUNDLE_INFO"
},
{
"name": "ohos.permission.INTERNET"
}
]
Copyright [2021] [chenjianpeng of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。