Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing an image using Xamarin Forms

I’ve created a Xamarin Forms (PCL) solution, and I’m focusing on the Android project at the moment. I’m trying to implement image sharing using a dependency service. The images are located in the drawable folder of the Android project. However, every time I run the code below, the app crashes with: an unhandled exception occurred. I've checked the output log but nothing stands out. Would anyone be able to run an eye over my code and tell me if there is an error in it?

Many thanks

Interface:

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

Xaml:

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

Code-Behind:

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

ShareClass (in Android project):

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

        }
    }
}
like image 571
hlbmallo Avatar asked May 28 '17 17:05

hlbmallo


2 Answers

You first need to add permissions in the 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, () => { });
        }
    }
}
like image 161
Venkata Swamy Balaraju Avatar answered Oct 18 '22 20:10

Venkata Swamy Balaraju


Here is what I use for Android Implementation

 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;
        }

As my targetSdkVersion >24, I add the following two lines to MainActivity.cs to allow other apps to access files.

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

And here are the permissions required to be allowed in 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" />
like image 2
HarshitGindra Avatar answered Oct 18 '22 18:10

HarshitGindra