HarmonyOS应用开发实战:猫猫大作战-systemShare 的使用
·


前言
ShareKit 是 HarmonyOS 的分享服务能力,支持应用间分享文本、图片、文件等数据。在「猫猫大作战」中,玩家完成一局游戏后可以分享战绩到微信、微博等社交平台,吸引更多朋友来挑战。
本文以「猫猫大作战」的战绩分享功能为锚点,讲解 systemShare 的完整使用方法,包括文本分享、图片分享、UniformDataObject 数据封装、以及分享后的回调处理。
提示:本系列不讲 ArkTS 基础语法与环境搭建。本篇是阶段五第 154 篇。
一、systemShare 基础用法
1.1 分享文本
import { systemShare } from '@kit.ShareKit';
import { uniformDataStruct } from '@kit.ArkData';
async function shareText(score: number, playerName: string): Promise<void> {
const sharedData: uniformDataStruct.UniformDataObject = {
value: {
text: `我在「猫猫大作战」中获得了 ${score} 分!快来挑战我吧!🐱`,
html: `<h3>猫猫大作战</h3><p>得分: <b>${score}</b></p><p>玩家: ${playerName}</p>`,
},
type: 'general.text',
};
await systemShare.share(sharedData);
}
1.2 参数说明
| 参数 | 类型 | 说明 | 示例 |
|---|---|---|---|
value.text |
string | 纯文本内容 | “我在猫猫大作战中获得了 2450 分!” |
value.html |
string | HTML 富文本(可选) | <b>2450</b> 分 |
type |
string | 统一类型标识符 (UTD) | 'general.text'、'general.image' |
提示:
type字段是 UTD(Uniform Type Descriptor),告诉系统分享数据的类型。常用类型:general.text(文本)、general.image(图片)、general.file(文件)。
二、 UniformDataObject 数据封装
2.1 数据封装方法
import { uniformDataStruct } from '@kit.ArkData';
// 文本分享
const textData: uniformDataStruct.UniformDataObject = {
value: { text: '分享内容', html: '<b>富文本</b>' },
type: 'general.text',
};
// 图片分享
const imageData: uniformDataStruct.UniformDataObject = {
value: { image: pixelMap },
type: 'general.image',
};
// 文件分享
const fileData: uniformDataStruct.UniformDataObject = {
value: { fileUri: 'file://{sandboxPath}/score.png' },
type: 'general.file',
};
2.2 数据类型的 UTD 对照
| 分享类型 | UTD 标识 | value 格式 | 目标应用 |
|---|---|---|---|
| 纯文本 | general.text |
{ text: string } |
微信、短信 |
| 富文本 | general.text |
{ text, html } |
微信、QQ |
| 图片 | general.image |
{ image: PixelMap } |
微博、朋友圈 |
| 文件 | general.file |
{ fileUri: string } |
文件管理器 |
| 链接 | general.url |
{ url: string } |
浏览器 |
三、游戏中分享战绩的完整实现
3.1 战绩分享按钮
// 游戏结束界面的分享按钮
@Builder
ShareButton(score: number, playerName: string) {
Button({
icon: $r('app.media.ic_share'),
text: '分享战绩'
})
.width('80%').height(48)
.fontSize(17).fontColor('#FFFFFF')
.backgroundColor('#45B7D1')
.borderRadius(24)
.onClick(async () => {
try {
await shareGameResult(score, playerName);
promptAction.showToast({ message: '分享成功!' });
} catch (err) {
console.error(`分享失败: ${err.message}`);
promptAction.showToast({ message: '分享取消或失败' });
}
})
}
3.2 构造分享内容
async function shareGameResult(score: number, playerName: string): Promise<void> {
// 构造分享文本
const scoreText = score.toLocaleString('zh-CN');
const shareContent = formatShareText(score, playerName);
const sharedData: uniformDataStruct.UniformDataObject = {
value: {
text: shareContent.text,
html: shareContent.html,
},
type: 'general.text',
};
await systemShare.share(sharedData);
}
function formatShareText(score: number, playerName: string) {
const scoreText = score.toLocaleString('zh-CN');
return {
text: `🐱 我在「猫猫大作战」中获得 ${scoreText} 分!来挑战我的记录吧!下载地址: https://appgallery.huawei.com/cat-battle-war`,
html: `
<div style="text-align:center;padding:20px;">
<h2>🐱 猫猫大作战</h2>
<p style="font-size:24px;color:#E74C3C;">
<b>${scoreText}</b> 分
</p>
<p>玩家: ${playerName}</p>
<p style="font-size:14px;color:#95A5A6;">
来挑战我的记录吧!
</p>
</div>
`,
};
}
3.3 分享回调处理
// systemShare.share() 返回的 Promise
// resolve = 用户选择了分享目标
// reject = 用户取消或分享失败
try {
const result = await systemShare.share(sharedData);
// 分享成功(用户选择了目标应用)
console.info('分享成功', JSON.stringify(result));
// 可以在这里触发分享成功统计
analytics.recordEvent('share_success', { score });
} catch (err) {
// 用户取消或在目标应用分享失败
console.info(`分享取消: ${err.message}`);
// 不视为错误,只记录取消
analytics.recordEvent('share_cancel');
}
四、分享图片(截图)
4.1 截取游戏画面
import { image } from '@kit.ImageKit';
async function captureAndShare(): Promise<void> {
// 1. 获取当前 UI 的 PixelMap(截图)
const uiContext = this.getUIContext();
const pixelMap = await uiContext.createPixelMap({
width: 360,
height: 640,
});
// 2. 编码为 JPEG
const packer = image.createImagePacker();
const buffer = await packer.packing(pixelMap, {
format: 'image/jpeg',
quality: 85,
});
packer.release();
// 3. 保存到临时文件
const context = getContext() as common.UIAbilityContext;
const tempPath = `${context.tempDir}/share_score.jpg`;
const file = fileIo.openSync(tempPath,
fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);
fileIo.writeSync(file.fd, buffer);
fileIo.closeSync(file);
// 4. 分享图片文件
const sharedData: uniformDataStruct.UniformDataObject = {
value: { fileUri: `file://${tempPath}` },
type: 'general.file',
};
await systemShare.share(sharedData);
}
4.2 图片规��
| 图片类型 | 建议尺寸 | 格式 | 质量 | 文件大小 |
|---|---|---|---|---|
| 战绩分享截图 | 360×640 | JPEG | 85% | ~100KB |
| 邀请横幅 | 720×360 | PNG | - | ~200KB |
| 角色卡片 | 240×240 | PNG | - | ~50KB |
提示:分享图片文件大小建议不超过 1MB。过大的图片在社交平台加载慢,可能被压缩。
五、文件分享(战绩数据导出)
async function shareGameData(playerName: string, records: GameRecord[]): Promise<void> {
// 1. 序列化战绩数据为 JSON
const data = JSON.stringify({
playerName,
exportDate: new Date().toISOString(),
records,
}, null, 2);
// 2. 写入临时文件
const context = getContext() as common.UIAbilityContext;
const filePath = `${context.tempDir}/game_data_${Date.now()}.json`;
const file = fileIo.openSync(filePath,
fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);
fileIo.writeSync(file.fd, data);
fileIo.closeSync(file);
// 3. 分享文件
const sharedData: uniformDataStruct.UniformDataObject = {
value: { fileUri: `file://${filePath}` },
type: 'general.file',
};
await systemShare.share(sharedData);
}
六、ShareKit vs 原生分享方案
| 维度 | systemShare | 原生 systemShare | 自定义分享面板 |
|---|---|---|---|
| 集成复杂度 | 简单(3 行代码) | 中等 | 复杂 |
| 目标应用 | 系统所有支持的应用 | 系统所有 | 手动指定 |
| UI 一致性 | 系统原生界面 | 系统原生 | 需自定义 |
| 支持数据类型 | 文本/图片/文件 | 文本/URI | 任意 |
| 推荐场景 | 通用分享 | 通用分享 | 品牌定制分享 |
七、分享最佳实践
7.1 分享内容策略
- 引人注目的开头:用 Emoji 🐱🏆 吸引注意
- 具体数字:得分要精确(2450 分 比"很高分"更吸引人)
- 行动号召:“来挑战我吧!” 引导好友下载
- 下载链接:附带应用市场下载地址
- 个性化:包含玩家名称,让好友知道是谁在邀请
7.2 性能考虑
// ✅ 分享操作应在用户点击后异步执行,避免阻塞 UI
Button('分享').onClick(async () => {
// show loading
this.isSharing = true;
try {
await shareGameResult(this.score, this.playerName);
} finally {
this.isSharing = false;
}
})
// ✅ 大图片分享前压缩
async function compressForShare(pixelMap: PixelMap): Promise<ArrayBuffer> {
const packer = image.createImagePacker();
const buffer = await packer.packing(pixelMap, {
format: 'image/jpeg',
quality: 75, // 适当降低质量减小文件
});
packer.release();
return buffer;
}
八、错误排查
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| 分享界面未弹出 | 数据格式错误 | 检查 UniformDataObject 结构 |
| 分享后无响应 | UTD 类型不匹配 | 确保 type 与实际 value 匹配 |
| 图片分享失败 | 文件路径不存在 | 检查 file:// 路径和文件权限 |
| 内容为空 | value.text 未设 | 确保 text 字段有内容 |
九、权限与合规
// 分享不需要额外权限
// 但如果要分享图片,需要读取临时文件的权限
// 临时文件在 tempDir 中,应用自有权限可直接读写
// 隐私提示:分享内容中包含玩家名称,需在隐私政策中说明
const sharePrivacyNotice = `
分享功能会包含您的游戏昵称和得分信息。
这些信息仅用于本次分享,不会被我们收集。
`;
十、多语言分享
function formatShareByLocale(score: number, locale: string) {
const scoreText = score.toLocaleString(locale === 'zh' ? 'zh-CN' : 'en-US');
const templates: Record<string, { text: string; html: string }> = {
'zh': {
text: `🐱 我在「猫猫大作战」中获得 ${scoreText} 分!`,
html: `<b>${scoreText}</b> 分`,
},
'en': {
text: `🐱 I scored ${scoreText} in Cat Battle!`,
html: `Score: <b>${scoreText}</b>`,
},
};
return templates[locale] ?? templates['en'];
}
总结
ShareKit 通过 systemShare.share() 提供系统级分享能力,支持文本、图片、文件三种数据格式。核心要点:UniformDataObject 封装数据、 type 字段标识数据类型、 文本分享附带 HTML 增强展示、 图片先压缩再分享、 分享取消非异常、 包含下载链接传播应用。
下一篇将深入 systemShare——SharedData 与 UTD 类型详解。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐

所有评论(0)