Xamarin.Forms自定义分享同时发图片与URL时Android端图片无法分享问题
Android端图片无法同步分享的常见成因
- Intent类型配置错误:同时分享文本+图片时必须将Intent的type设置为
"*/*",如果仅设置为text/plain,系统会直接忽略携带的图片参数。 - 文件权限未适配:Android 7.0及以上版本禁止直接传递
file://格式的URI,必须通过FileProvider生成content://格式的URI,同时需要给目标应用添加Intent.FLAG_GRANT_READ_URI_PERMISSION临时读取权限,否则第三方应用无法读取图片资源,会自动丢弃图片参数。 - Extra参数键值不匹配:图片必须通过
Intent.ExtraStream传入,若误将图片路径作为文本参数传入,系统无法识别为图片资源。 - 目标应用限制:少数第三方应用本身不支持多类型内容同时接收,会优先读取文本丢弃图片,该类情况属于应用自身规则限制,和代码实现无关。
跨平台多内容分享正确实现方案
1. 共享项目接口定义
先在共享项目中声明跨平台调用接口:
public interface IShareService { void Share(string title, string contentText, string shareUrl, string imageLocalPath = null); }
业务层调用时直接通过DependencyService.Get<IShareService>()获取实例触发分享即可。
2. Android端实现
前置配置:添加FileProvider
在Android项目的AndroidManifest.xml的<application>节点下添加Provider配置:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
在Resources/xml目录下新建file_paths.xml,配置允许分享的文件路径:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="app_files" path="." /> <cache-path name="app_cache" path="." /> <external-files-path name="external_files" path="." /> </paths>
接口实现代码
[assembly: Dependency(typeof(ShareServiceAndroid))] namespace YourAppNamespace.Droid { public class ShareServiceAndroid : IShareService { public void Share(string title, string contentText, string shareUrl, string imageLocalPath = null) { var shareIntent = new Intent(Intent.ActionSend); // 多类型分享必须设置为通用类型 shareIntent.SetType("*/*"); // 拼接文本和URL string fullContent = $"{contentText}\n{shareUrl}"; shareIntent.PutExtra(Intent.ExtraText, fullContent); shareIntent.PutExtra(Intent.ExtraSubject, title); if (!string.IsNullOrEmpty(imageLocalPath)) { var imageFile = new Java.IO.File(imageLocalPath); // 生成合规的Content URI Android.Net.Uri imageUri = FileProvider.GetUriForFile( Android.App.Application.Context, $"{Android.App.Application.Context.PackageName}.fileprovider", imageFile); shareIntent.PutExtra(Intent.ExtraStream, imageUri); // 授予临时读取权限 shareIntent.AddFlags(ActivityFlags.GrantReadUriPermission); } var chooserIntent = Intent.CreateChooser(shareIntent, title); chooserIntent.SetFlags(ActivityFlags.NewTask); Android.App.Application.Context.StartActivity(chooserIntent); } } }
3. iOS端实现
iOS原生UIActivityViewController天然支持多类型内容同时传递,实现代码如下:
[assembly: Dependency(typeof(ShareServiceiOS))] namespace YourAppNamespace.iOS { public class ShareServiceiOS : IShareService { public void Share(string title, string contentText, string shareUrl, string imageLocalPath = null) { var shareItems = new List<NSObject>(); if (!string.IsNullOrEmpty(contentText)) shareItems.Add(new NSString(contentText)); if (!string.IsNullOrEmpty(shareUrl)) shareItems.Add(NSUrl.FromString(shareUrl)); if (!string.IsNullOrEmpty(imageLocalPath) && File.Exists(imageLocalPath)) shareItems.Add(UIImage.FromFile(imageLocalPath)); var activityVc = new UIActivityViewController(shareItems.ToArray(), null); // 获取当前顶层控制器弹出分享面板 var topVc = UIApplication.SharedApplication.KeyWindow.RootViewController; while (topVc.PresentedViewController != null) topVc = topVc.PresentedViewController; // 适配iPad弹出规则 if (activityVc.PopoverPresentationController != null) { activityVc.PopoverPresentationController.SourceView = topVc.View; activityVc.PopoverPresentationController.SourceRect = new CoreGraphics.CGRect( topVc.View.Bounds.Width / 2, topVc.View.Bounds.Height / 2, 0, 0); activityVc.PopoverPresentationController.PermittedArrowDirections = UIPopoverArrowDirection.Any; } topVc.PresentViewController(activityVc, true, null); } } }
内容的提问来源于stack exchange,提问作者장주명
相关产品推荐
相关产品推荐

