Xamarin.Form 与 URL 共享 Essentials 图片以同时发送
Xamarin.Form Share of Essentials image with URL to send both at the same time
我想与文件和消息共享URL。
不过,似乎只能使用 Share of Essentials 来共享两者之一。
我可以实现两者,但我不知道如何同时发送。
所以我进行了如下定制。
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代码
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代码
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, () => { });
}
但是Android 消息是共享的。但图像不共享。我可以知道是什么问题吗?还是我知道如何同时发送。
如果您使用 Android 7.0 或更高版本,您应该使用 FileProvider 来处理您的 uri。
将 provider
添加到您的 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>
并将provider_paths.xml添加到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>
并在android项目中分享方法:
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;
}
并且在您的 Activity 中,您可以收到如下消息和 uri:
注意:这里我设置了Acitivity属性LaunchMode =Android.Content.PM.LaunchMode.SingleTask
,然后覆盖OnNewIntent接收分享内容的方法
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
if (intent != null)
{
string message = intent.GetStringExtra(Intent.ExtraText);
var uri = intent.GetParcelableExtra(Intent.ExtraStream);
}
}
我想与文件和消息共享URL。
不过,似乎只能使用 Share of Essentials 来共享两者之一。
我可以实现两者,但我不知道如何同时发送。
所以我进行了如下定制。
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代码
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代码
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, () => { });
}
但是Android 消息是共享的。但图像不共享。我可以知道是什么问题吗?还是我知道如何同时发送。
如果您使用 Android 7.0 或更高版本,您应该使用 FileProvider 来处理您的 uri。
将 provider
添加到您的 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>
并将provider_paths.xml添加到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>
并在android项目中分享方法:
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;
}
并且在您的 Activity 中,您可以收到如下消息和 uri:
注意:这里我设置了Acitivity属性LaunchMode =Android.Content.PM.LaunchMode.SingleTask
,然后覆盖OnNewIntent接收分享内容的方法
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
if (intent != null)
{
string message = intent.GetStringExtra(Intent.ExtraText);
var uri = intent.GetParcelableExtra(Intent.ExtraStream);
}
}