【问题标题】:Sharing an image using Xamarin Forms使用 Xamarin 表单共享图像
【发布时间】:2017-05-28 17:20:50
【问题描述】:

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

非常感谢

界面:

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"));

        }
    }
}

【问题讨论】:

  • 您是否在调试器中单步执行代码以确定导致崩溃的行?
  • @Jason 没有具体做过,但我尝试注释掉 ShareClass.cs 中的 using 语句。当我这样做时,共享 UI 弹出,图像可以共享到其他应用程序,如 OneDrive(但是,图像无法在 OneDrive 中打开,可能是因为它没有正确压缩?)。基于此,我怀疑是 using 语句导致了问题。
  • 那么你有没有尝试将它包装在 try/catch 中以捕获异常?
  • 是的,try/catch 确认问题出在 using 语句上。您认为这可能与 ShareClass.cs 中 System.IO 和 Java.IO 的混合有关吗?除此之外,我完全没有想法,不知道如何解决这个问题。
  • 你得到了什么异常?

标签: android xamarin.forms share


【解决方案1】:

您首先需要在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, () => { });
        }
    }
}

【讨论】:

  • 感谢@Venkata Swamy Balaraju 的帮助,但我忘了说我已经在我的原始帖子中添加了 AndroidManifest.xml 的权限。不幸的是,我仍然遇到同样的异常。
  • ios 9.3.5 = crash: *** 由于未捕获的异常 'NSGenericException' 导致应用程序终止,原因:'UIPopoverPresentationController (<_uialertcontrolleractionsheetregularpresentationcontroller:>) 之前应该有一个非零的 sourceView 或 barButtonItem演示发生。'
【解决方案2】:

这是我用于 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" />

【讨论】:

    【解决方案3】:

    这是我用于 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"));
        }
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-13
      • 2020-11-16
      相关资源
      最近更新 更多