HarmonyOS鸿蒙Next中如何在应用中实现分享功能?
HarmonyOS鸿蒙Next中如何在应用中实现分享功能? 鸿蒙应用可以通过系统分享功能分享内容,本文介绍如何使用 plus.share API 实现文本、图片、链接等内容的分享功能。
3 回复
一、分享功能架构设计
1. 分享类型支持
- 文本分享
- 图片分享
- 链接分享
- 多类型混合分享
2. 分享目标
- 系统分享面板
- 微信/QQ/微博等
- 复制到剪贴板
- 保存到相册
二、基础分享实现
1. 创建分享工具(utils/share.js)
/**
* 分享功能工具
* 支持文本、图片、链接等分享
*/
/**
* 分享文本
* @param {String} text 分享文本
* @param {Object} options 配置选项
* @returns {Promise<Object>} 分享结果
*/
export async function shareText(text, options = {}) {
const {
title = '分享',
success = null,
fail = null
} = options
return new Promise((resolve, reject) => {
// #ifdef APP-HARMONY
try {
// 使用 plus.share 分享文本
const shareService = plus.share.getServices((services) => {
if (services && services.length > 0) {
// 显示分享选择器
plus.share.sendWithSystem({
type: 'text',
content: text,
title: title,
success: (result) => {
console.log('分享成功:', result)
if (success) success(result)
resolve({
success: true,
result: result
})
},
fail: (error) => {
console.error('分享失败:', error)
if (fail) fail(error)
reject(error)
}
})
} else {
// 降级方案:复制到剪贴板
copyToClipboard(text)
resolve({
success: true,
method: 'clipboard'
})
}
}, (error) => {
console.error('获取分享服务失败:', error)
// 降级方案
copyToClipboard(text)
resolve({
success: true,
method: 'clipboard'
})
})
} catch (error) {
console.error('分享文本失败:', error)
// 降级方案
copyToClipboard(text)
resolve({
success: true,
method: 'clipboard'
})
}
// #endif
// #ifndef APP-HARMONY
// H5 或其他平台使用 Web Share API
if (navigator.share) {
navigator.share({
title: title,
text: text
}).then(() => {
if (success) success()
resolve({ success: true })
}).catch((error) => {
if (fail) fail(error)
reject(error)
})
} else {
// 降级方案
copyToClipboard(text)
resolve({
success: true,
method: 'clipboard'
})
}
// #endif
})
}
/**
* 分享图片
* @param {String} imagePath 图片路径(本地路径或网络路径)
* @param {Object} options 配置选项
* @returns {Promise<Object>} 分享结果
*/
export async function shareImage(imagePath, options = {}) {
const {
title = '分享图片',
description = '',
success = null,
fail = null
} = options
return new Promise((resolve, reject) => {
// #ifdef APP-HARMONY
try {
// 如果是网络图片,先下载到本地
if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
downloadImage(imagePath).then(localPath => {
shareLocalImage(localPath, options)
.then(resolve)
.catch(reject)
}).catch(reject)
} else {
shareLocalImage(imagePath, options)
.then(resolve)
.catch(reject)
}
} catch (error) {
console.error('分享图片失败:', error)
if (fail) fail(error)
reject(error)
}
// #endif
// #ifndef APP-HARMONY
// H5 平台
if (navigator.share && navigator.canShare) {
// 需要将图片转换为 File 对象
imageToFile(imagePath).then(file => {
navigator.share({
title: title,
text: description,
files: [file]
}).then(() => {
if (success) success()
resolve({ success: true })
}).catch((error) => {
if (fail) fail(error)
reject(error)
})
}).catch(reject)
} else {
// 降级方案:保存到相册
saveImageToAlbum(imagePath)
.then(() => {
uni.showToast({
title: '图片已保存到相册',
icon: 'success'
})
resolve({ success: true, method: 'album' })
})
.catch(reject)
}
// #endif
})
}
/**
* 分享本地图片
*/
function shareLocalImage(imagePath, options) {
return new Promise((resolve, reject) => {
// #ifdef APP-HARMONY
plus.share.sendWithSystem({
type: 'image',
pictures: [imagePath],
title: options.title || '分享图片',
content: options.description || '',
success: (result) => {
console.log('分享图片成功:', result)
if (options.success) options.success(result)
resolve({
success: true,
result: result
})
},
fail: (error) => {
console.error('分享图片失败:', error)
if (options.fail) options.fail(error)
reject(error)
}
})
// #endif
})
}
/**
* 分享链接
* @param {String} url 链接地址
* @param {Object} options 配置选项
* @returns {Promise<Object>} 分享结果
*/
export async function shareLink(url, options = {}) {
const {
title = '分享链接',
description = '',
thumb = '', // 缩略图
success = null,
fail = null
} = options
return new Promise((resolve, reject) => {
// #ifdef APP-HARMONY
try {
plus.share.sendWithSystem({
type: 'web',
href: url,
title: title,
content: description,
thumbs: thumb ? [thumb] : [],
success: (result) => {
console.log('分享链接成功:', result)
if (success) success(result)
resolve({
success: true,
result: result
})
},
fail: (error) => {
console.error('分享链接失败:', error)
// 降级方案:复制链接
copyToClipboard(url)
uni.showToast({
title: '链接已复制',
icon: 'success'
})
resolve({
success: true,
method: 'clipboard'
})
}
})
} catch (error) {
console.error('分享链接失败:', error)
copyToClipboard(url)
resolve({
success: true,
method: 'clipboard'
})
}
// #endif
// #ifndef APP-HARMONY
if (navigator.share) {
navigator.share({
title: title,
text: description,
url: url
}).then(() => {
if (success) success()
resolve({ success: true })
}).catch((error) => {
if (fail) fail(error)
copyToClipboard(url)
resolve({
success: true,
method: 'clipboard'
})
})
} else {
copyToClipboard(url)
resolve({
success: true,
method: 'clipboard'
})
}
// #endif
})
}
/**
* 分享多类型内容
* @param {Object} shareData 分享数据
* @returns {Promise<Object>} 分享结果
*/
export async function shareMultiple(shareData) {
const {
text = '',
image = '',
url = '',
title = '分享',
description = '',
thumb = ''
} = shareData
// #ifdef APP-HARMONY
try {
const shareOptions = {
title: title,
content: description || text,
success: (result) => {
console.log('分享成功:', result)
uni.showToast({
title: '分享成功',
icon: 'success'
})
},
fail: (error) => {
console.error('分享失败:', error)
uni.showToast({
title: '分享失败',
icon: 'none'
})
}
}
// 根据内容类型设置
if (url) {
shareOptions.type = 'web'
shareOptions.href = url
if (thumb) {
shareOptions.thumbs = [thumb]
}
} else if (image) {
shareOptions.type = 'image'
shareOptions.pictures = [image]
} else if (text) {
shareOptions.type = 'text'
shareOptions.content = text
}
return new Promise((resolve, reject) => {
plus.share.sendWithSystem(shareOptions)
})
} catch (error) {
console.error('分享失败:', error)
throw error
}
// #endif
}
三、辅助功能实现
2. 辅助工具函数
/**
* 复制到剪贴板
* @param {String} text 文本内容
* @returns {Promise<Boolean>} 是否成功
*/
export function copyToClipboard(text) {
return new Promise((resolve, reject) => {
uni.setClipboardData({
data: text,
success: () => {
uni.showToast({
title: '已复制',
icon: 'success'
})
resolve(true)
},
fail: (error) => {
console.error('复制失败:', error)
reject(error)
}
})
})
}
/**
* 下载网络图片到本地
* @param {String} imageUrl 图片 URL
* @returns {Promise<String>} 本地路径
*/
function downloadImage(imageUrl) {
return new Promise((resolve, reject) => {
uni.downloadFile({
url: imageUrl,
success: (res) => {
if (res.statusCode === 200) {
resolve(res.tempFilePath)
} else {
reject(new Error('下载失败'))
}
},
fail: (error) => {
reject(error)
}
})
})
}
/**
* 保存图片到相册
* @param {String} imagePath 图片路径
* @returns {Promise<Boolean>} 是否成功
*/
export function saveImageToAlbum(imagePath) {
return new Promise((resolve, reject) => {
// #ifdef APP-HARMONY
// 先保存到本地
if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
downloadImage(imagePath).then(localPath => {
saveLocalImageToAlbum(localPath)
.then(resolve)
.catch(reject)
}).catch(reject)
} else {
saveLocalImageToAlbum(imagePath)
.then(resolve)
.catch(reject)
}
// #endif
// #ifndef APP-HARMONY
// H5 平台需要用户手动保存
uni.showModal({
title: '保存图片',
content: '请长按图片保存',
showCancel: false
})
resolve(true)
// #endif
})
}
/**
* 保存本地图片到相册
*/
function saveLocalImageToAlbum(imagePath) {
return new Promise((resolve, reject) => {
// #ifdef APP-HARMONY
plus.gallery.save(
imagePath,
() => {
resolve(true)
},
(error) => {
console.error('保存图片失败:', error)
reject(error)
}
)
// #endif
// #ifndef APP-HARMONY
resolve(true)
// #endif
})
}
/**
* 生成分享图片(用于分享健康报告等)
* @param {Object} data 数据
* @returns {Promise<String>} 图片路径
*/
export async function generateShareImage(data) {
// 使用 canvas 生成分享图片
return new Promise((resolve, reject) => {
// 这里需要使用 canvas API 生成图片
// 具体实现根据需求定制
const ctx = uni.createCanvasContext('shareCanvas')
// 绘制背景
ctx.setFillStyle('#FFFFFF')
ctx.fillRect(0, 0, 750, 1334)
// 绘制内容
ctx.setFillStyle('#333333')
ctx.setFontSize(32)
ctx.fillText(data.title || '健康报告', 40, 100)
// ... 更多绘制内容
// 导出图片
ctx.draw(false, () => {
uni.canvasToTempFilePath({
canvasId: 'shareCanvas',
success: (res) => {
resolve(res.tempFilePath)
},
fail: reject
})
})
})
}
四、分享组件实现
3. 分享组件(components/share-panel/share-panel.vue)
<template>
<view class="share-panel-mask" v-if="visible" @tap="handleMaskTap">
<view class="share-panel" @tap.stop>
<view class="panel-header">
<text class="panel-title">分享到</text>
<text class="panel-close" @tap="handleClose">×</text>
</view>
<view class="panel-content">
<scroll-view scroll-y class="share-options">
<!-- 系统分享 -->
<view class="share-option" @tap="handleSystemShare">
<view class="option-icon system-icon">📤</view>
<text class="option-text">系统分享</text>
</view>
<!-- 复制链接 -->
<view class="share-option" @tap="handleCopyLink" v-if="shareData.url">
<view class="option-icon copy-icon">🔗</view>
<text class="option-text">复制链接</text>
</view>
<!-- 复制文本 -->
<view class="share-option" @tap="handleCopyText" v-if="shareData.text">
<view class="option-icon copy-icon">📋</view>
<text class="option-text">复制文本</text>
</view>
<!-- 保存图片 -->
<view class="share-option" @tap="handleSaveImage" v-if="shareData.image">
<view class="option-icon save-icon">💾</view>
<text class="option-text">保存图片</text>
</view>
<!-- 生成分享图 -->
<view class="share-option" @tap="handleGenerateImage" v-if="shareData.generateImage">
<view class="option-icon generate-icon">🖼️</view>
<text class="option-text">生成分享图</text>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import {
shareText,
shareImage,
shareLink,
shareMultiple,
copyToClipboard,
saveImageToAlbum,
generateShareImage
} from '@/utils/share.js'
export default {
name: 'SharePanel',
props: {
visible: {
type: Boolean,
default: false
},
shareData: {
type: Object,
default: () => ({
text: '',
image: '',
url: '',
title: '',
description: '',
thumb: ''
})
}
},
methods: {
handleMaskTap() {
this.handleClose()
},
handleClose() {
this.$emit('close')
},
// 系统分享
async handleSystemShare() {
try {
let result
if (this.shareData.url) {
result = await shareLink(this.shareData.url, {
title: this.shareData.title,
description: this.shareData.description,
thumb: this.shareData.thumb
})
} else if (this.shareData.image) {
result = await shareImage(this.shareData.image, {
title: this.shareData.title,
description: this.shareData.description
})
} else if (this.shareData.text) {
result = await shareText(this.shareData.text, {
title: this.shareData.title
})
} else {
result = await shareMultiple(this.shareData)
}
if (result.success) {
this.handleClose()
this.$emit('success', result)
}
} catch (error) {
console.error('分享失败:', error)
uni.showToast({
title: '分享失败',
icon: 'none'
})
}
},
// 复制链接
async handleCopyLink() {
try {
await copyToClipboard(this.shareData.url)
this.handleClose()
this.$emit('success', { method: 'copyLink' })
} catch (error) {
console.error('复制失败:', error)
}
},
// 复制文本
async handleCopyText() {
try {
await copyToClipboard(this.shareData.text)
this.handleClose()
this.$emit('success', { method: 'copyText' })
} catch (error) {
console.error('复制失败:', error)
}
},
// 保存图片
async handleSaveImage() {
try {
uni.showLoading({
title: '保存中...',
mask: true
})
await saveImageToAlbum(this.shareData.image)
uni.hideLoading()
this.handleClose()
this.$emit('success', { method: 'saveImage' })
} catch (error) {
uni.hideLoading()
console.error('保存失败:', error)
uni.showToast({
title: '保存失败',
icon: 'none'
})
}
},
// 生成分享图
async handleGenerateImage() {
try {
uni.showLoading({
title: '生成中...',
mask: true
})更多关于HarmonyOS鸿蒙Next中如何在应用中实现分享功能?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,应用分享功能主要通过Share模块实现。使用ShareAction类创建分享意图,设置分享内容(如文本、链接、文件等)。通过show()方法触发系统分享面板,用户可选择目标应用进行分享。分享数据需符合系统定义的ShareData格式。
在HarmonyOS Next中,应用可以通过系统分享功能实现内容分享。以下是使用plus.share API实现分享功能的核心步骤:
- 导入模块:在代码中导入
@kit.ShareKit模块。 - 创建分享器:使用
ShareKit.getShareService()获取系统分享服务。 - 配置分享内容:构建
ShareOption对象,设置分享的标题、文本、链接或图片URI等。 - 调用分享:调用
share()方法触发系统分享面板,用户可选择目标应用进行分享。
示例代码(文本分享):
import shareKit from '@kit.ShareKit';
let shareService = shareKit.getShareService();
let shareOption = {
title: '分享标题',
text: '这是分享的文本内容。',
link: 'https://example.com'
};
shareService.share(shareOption).then(() => {
console.log('分享成功');
}).catch((err) => {
console.error('分享失败: ' + err);
});
关键点:
- 分享图片时需将图片路径转换为URI格式(如
dataability://或file://)。 - 系统分享面板会自动适配可用应用(如邮件、社交软件)。
- 分享操作依赖用户界面交互触发。
此方式无需处理具体应用逻辑,由系统统一调度,符合HarmonyOS Next的安全与体验规范。

