HarmonyOS 鸿蒙Next中uniapp开发如何通过uts插件实现选择动态照片
HarmonyOS 鸿蒙Next中uniapp开发如何通过uts插件实现选择动态照片 通过uts插件实现选择动态照片,支持批量获取,并解析图片中包含的地址、视频等信息
您好,可以参考下uts插件文档
-
在uni-modules目录上点击右键,选择新建uni-modules插件,继续选择
UTS插件-API插件,键入合适的插件名后点击创建。utssdk目录下添加app-harmony目录和相关文件。 -
在app-harmony/index.uts中实现选择动态照片的逻辑。
-
在uni-app页面中调用插件。
【背景知识】
uts插件是指利用uts语法,调用OS的API或三方SDK,封装成一个供前端调用的uni_modules插件。
更多关于HarmonyOS 鸿蒙Next中uniapp开发如何通过uts插件实现选择动态照片的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
这是一个非常有技术深度的需求。在 UniApp 开发鸿蒙(HarmonyOS NEXT)应用时,标准的 uni.chooseImage 或 uni.chooseMedia 可能无法直接满足**“选择动态照片(Live Photo)”并“解析其中包含的地址、视频”**这种定制化需求。
要实现这个功能,你需要编写一个 UTS(Uni Type Script)插件,直接调用鸿蒙原生的 PhotoViewPicker 和 PHAsset 相关 API。
以下是实现这一功能的完整技术方案和代码逻辑:
核心思路
- 选择器(Picker): 使用鸿蒙原生的
@ohos.file.picker模块中的PhotoViewPicker。 - 权限: 需要在
module.json5中申请ohos.permission.READ_MEDIA。 - 数据获取: 获取到
PhotoAsset对象后,判断其是否为 Live Photo(通常包含一张图片和一段视频)。 - 解析信息:
- 视频: 从 Live Photo 中提取视频流并保存到临时路径。
- 地址: 读取图片的 EXIF 信息(GPS 标签)获取经纬度,再反解为地址。
第一步:配置权限
在 uni_modules/你的插件目录/package.json 或者主项目的 module.json5 中添加权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.READ_MEDIA",
"reason": "用于选择动态照片",
"usedScene": {
"abilities": ["MainAbility"],
"when": "always"
}
}
]
}
}
第二步:编写 UTS 插件代码
创建一个 UTS 类文件(例如 LivePhotoPicker.uts)。
// LivePhotoPicker.uts
import picker from '@ohos.file.picker';
import photoAccessHelper from '@ohos.file.photoAccessHelper';
import { BusinessError } from '@ohos.base';
import media from '@ohos.multimedia.media'; // 用于处理媒体资源
// 注意:读取EXIF可能需要 @ohos.multimedia.image 模块
export class LivePhotoPicker {
private photoPicker: picker.PhotoViewPicker;
constructor() {
this.photoPicker = new picker.PhotoViewPicker();
}
/**
* 选择动态照片
*/
async selectLivePhotos(): Promise<Array<LivePhotoResult>> {
return new Promise((resolve, reject) => {
// 1. 配置选择器,允许选择图片和视频(LivePhoto本质是图+视频)
let options = new picker.PhotoSelectOptions();
options.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 主要选图片,LivePhoto以图片形式展示
options.maxSelectNumber = 10; // 批量获取
this.photoPicker.select(options, (err, result) => {
if (err) {
reject(err);
return;
}
if (result && result.photoUris && result.photoUris.length > 0) {
// 2. 遍历选中的资源,解析详细信息
this.parseAssets(result.photoUris).then(res => {
resolve(res);
}).catch(e => {
reject(e);
});
} else {
resolve([]);
}
});
});
}
/**
* 解析资源(核心逻辑)
*/
private async parseAssets(uris: string[]): Promise<Array<LivePhotoResult>> {
let results: Array<LivePhotoResult> = [];
// 获取 PhotoAsset 实例(需要 context,这里假设你能获取到 application 的 context)
// 注意:在 uts 插件中获取 context 方式可能因版本而异,通常是 getContext()
let context = getContext() as common.UIAbilityContext;
let photoView = photoAccessHelper.getPhotoView(context);
for (let uri of uris) {
try {
// 通过 URI 获取 PhotoAsset
let asset = await photoView.getAssetFromUri(uri);
let resultItem = new LivePhotoResult();
resultItem.imagePath = uri; // 原图路径
// 3. 判断并提取 Live Photo 的视频部分
// Live Photo 在鸿蒙中通常是一个主资源,包含子资源(视频)
if (asset.type === photoAccessHelper.PhotoType.LIVE_PHOTO) {
// 获取子资源(即视频)
let subResources = await asset.getSubResources();
for (let subRes of subResources) {
if (subRes.type === photoAccessHelper.PhotoType.VIDEO) {
// 获取视频 URI 或文件流
resultItem.videoPath = subRes.uri;
break;
}
}
}
// 4. 解析 EXIF 信息(地址)
// 这里需要调用 image 模块读取图片的 ExifInterface
// 伪代码逻辑:
// let exif = await image.createExif(uri);
// resultItem.location = exif.getGPSInfo();
results.push(resultItem);
} catch (e) {
console.error('解析资源失败', e);
}
}
return results;
}
}
// 定义返回数据结构
export class LivePhotoResult {
imagePath: string = ''; // 图片路径
videoPath: string = ''; // 关联的视频路径(如果是LivePhoto)
latitude: number = 0; // 纬度
longitude: number = 0; // 经度
address: string = ''; // 解析后的地址
}
第三步:在 UniApp 页面中调用
// 在 .vue 页面中
import { LivePhotoPicker, LivePhotoResult } from '@/uni_modules/你的插件路径/LivePhotoPicker';
const picker = new LivePhotoPicker();
async function choosePhoto() {
try {
const photos: LivePhotoResult[] = await picker.selectLivePhotos();
console.log('选择的照片:', photos);
photos.forEach(p => {
console.log('图片:', p.imagePath);
if (p.videoPath) {
console.log('这是动态照片,包含视频:', p.videoPath);
}
if (p.address) {
console.log('拍摄地点:', p.address);
}
});
} catch (error) {
console.error('选择失败', error);
}
}
注意配置权限, 剩下的看下这个指南吧 https://doc.dcloud.net.cn/uni-app-x/plugin/uts-for-harmony.html
在您的uni-app项目中,通常在 uni_modules 目录下新建一个文件夹(例如 ha-photo-picker)作为插件根目录。
定义接口 :
在插件的 utssdk/interface.uts 文件中,定义将要暴露给前端的方法签名。
可以参考uts插件文档试试。
在HarmonyOS Next中,通过uts插件实现选择动态照片,需使用@ohos.multimedia.mediaLibrary API的getActiveAlbum方法获取动态照片相册,结合FileAsset的uri属性选取资源。在uniapp中封装uts插件,定义接口调用系统选择器,返回动态照片的本地路径或文件对象。注意需在module.json5中配置ohos.permission.READ_MEDIA权限。
在HarmonyOS NEXT中,通过uts插件实现动态照片选择与信息解析,核心在于利用系统Picker的PhotoViewPicker能力,结合媒体库接口获取Dynamic Photos元数据。
实现步骤:
-
集成Picker能力:在uts插件中,调用
ohos.file.picker的PhotoViewPicker。通过select方法设置MIME_TYPE_IMAGE过滤,并开启isPhotoDynamic属性支持动态照片。 -
批量获取URI:调用
select(option)返回用户选择的图片URI列表。需设置maxSelectNumber控制批量上限。 -
解析动态照片:对每个URI,使用
@ohos.multimedia.mediaLibrary或@ohos.multimedia.image接口。通过MediaDataSource读取原数据,检查文件是否包含动态元数据(如com.android.camera.dynamic标签或HDR增益图)。动态照片通常为HEIC文件内嵌MOV/MP4视频流,或存为独立视频帧。 -
提取地址与视频:获取动态照片关联的视频URI(通常为同文件名不同后缀或元数据引用),使用
@ohos.multimedia.media的VideoInfo接口提取时长、尺寸。地理位置通过ImageInfo的exif字段读取GPS坐标。
关键代码片段(uts):
import { PhotoViewPicker } from '@kit.MediaKit';
import { mediaLibrary } from '@kit.MediaKit';
async function pickDynamicPhotos(maxCount: number): Promise<Array<DynamicPhotoInfo>> {
const picker = new PhotoViewPicker();
const result = await picker.select({
MIME_TYPE: ['image/*'],
isPhotoDynamic: true,
maxSelectNumber: maxCount
});
return result.photoUris.map(uri => extractDynamicInfo(uri));
}
function extractDynamicInfo(uri: string): DynamicPhotoInfo {
// 使用mediaLibrary获取动态数据
const info = getDynamicMetaData(uri);
return {
uri: uri,
videoUri: info.videoUri,
latitude: info.gpsLatitude,
longitude: info.gpsLongitude,
duration: info.videoDuration
};
}
注意事项:
- Picker需在UIAbility上下文调用。
- 动态照片功能依赖设备硬件与系统版本(HarmonyOS NEXT 5.0+)。
- 批量选择时注意性能,避免阻塞主线程。


