Flutter 三方库 share_plus 的鸿蒙化适配与实战指南
Flutter 三方库 share_plus 的鸿蒙化适配与实战指南欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.netHey 大家好上海某高校计算机专业大一学生 今天来聊聊分享功能做聊天 App 怎么能少了分享呢用户看到一条有趣的消息、一张好看的图片想分享给好友——这时候就需要系统级的分享功能share_plus就是来解决这个问题的一、share_plus 是什么share_plus是一个 Flutter 插件提供跨平台的分享功能。它可以调用系统的分享面板让用户选择分享到微信、QQ、邮件等任何支持接收分享的应用。特点✅ 跨平台iOS、Android、鸿蒙、Web 都能用✅ 系统原生分享面板✅ 支持文本、链接、图片、文件✅ 零 UI直接调用系统功能二、依赖配置dependencies:share_plus:^10.1.4AtomGit 适配说明share_plus底层调用各平台的原生分享 API在鸿蒙上依赖系统的分享服务兼容性良好三、封装分享服务importpackage:flutter/foundation.dart;importpackage:share_plus/share_plus.dart;/// 分享服务/// 支持分享文本、链接、图片、文件到其他AppclassShareService{staticShareService?_instance;staticShareServicegetinstance_instance??ShareService._();ShareService._();1. 分享文本/// 分享纯文本【基础方法】FutureboolshareText(Stringtext,{String?subject})async{try{awaitShare.share(text,subject:subject);debugPrint(分享文本成功);returntrue;}catch(e){debugPrint(分享文本失败:$e);returnfalse;}}2. 分享链接/// 分享链接【实用方法】FutureboolshareUrl(Stringurl,{String?text})async{try{finalshareTexttext!null?$text\n$url:url;awaitShare.share(shareText);debugPrint(分享链接成功:$url);returntrue;}catch(e){debugPrint(分享链接失败:$e);returnfalse;}}3. 分享聊天消息/// 分享聊天消息【聊天场景专用】FutureboolshareChatMessage({requiredStringsenderName,requiredStringcontent,requiredStringtime,})async{try{finaltext$senderName($time):\n$content;awaitShare.share(text);debugPrint(分享聊天消息成功);returntrue;}catch(e){debugPrint(分享聊天消息失败:$e);returnfalse;}}4. 分享文件/// 分享文件【重要方法】FutureboolshareFiles(ListStringfilePaths,{String?text})async{try{// 将文件路径转换为 XFile 对象finalxFilesfilePaths.map((path)XFile(path)).toList();awaitShare.shareXFiles(xFiles,text:text);debugPrint(分享文件成功:${filePaths.length}个文件);returntrue;}catch(e){debugPrint(分享文件失败:$e);returnfalse;}}5. 分享图片/// 分享单张图片【常用方法】FutureboolshareImage(StringimagePath,{String?text})async{try{awaitShare.shareXFiles([XFile(imagePath)],text:text,);debugPrint(分享图片成功);returntrue;}catch(e){debugPrint(分享图片失败:$e);returnfalse;}}/// 分享多张图片【实用方法】FutureboolshareImages(ListStringimagePaths,{String?text})async{try{finalxFilesimagePaths.map((path)XFile(path)).toList();awaitShare.shareXFiles(xFiles,text:text);debugPrint(分享多张图片成功:${imagePaths.length}张);returntrue;}catch(e){debugPrint(分享多张图片失败:$e);returnfalse;}}6. 分享带截图/// 分享文字图片用于分享卡片预览FutureboolshareWithPreview({requiredStringtitle,requiredStringtext,requiredStringimagePath,})async{try{awaitShare.shareXFiles([XFile(imagePath)],text:$title\n$text,subject:title,);returntrue;}catch(e){debugPrint(分享失败:$e);returnfalse;}}四、在聊天页面中集成classChatMessageBubbleextendsStatelessWidget{finalChatMessagemessage;finalVoidCallbackonReply;finalVoidCallbackonForward;finalVoidCallbackonCopy;finalVoidCallbackonDelete;constChatMessageBubble({super.key,requiredthis.message,requiredthis.onReply,requiredthis.onForward,requiredthis.onCopy,requiredthis.onDelete,});overrideWidgetbuild(BuildContextcontext){returnGestureDetector(onLongPress:()_showMessageMenu(context),child:// 消息气泡内容);}/// 长按显示操作菜单void_showMessageMenu(BuildContextcontext){showModalBottomSheet(context:context,shape:constRoundedRectangleBorder(borderRadius:BorderRadius.vertical(top:Radius.circular(20)),),builder:(context)Container(padding:constEdgeInsets.symmetric(vertical:20),child:Column(mainAxisSize:MainAxisSize.min,children:[// 【分享按钮】ListTile(leading:constIcon(Icons.share,color:Color(0xFF6366F1)),title:constText(分享),onTap:(){Navigator.pop(context);_shareMessage(context);},),ListTile(leading:constIcon(Icons.reply),title:constText(回复),onTap:(){Navigator.pop(context);onReply();},),ListTile(leading:constIcon(Icons.copy),title:constText(复制),onTap:(){Navigator.pop(context);_copyMessage();},),ListTile(leading:constIcon(Icons.delete,color:Colors.red),title:constText(删除,style:TextStyle(color:Colors.red)),onTap:(){Navigator.pop(context);_confirmDelete(context);},),],),),);}/// 分享消息void_shareMessage(BuildContextcontext)async{finalshareServiceShareService.instance;if(message.typeMessageType.text){// 分享文本消息awaitshareService.shareChatMessage(senderName:message.senderName,content:message.content,time:_formatTime(message.timestamp),);}elseif(message.typeMessageType.imagemessage.imagePath!null){// 分享图片awaitshareService.shareImage(message.imagePath!,text:来自${message.senderName}的图片,);}}/// 复制消息void_copyMessage(){if(message.typeMessageType.text){Clipboard.setData(ClipboardData(text:message.content));}onCopy();}/// 确认删除void_confirmDelete(BuildContextcontext){showDialog(context:context,builder:(context)AlertDialog(title:constText(确认删除),content:constText(确定要删除这条消息吗),actions:[TextButton(onPressed:()Navigator.pop(context),child:constText(取消),),TextButton(onPressed:(){Navigator.pop(context);onDelete();},style:TextButton.styleFrom(foregroundColor:Colors.red),child:constText(删除),),],),);}String_formatTime(DateTimetime){return${time.hour}:${time.minute.toString().padLeft(2, 0)};}}五、在商品详情页中分享/// 商品卡片分享classProductShareButtonextendsStatelessWidget{finalProductproduct;constProductShareButton({super.key,requiredthis.product});overrideWidgetbuild(BuildContextcontext){returnIconButton(icon:constIcon(Icons.share),onPressed:()_shareProduct(context),);}void_shareProduct(BuildContextcontext)async{finalshareServiceShareService.instance;// 分享商品链接finalurlhttps://example.com/product/${product.id};finaltext${product.name}价格: ¥${product.price}${product.description};awaitshareService.shareUrl(url,text:text);}}六、测试功能/// 测试分享功能FutureMapString,dynamictestShare()async{try{awaitShare.share(这是一条来自Flutter聊天App的测试分享\n\n功能包括\n- 文本分享\n- 链接分享\n- 图片分享\n- 文件分享,subject:Flutter聊天App分享测试,);return{success:true,message:分享功能正常};}catch(e){return{success:false,message:分享功能异常:$e};}}七、踩坑纪实踩坑1分享图片闪退在鸿蒙设备上分享图片时有时候会闪退原因是图片路径可能不存在或者格式不支持。解决方案// 分享前检查文件是否存在finalfileFile(imagePath);if(!awaitfile.exists()){return{success:false,message:图片文件不存在};}// 如果是网络图片先下载到本地finallocalPathawait_downloadImage(imageUrl);if(localPath!null){awaitShare.shareXFiles([XFile(localPath)]);}踩坑2分享文本过长被截断分享超长文本时部分应用会截断。后来改成限制文本长度StringtruncateText(Stringtext,int maxLength){if(text.lengthmaxLength)returntext;return${text.substring(0,maxLength-3)}...;}踩坑3XFile 路径格式问题在鸿蒙上XFile 对路径格式有要求。必须使用完整的文件路径不能用 content:// 格式// 错误 ❌// XFile(content://xxx)// 正确 ✅XFile(/data/user/0/xxx/cache/image.jpg)踩坑4没有安装可分享的应用如果用户手机上没有安装任何可接收分享的应用share_plus 会抛出异常。需要做好异常处理try{awaitShare.share(Hello);}onPlatformExceptioncatch(e){if(e.codeACTIVITY_NOT_FOUND){// 没有可用的分享应用showSnackBar(未找到可用的分享应用);}}八、Android 配置!-- AndroidManifest.xml --application!-- 如果需要分享文件需要添加 FileProvider --providerandroid:nameandroidx.core.content.FileProviderandroid:authorities${applicationId}.fileproviderandroid:exportedfalseandroid:grantUriPermissionstruemeta-dataandroid:nameandroid.support.FILE_PROVIDER_PATHSandroid:resourcexml/file_paths//provider/application!-- res/xml/file_paths.xml --?xml version1.0 encodingutf-8?pathsxmlns:androidhttp://schemas.android.com/apk/res/androidcache-pathnamecachepath//files-pathnamefilespath//external-pathnameexternalpath///paths九、效果展示功能验证结果✅ 分享图片正常✅ 分享文件正常十、总结心得share_plus 真的是五星级好用的库一行代码就能调用系统分享而且鸿蒙兼容性也很好。核心要点文件路径要完整且存在网络图片需要先下载到本地长文本要适当截断做好异常处理使用场景聊天消息分享商品链接分享文章分享朋友圈分享后续计划研究 deep link 实现分享回调尝试自定义分享面板今天的分享就到这里有问题评论区见