Issue
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.
Solution
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);
}
}
Answered By - Leo Zhu - MSFT
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.