Home > Back-end >  Xamarin.Form Share of Essentials image with URL to send both at the same time
Xamarin.Form Share of Essentials image with URL to send both at the same time

Time:09-17

I want to share the URL with the file and the message.

However, it seems that only one of the two can be shared using Share of Essentials.

I can implement both, but I don't know how to send both at the same time.

So I proceeded with the customization as follows.

Xamarin.From

public interface IShare
    {
        void Share(string subject, string message, byte[] image);
    }

private async void Button_Clicked(object sender, EventArgs e)
        {
            var imageStream = await ScreenShot.CaptureImageAsync();

            DependencyService.Get<IShare>().Share(" ", "Hello - https://www.naver.com/", GetImageBytes(imageStream));

        }

private byte[] GetImageBytes(Stream stream)
            {
                byte[] ImageBytes;
                using (var memoryStream = new System.IO.MemoryStream())
                {
                    stream.CopyTo(memoryStream);
                    ImageBytes = memoryStream.ToArray();
                }
                return ImageBytes;
            }

Android Code

public void Share(string subject, string message, byte[] image)
{
    ShareMultipleFilesRequest(message,image);
}

static Task ShareMultipleFilesRequest(string message, byte[] image)
{
    var intent = new Intent(Intent.ActionSend);

    intent.PutExtra(Intent.ExtraText, message);

    intent.SetType("image/png");
    intent.SetFlags(ActivityFlags.GrantReadUriPermission);

    string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
    string filename = System.IO.Path.Combine(path, "CaptureScreen.png");

    System.IO.File.WriteAllBytes(filename, image);

    Java.IO.File sharedFile;

    sharedFile = new Java.IO.File(filename);

    System.Console.WriteLine($"{sharedFile.IsAbsolute}");

    intent.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(new Java.IO.File(sharedFile.AbsolutePath)));

    intent.PutExtra(Intent.ExtraTitle, "Share Image");

    var chooserIntent = Intent.CreateChooser(intent, "Share Image" ?? string.Empty);

    var flags = ActivityFlags.ClearTop | ActivityFlags.NewTask;

    chooserIntent.SetFlags(flags);

    Xamarin.Essentials.Platform.AppContext.StartActivity(chooserIntent);

    return Task.CompletedTask;
}

iOS Code

 public void Share(string subject, string message, byte[] image)
        {

            var chartImage = new UIImage(NSData.FromArray(image));
            var mess = NSObject.FromObject(message);

            var activityItems = new[] { mess, chartImage };
            var activityController = new UIActivityViewController(activityItems, null);

            var topController = UIApplication.SharedApplication.KeyWindow.RootViewController;

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

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

But Android Messages are shared. But the image is not shared. May I know what is the problem? Or do I know how to send both at the same time.

CodePudding user response:

If you are using Android 7.0 or above,you should use FileProvider to deal with your uri.

add provider into your manifest:

<application ...>
  <provider
       android:name="androidx.core.content.FileProvider"
       android:authorities="${applicationId}.provider"
       android:exported="false"
       android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
  </provider>
</application>

and add the provider_paths.xml into Resoures/xml:

<?xml version="1.0" encoding="utf-8" ?>
<paths>
  <files-path
      name="files-path"
      path="." />
  <cache-path
      name="cache-path"
      path="." />
  <external-path
      name="external_storage_root"
      path="." />
  <external-files-path
      name="external_file_path"
      path="." />
  <external-cache-path
      name="external_cache_path"
      path="." />
  <root-path
      name="root-path"
      path="" />
</paths>

and share method in android project:

 private Task ShareMultipleFilesRequest(string message, byte[] image)
    {
        var intent = new Intent(Intent.ActionSend);

        intent.PutExtra(Intent.ExtraText, message);

        intent.SetType("image/png");
        intent.SetFlags(ActivityFlags.GrantReadUriPermission);

        string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
        string filename = System.IO.Path.Combine(path, "CaptureScreen.png");

        System.IO.File.WriteAllBytes(filename, image);

        Java.IO.File sharedFile;

        sharedFile = new Java.IO.File(filename);

        System.Console.WriteLine($"{sharedFile.IsAbsolute}");

        intent.PutExtra(Intent.ExtraStream, FileProvider.GetUriForFile(Xamarin.Essentials.Platform.AppContext, Xamarin.Essentials.Platform.AppContext.PackageName   ".provider", sharedFile));

        intent.PutExtra(Intent.ExtraTitle, "Share Image");

        var chooserIntent = Intent.CreateChooser(intent, "Share Image" ?? string.Empty);

        var flags = ActivityFlags.ClearTop | ActivityFlags.NewTask;

        chooserIntent.SetFlags(flags);

        Xamarin.Essentials.Platform.AppContext.StartActivity(chooserIntent);

        return Task.CompletedTask;
    }

and in your Activity,you could receive the message and uri like:

Note:here i set the Acitivity attribute LaunchMode =Android.Content.PM.LaunchMode.SingleTask,then overwrite the OnNewIntent method to receive the share content.

protected override void OnNewIntent(Intent intent)
    {
        base.OnNewIntent(intent);
        if (intent != null)
        {
            string message = intent.GetStringExtra(Intent.ExtraText);
            var uri = intent.GetParcelableExtra(Intent.ExtraStream);
        }
    }
  • Related