使用 Xamarin Forms 共享图像

Sharing an image using Xamarin Forms

我已经创建了一个 Xamarin Forms (PCL) 解决方案,目前我正专注于 Android 项目。我正在尝试使用依赖服务实现图像共享。图片位于 Android 项目的可绘制文件夹中。但是,每次我 运行 下面的代码时,应用程序都会崩溃:发生未处理的异常。我检查了输出日志,但没有什么特别的。谁能 运行 查看我的代码并告诉我其中是否有错误?

非常感谢

接口:

public interface IShare
{
    void Share(ImageSource imageSource);
}

Xaml:

<ContentPage.Content>
    <Image x:Name="LogoImage" Source="icon.png"/>
</ContentPage.Content>

代码隐藏:

private void Action_Clicked(object sender, EventArgs e)
{
    DependencyService.Get<IShare>().Share(LogoImage.Source);
}

ShareClass(在Android项目中):

[assembly: Dependency(typeof(ShareClass))]
namespace MyProject.Droid
{
    public class ShareClass : Activity, IShare
    {
        public async void Share(ImageSource imageSource)
        {
            var intent = new Intent(Intent.ActionSend);
            intent.SetType("image/png");

            var handler = new ImageLoaderSourceHandler();
            var bitmap = await handler.LoadImageAsync(imageSource, this);

            var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads
                + Java.IO.File.Separator + "logo.png");

            using (var os = new System.IO.FileStream(path.AbsolutePath, FileMode.Create))
            {
                bitmap.Compress(Bitmap.CompressFormat.Png, 100, os);
            }

            intent.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(path));
            Forms.Context.StartActivity(Intent.CreateChooser(intent, "Share Image"));

        }
    }
}

您首先需要在AndroidManifest.xml中添加权限。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"  />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Xamarin.Android

[assembly:Dependency(typeof(ShareClass))]
namespace ShareDemo.Droid
{
    public class ShareClass : Activity, IShare
    {
        public async void Share(string subject, string message, ImageSource image)
        {
            Intent intent = new Intent(Intent.ActionSend);
            //intent.PutExtra(Intent.ExtraSubject, subject);
            intent.PutExtra(Intent.ExtraText, message);
            intent.SetType("image/png");

            ImageLoaderSourceHandler handler = new 
            ImageLoaderSourceHandler();
            Bitmap bitmap = await handler.LoadImageAsync(image, this);

            Java.IO.File path = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads + Java.IO.File.Separator + "logo.png");

            using (System.IO.FileStream os = new System.IO.FileStream(path.AbsolutePath, System.IO.FileMode.Create))
            {
                bitmap.Compress(Bitmap.CompressFormat.Png, 100, os);
            }

            intent.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(path));
            Forms.Context.StartActivity(Intent.CreateChooser(intent, "Share Image"));
        }
    }
}

Xamarin.iOS

[assembly: Dependency(typeof(ShareClass))]
namespace ShareSample.iOS
{
    public class ShareClass : IShare
    {
        public async void Share(string subject, string message, ImageSource image)
        {
            var handler = new ImageLoaderSourceHandler();
            var uiImage = await handler.LoadImageAsync(image);
            var img = NSObject.FromObject(uiImage);
            var mess = NSObject.FromObject(message);
            var activityItems = new[] { mess, img };
            var activityController = new UIActivityViewController(activityItems, null);
            var topController = UIApplication.SharedApplication.KeyWindow.RootViewController;

            while (topController.PresentedViewController != null)
            {
                topController = topController.PresentedViewController;
            }

            topController.PresentViewController(activityController, true, () => { });
        }
    }
}

这是我用于 ShareClass 的代码,最终使共享意图起作用,希望它对某人有所帮助:

[assembly: Xamarin.Forms.Dependency(typeof(ShareClass))]
namespace MyProject.Droid
{
public class ShareClass: MainActivity, IShare
{
    public async void Share(ImageSource imageSource)
    {
        var intent = new Intent(Intent.ActionSend);

        intent.SetType("image/jpeg");

        IImageSourceHandler handler;

        if (imageSource is FileImageSource)
        {
            handler = new FileImageSourceHandler();
        }
        else if (imageSource is StreamImageSource)
        {
            handler = new StreamImagesourceHandler(); // sic
        }
        else if (imageSource is UriImageSource)
        {
            handler = new ImageLoaderSourceHandler(); // sic
        }
        else
        {
            throw new NotImplementedException();
        }

        var bitmap = await handler.LoadImageAsync(imageSource, CrossCurrentActivity.Current.Activity);

        Java.IO.File path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads
            + Java.IO.File.Separator + "MyDiagram.jpg");

        using (System.IO.FileStream os = new System.IO.FileStream(path.AbsolutePath, System.IO.FileMode.Create))
        {
            bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, os);
        }

        intent.AddFlags(ActivityFlags.GrantReadUriPermission);
        intent.AddFlags(ActivityFlags.GrantWriteUriPermission);
        intent.PutExtra(Intent.ExtraStream, FileProvider.GetUriForFile(CrossCurrentActivity.Current.Activity, "com.mypackagename.fileprovider", path));

        CrossCurrentActivity.Current.Activity.StartActivity(Intent.CreateChooser(intent, "Share Image"));
    }
}
}

这是我用于 Android 实施的内容

 public Task Share(string url)
        {
            var path = Android.OS.Environment.GetExternalStoragePublicDirectory("Temp");

            if (!File.Exists(path.Path))
            {
                Directory.CreateDirectory(path.Path);
            }

            string absPath = path.Path + "tempfile.jpg";
            File.WriteAllBytes(absPath, GetBytes(url));

            var _context = Android.App.Application.Context;

            Intent sendIntent = new Intent(global::Android.Content.Intent.ActionSend);

            sendIntent.PutExtra(global::Android.Content.Intent.ExtraText, "Application Name");

            sendIntent.SetType("image/*");

            sendIntent.PutExtra(Intent.ExtraStream, Android.Net.Uri.Parse("file://" + absPath));
            _context.StartActivity(Intent.CreateChooser(sendIntent, "Sharing"));
            return Task.FromResult(0);
        }

        public static byte[] GetBytes(string url)
        {
            byte[] arry;
            using (var webClient = new WebClient())
            {
                arry = webClient.DownloadData(url);
            }
            return arry;
        }

作为我的targetSdkVersion >24,我在MainActivity.cs中添加如下两行,允许其他应用访问文件.

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.SetVmPolicy(builder.Build());

这里是 AndroidManifest.xml

中需要允许的权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />