📚往期笔录记录🔖:
🔖鸿蒙(HarmonyOS)北向开发知识点记录~
🔖鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
🔖鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
🔖嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
🔖对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
🔖鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
🔖记录一场鸿蒙开发岗位面试经历~
🔖持续更新中……
场景一:视频播放预加载,边下边播
方案
- 创建一个沙箱文件,并获取沙箱文件的readFd和writeFd。
- 通过.new rcp.Request(DOWNLOAD_URL)创建网络下载请求request,配置request的TracingConfiguration,在onDataReceive回调中通过fs.writeSync传入沙箱文件的writeFd,将下载的数据流写入本地沙箱文件,将fs.writeSync返回写入字节大小作为网络下载大小downloadSize,根据downloadSize和下载大小(默认1024*1024字节,AVPlayer默认缓存为1M)配置request的transferRange属性,控制网络下载的起始字节和结束字节。
- 通过RCP的session.fetch传入request下载获取网络视频资源。
- 配置AVPlayer的datasrc属性,在datasrc的回调函数中,通过fs.readSync传入沙箱文件的readFd,将沙箱文件的数据写入内存buffer,沙箱文件大小为0时开启网络下载,当pos(表示填写的数据在资源文件中的位置)小于沙箱文件100kb时,再次开启网络下载进而实现分段下载,该回调函数在AVPlayer解析数据时触发,在边下边播的场景中,会不断触发该回调。
- 设置AVPlayer播放资源,将datasrc设置给AVPlayer。
核心代码
控制网络下载的起始字节和结束字节。
function download(length: number) {
console.info('MineRcp download from = ' + downloadSize + 'to = ' + (downloadSize + length - 1));
request.transferRange = {
from: downloadSize,
to: downloadSize + length - 1,
};
downloadStarted = true;
session.fetch(request).then(() => {
downloadStarted = false;
}).catch(() => {
downloadStarted = false;
});
}
onDataReceive回调中通过fs.writeSync传入沙箱文件的writeFd,将下载的数据流写入本地沙箱文件。
request.configuration = {
tracing: {
httpEventsHandler: {
onDataReceive: (incomingData: ArrayBuffer) => {
const writeLength = fs.writeSync(this.writeFd, GetDecodedBuffer(incomingData));
downloadSize += writeLength;
console.info('MineRcp recieve Length = ' + writeLength.toString() + " , recieve = " + downloadSize);
return incomingData.byteLength;
}
}
}
};
配置AVPlayer的datasrc属性。
let src: media.AVDataSrcDescriptor = {
fileSize: -1,
callback: (buf: ArrayBuffer, length: number, pos?: number) => {
// buffer,ArrayBuffer类型,表示被填写的内存,必选。
//
// - length,number类型,表示被填写内存的最大长度,必选。
//
// - pos,number类型,表示填写的数据在资源文件中的位置,可选,当fileSize设置为-1时,该参数禁止被使用。
// - 返回值,number类型,返回要填充数据的长度。
let num = 0;
if (buf === undefined || length === undefined) {
return -1;
}
num = fs.readSync(this.readFd, buf);
console.info('MineRcp cacheBuffer after checkBuffer Length = ' + num.toString() + ', pos: ' + pos +
', downloadSize: ' +
downloadSize);
if (num > 0) {
if (pos != undefined && downloadSize - pos < 100 * 1024) {
console.info('MineRcp data not enough, download more');
let downloadLength = 1024 * 1024;
if (this.fileSize - downloadSize <= downloadLength) {
downloadLength = this.fileSize - downloadSize;
}
if (!downloadStarted) {
download(downloadLength);
}
}
return num;
}
if (num === 0) {
console.info('MineRcp no data read, download more');
if (!downloadStarted) {
let downloadLength = 1024 * 1024;
if (this.fileSize - downloadSize <= downloadLength) {
downloadLength = this.fileSize - downloadSize;
}
download(downloadLength);
}
return 0;
}
return -1;
}
}
src.fileSize = this.fileSize;
this.isSeek = false; // 支持seek操作
this.player.dataSrc = src;
场景二:同一页面内视频播放横竖屏全屏切换无缝转场
方案
设置竖屏和全屏两个按钮,分别添加点击事件。
- 首先设置窗口方向,通过window的setPreferredOrientation接口来设置屏幕方向,接口文档: setPreferredO