鸿蒙学习实战之路-Share Kit系列(5/17)-分享视频内容实战
最近好多朋友问我:“西兰花啊,我想让用户分享视频,比如短视频、录像之类的,但不知道代码怎么写?” 害,这问题可问对人了!今天这篇,我就手把手带你实现分享视频功能,从零到一,全程不超过 5 分钟(不含调试时间)~
鸿蒙学习实战之路-Share Kit系列(5/17)-分享视频内容实战
最近好多朋友问我:“西兰花啊,我想让用户分享视频,比如短视频、录像之类的,但不知道代码怎么写?” 害,这问题可问对人了!
今天这篇,我就手把手带你实现分享视频功能,从零到一,全程不超过 5 分钟(不含调试时间)~
分享视频是啥?
分享视频就是把视频文件分享到其他应用或设备。比如:
- 分享短视频到微信
- 分享录像到微博
- 分享视频到华为图库
目标设备会把视频保存到图库,方便用户查看和管理。
核心步骤
实现分享视频,就三步:
- 构造分享数据:创建 SharedData 对象,utd 类型设置为
general.video - 构建分享控制器:创建 ShareController 对象
- 显示分享面板:调用 show 方法显示分享面板
完整代码示例
import { common } from '@kit.AbilityKit';
import { systemShare } from '@kit.ShareKit';
// 步骤1:构造分享数据
let shareData: systemShare.SharedData = new systemShare.SharedData({
utd: 'general.video',
uri: 'file://.../xxx.mp4',
title: '分享视频',
preview: 'file://.../preview.jpg',
description: '这是一段分享视频'
});
// 步骤2:构建分享控制器
let controller: systemShare.ShareController = new systemShare.ShareController(shareData);
// 步骤3:显示分享面板
let uiContext: UIContext = this.getUIContext();
let context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;
controller.show(context, {
previewMode: systemShare.SharePreviewMode.DEFAULT,
selectionMode: systemShare.SelectionMode.SINGLE
});
参数详解
utd - 视频类型标识
utd: 'general.video' 表示这是一个视频类型的数据。
🥦 西兰花小贴士:general.video 是通用的视频类型,适用于大部分视频分享场景。如果你需要更精确的视频类型,可以使用具体的视频格式,比如:
general.mp4:MP4 格式视频general.avi:AVI 格式视频general.mov:MOV 格式视频
uri - 视频文件路径
uri: 'file://.../xxx.mp4' 是视频文件的 URI 路径。
这个路径需要指向一个实际存在的视频文件,否则分享会失败。
🥦 西兰花警告:
我有个朋友第一次分享视频,随便写了个路径,结果分享面板弹出来但分享失败,debug 了两小时才发现文件不存在!血泪教训啊朋友们!
title - 分享标题
title: '分享视频' 是分享内容的标题,会在分享面板中显示。
这个标题要简洁明了,让用户一眼就知道分享的是什么内容。
preview - 封面图
preview: 'file://.../preview.jpg' 是封面图的 URI 路径。
封面图会在分享面板中显示,提升用户体验。如果不需要封面图,可以不设置这个参数。
🥦 西兰花小贴士:
封面图可以是视频的截图,也可以是自定义的图片。建议使用视频的截图,这样用户能更直观地了解视频内容。
description - 分享描述
description: '这是一段分享视频' 是分享内容的描述信息,会在分享面板中显示。
描述信息可以更详细地说明分享的内容,帮助用户理解。
在实际项目中怎么用?
上面的代码是基础实现,但在实际项目中,你可能会这样用:
示例:分享短视频
import { common } from '@kit.AbilityKit';
import { systemShare } from '@kit.ShareKit';
@Entry
@Component
struct VideoPage {
// 视频数据
videoTitle: string = '西兰花烹饪教程';
videoPath: string = 'file://.../broccoli_cooking.mp4';
videoPreview: string = 'file://.../preview.jpg';
videoDescription: string = '教你如何烹饪美味的西兰花';
// 分享视频
onShareVideo() {
// 构造分享数据
let shareData: systemShare.SharedData = new systemShare.SharedData({
utd: 'general.video',
uri: this.videoPath,
title: this.videoTitle,
preview: this.videoPreview,
description: this.videoDescription
});
// 构建分享控制器
let controller: systemShare.ShareController = new systemShare.ShareController(shareData);
// 显示分享面板
let uiContext: UIContext = this.getUIContext();
let context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;
controller.show(context, {
previewMode: systemShare.SharePreviewMode.DEFAULT,
selectionMode: systemShare.SelectionMode.SINGLE
});
}
build() {
Column() {
Image(this.videoPreview)
.width(200)
.height(200)
.margin(20);
Text(this.videoTitle)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ left: 20, right: 20, bottom: 10 })
.fontColor(Color.Black);
Text(this.videoDescription)
.fontSize(16)
.margin({ left: 20, right: 20, bottom: 20 })
.fontColor(Color.Gray);
Button('分享视频')
.onClick(() => {
this.onShareVideo();
})
.margin(20);
}
.width('100%')
.height('100%');
}
}
如何生成视频封面图?
上面的示例中,封面图是固定的。但在实际项目中,你可能需要从视频中提取封面图。
示例:从视频中提取封面图
import { image } from '@kit.ImageKit';
import { media } from '@kit.MediaKit';
import { fileIo } from '@kit.CoreFileKit';
// 从视频中提取封面图
async function extractVideoThumbnail(videoPath: string, outputPath: string): Promise<void> {
try {
// 创建视频播放器
let videoPlayer = await media.createVideoPlayer();
// 设置视频源
videoPlayer.src = videoPath;
// 等待视频准备就绪
await new Promise<void>((resolve) => {
videoPlayer.on('playbackComplete', () => {
resolve();
});
});
// 获取视频时长
let duration = videoPlayer.duration;
// 跳转到视频的中间位置
let seekTime = duration / 2;
await videoPlayer.seek(seekTime, media.SeekMode.SEEK_NEXT_SYNC);
// 获取当前帧
let surfaceId = videoPlayer.getSurfaceId();
let imageInfo = await image.createImageInfo(surfaceId);
let pixelMap = await image.createPixelMap(imageInfo);
// 保存为图片
let file = await fileIo.open(outputPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
let imagePacker = image.createImagePacker();
let packOpts = image.PackingOption();
let packedData = await imagePacker.packing(pixelMap, packOpts);
await fileIo.write(file.fd, packedData);
await fileIo.close(file.fd);
// 释放资源
pixelMap.release();
videoPlayer.release();
} catch (e) {
console.error(`提取视频封面图失败:${e}`);
}
}
// 使用示例
extractVideoThumbnail('file://.../xxx.mp4', 'file://.../preview.jpg');
🥦 西兰花小贴士:
上面的代码是一个简化的示例,实际使用时可能需要根据你的需求进行调整。比如,你可以选择视频的任意一帧作为封面图,而不仅仅是中间帧。
如何从相册选择视频并分享?
上面的示例中,视频路径是固定的。但在实际项目中,你可能需要让用户从相册选择视频,然后分享。
示例:从相册选择视频并分享
import { common } from '@kit.AbilityKit';
import { systemShare } from '@kit.ShareKit';
import { picker } from '@kit.CoreFileKit';
@Entry
@Component
struct GalleryVideoSharePage {
// 选中的视频路径
selectedVideo: string = '';
// 从相册选择视频
async selectVideoFromGallery(): Promise<void> {
try {
// 创建视频选择器
let videoPicker = new picker.PhotoViewPicker();
// 选择视频
let result = await videoPicker.select({
MIMEType: picker.PhotoViewMIMETypes.VIDEO_TYPE,
maxSelectNumber: 1
});
// 获取选中的视频路径
if (result.photoUris && result.photoUris.length > 0) {
this.selectedVideo = result.photoUris[0];
}
} catch (e) {
console.error(`选择视频失败:${e}`);
}
}
// 分享选中的视频
onShareSelectedVideo() {
if (!this.selectedVideo) {
console.error('请先选择视频');
return;
}
// 构造分享数据
let shareData: systemShare.SharedData = new systemShare.SharedData({
utd: 'general.video',
uri: this.selectedVideo,
title: '分享视频',
preview: this.selectedVideo
});
// 构建分享控制器
let controller: systemShare.ShareController = new systemShare.ShareController(shareData);
// 显示分享面板
let uiContext: UIContext = this.getUIContext();
let context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;
controller.show(context, {
previewMode: systemShare.SharePreviewMode.DEFAULT,
selectionMode: systemShare.SelectionMode.SINGLE
});
}
build() {
Column() {
Text('从相册选择视频并分享')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin(20)
.fontColor(Color.Black);
if (this.selectedVideo) {
Text(this.selectedVideo)
.fontSize(16)
.margin(20)
.fontColor(Color.Gray);
}
Row() {
Button('选择视频')
.onClick(() => {
this.selectVideoFromGallery();
})
.margin(10);
Button('分享视频')
.onClick(() => {
this.onShareSelectedVideo();
})
.margin(10);
}
.margin(20);
}
.width('100%')
.height('100%');
}
}
常见问题
Q1:分享视频时提示"文件不存在"怎么办?
检查以下几点:
-
文件路径是否正确:
- 确认 uri 指向的文件是否存在
- 确认 uri 格式是否正确(
file://开头)
-
文件权限是否正确:
- 确认应用是否有读取该文件的权限
Q2:如何分享不同格式的视频?
不同格式的视频,分享方式是一样的,只需要确保 uri 指向正确格式的视频文件即可:
- MP4 格式:
file://.../xxx.mp4 - AVI 格式:
file://.../xxx.avi - MOV 格式:
file://.../xxx.mov
Q3:如何限制分享视频的大小?
Share Kit 对分享数据量有限制,单次分享的分享数据描述信息总量不能超过 200KB。
如果视频过大,可以考虑:
- 压缩视频:在分享前先压缩视频
- 降低分辨率:降低视频的分辨率和码率
- 改为分享链接:如果视频是网络视频,可以改为分享视频链接
下一步学什么?
看完这篇,你应该已经能实现分享视频功能了。接下来可以深入学习:
- 分享链接内容:分享 App Linking 或普通链接
- 高级功能:自定义分享面板、获取分享结果
- 目标应用接入:让你的应用能接收其他应用分享的视频
- 跨端分享:碰一碰分享、隔空传送
推荐资料
📚 官方文档:
我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦
更多推荐



所有评论(0)