首先在工程文件的 App.xaml.cs 文件中 重写 OnShareTargetActivated(ShareTargetActivatedEventArgs args) 方法 :
protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args){ var rootFrame = new Frame(); rootFrame.Navigate(typeof(MainPage), args.ShareOperation); Window.Current.Content = rootFrame; Window.Current.Activate();}
即当分享源把从分享面板启动该应用时,直接调转到 MainPage 页面进行处理。
其中 ShareTargetActivatedEventArgs 的类包含 :namespace Windows.ApplicationModel.Activation{ // 为共享操作的目标提供信息。 public sealed class ShareTargetActivatedEventArgs : IShareTargetActivatedEventArgs, IActivatedEventArgs { // 获取激活类型。 // 返回结果: 枚举值之一。 public ActivationKind Kind { get; } // 在应用程序激活前获取该应用程序的执行状态。 // 返回结果: 枚举值之一。 public ApplicationExecutionState PreviousExecutionState { get; } // 获取共享操作中所包含数据的相关信息。 // 返回结果: 包含纳入发送操作的数据的对象。 public ShareOperation ShareOperation { get; } // 获取提供有关从初始屏幕转换到激活的应用程序的信息的初始屏幕对象。 // 返回结果: 提供初始屏幕信息的对象。 public SplashScreen SplashScreen { get; } }
其中 ShareTargetActivatedEventArgs 类中的各个参数:
namespace Windows.ApplicationModel.Activation{ //指定激活的类型。 public enum ActivationKind { //用户启动该应用程序或点击该内容平铺。 Launch = 0, //用户要通过应用程序搜索。 Search = 1, //将应用程序激活作为共享操作的目标。 ShareTarget = 2, //应用程序启动此应用程序注册要处理的文件类型的文件。 File = 3, //应用程序启动此应用程序注册要处理的协议的 URL。 Protocol = 4, //用户要选择由应用程序提供的文件或文件夹。 FileOpenPicker = 5, //用户要保存文件并选择该应用程序作为位置。 FileSavePicker = 6, // 用户要保存应用程序为其提供内容管理的文件。 CachedFileUpdater = 7, // 用户要选择联系人。 ContactPicker = 8, //应用程序处理自动播放。 Device = 9, //应用程序处理打印任务。 PrintTaskSettings = 10, //应用程序从附加的照相机获取图片或视频。 CameraSettings = 11, }}
namespace Windows.ApplicationModel.Activation{ // 指定应用程序的当前执行状态。 public enum ApplicationExecutionState { //应用程序未运行。 NotRunning = 0, //应用程序正在运行。 Running = 1, //应用程序被挂起。 Suspended = 2, // 在应用程序挂起后终止其运行。 Terminated = 3, //用户已关闭应用程序。 ClosedByUser = 4, }}
namespace Windows.ApplicationModel.DataTransfer.ShareTarget{ // 在共享操作时处理大部分工作。这包括用户要共享的数据,设置或移除 QuickLinks 和通知有关操作状态的系统。 public sealed class ShareOperation { //包含具有用户想要分享的数据的 DataPackage 对象。 // 返回结果: 包含用户希望共享的数据。 public DataPackageView Data { get; } // 包含 QuickLink 的 ID 的字符串。 // 返回结果: QuickLink 的 ID。 public string QuickLinkId { get; } // 删除可供用户使用的 QuickLink 列表中的 QuickLink。 public void RemoveThisQuickLink(); //指定共享操作已完成。 public void ReportCompleted(); // 指定共享操作已完成。系统可保存为未来共享操作的快捷方式的 QuickLink 对象包括在内。 //quicklink: 系统会保存为未来共享操作的快捷方式的 QuickLink 对象。 public void ReportCompleted(QuickLink quicklink); // 指定应用程序已获取用户想要共享的内容。 public void ReportDataRetrieved(); // 指定在共享操作时发生的错误 // value: 指定错误消息。系统会为用户显示此消息。 public void ReportError(string value); // 指定应用程序已开始获取用户想要共享的内容。 public void ReportStarted(); // 指定应用程序已请求系统允许共享操作作为后台任务运行。 public void ReportSubmittedBackgroundTask(); }}
namespace Windows.ApplicationModel.Activation{ //为应用程序的初始屏幕提供关闭事件和屏幕位置信息。 public sealed class SplashScreen { // 相对于窗体的应用程序初始屏幕图像的坐标。 // 返回结果: 相对于窗体并且针对设备的点/英寸 (dpi) 的初始屏幕图像的坐标。 public Rect ImageLocation { get; } // 当关闭应用程序的初始屏幕时激发。 public event TypedEventHandlerDismissed; }}
MainPage 页面的 xaml :
ID: Title: Description: Resource Map: Long-running Share Support (Optional) 如果你的应用支持上传比较耗时的文件格式,比如图片或者视频,这个 API 是必须的。用户应该有权关闭你的应用并且在用户做其它事情是,在后台使上传操作继续执行。为了使取消操作工作正常,你需要向分享平台报告你完成了获得用户的输入。在你调用完着 API 后,用户可以返回到分享面板并且看到你的应用正在进行分享操作 这个 API 是可选的,用来帮助 windows 系统优化系统资源的使用率。当你的应用从 Data Package 对象中提取信息结束时,你应该通知用户当有必要时,为了回收系统资源 windows 可以暂停或者终止源应用程序 这个 API 是可选的,用来帮助 windows 系统优化系统资源的使用率。 如果你已经调用了 Windows Runtime Background Transfer 类去完成上传你的内容, 你应该通知用户。然后为了回收系统资源,windows 会终止你的应用 如果使用了这个 API,你应该在你调用完 ReportStarted 方法后调用它 如果你的应用在长时间在后台运行分享操作,并且最终失败了,你应该告诉用户失败的原因,并且告诉用户 怎样从错误中恢复操作。当用户返回到分享面板时,应该在进程列表中看到你的信息。如果你的应用 在前台可见,你应该从不调用 ReportError 方法 当你的应用成功完成分享操作时,应该报告成功完成。当报告完成时,你可以添加一个快速链接,从而用户可以重复这个经常 使用的分享方式。这个 API 使用于 快速分享 和 耗时较长的分享。 添加一个快速链接 (可选) Title: Icon:
分享功能启动 ShareTarget 时,应用跳转到 MainPage.xaml 页面,在页面的 OnNavigatedTo(NavigationEventArgs e) 方法中进行处理。
首先,在 C# 页面声明全局变量 :
ShareOperation shareOperation;private string sharedDataTitle;private string sharedDataDescription;private string shareQuickLinkId;private string sharedText;private Uri sharedUri;private IReadOnlyListsharedStorageItems;private string sharedCustomData;private string sharedHtmlFormat;private IReadOnlyDictionary sharedResourceMap;private IRandomAccessStreamReference sharedBitmapStreamRef;private IRandomAccessStreamReference sharedThumbnailStreamRef;private const string dataFormatName = "http://schema.org/Book";
页面的 OnNavigatedTo() 方法 :
protected override async void OnNavigatedTo(NavigationEventArgs e) { //建议从激活事件中只返回 ShareOperation 对象,从而尽可 //能快的操作,并且异步从分享源中获得分享的数据 this.shareOperation = (ShareOperation)e.Parameter; // 方法 : public TaskStartNew (Func function) : // 创建并启动 System.Threading.Tasks.Task{TResult}。 //function: 一个函数委托,可返回能够通过 System.Threading.Tasks.Task{TResult} 获得的将来结果。 //TResult : 可通过 System.Threading.Tasks.Task{TResult} 获得的结果的类型。 // 返回结果:已启动的 System.Threading.Tasks.Task{TResult}。 await Task.Factory.StartNew(async () => { //检索数据包中的属性 this.sharedDataTitle = this.shareOperation.Data.Properties.Title; this.sharedDataDescription = this.shareOperation.Data.Properties.Description; this.sharedThumbnailStreamRef = this.shareOperation.Data.Properties.Thumbnail; //包含 QuickLink 的 ID 的字符串。 this.shareQuickLinkId = this.shareOperation.QuickLinkId; //检索数据包内容 //Contains() : 检查是否 DataPackageView 包含特定数据格式 if (this.shareOperation.Data.Contains(StandardDataFormats.Uri)) { // 这些 GetUriAsync(), GetTextAsync(), GetStorageItemsAsync(), etc. APIs , 如果从源程序中检索数据错误时,将会抛出异常 //本示例仅仅把错误显示出来. //建议共享目标应用以友好的方式为特定的应用处理处理这些问题 try { //获取 DataPackageView 中包含的 URI this.sharedUri = await this.shareOperation.Data.GetUriAsync(); } catch (Exception ex) { NotifyUserBackgroundThread("Failed GetUriAsync - " + ex.Message, NotifyType.ErrorMessage); } } if (this.shareOperation.Data.Contains(StandardDataFormats.Text)) { try { //获取 DataPackageView 对象中的文本。 this.sharedText = await this.shareOperation.Data.GetTextAsync(); } catch (Exception ex) { NotifyUserBackgroundThread("Failed GetTextAsync - " + ex.Message, NotifyType.ErrorMessage); } } if (this.shareOperation.Data.Contains(StandardDataFormats.StorageItems)) { try { //获取 DataPackageView 对象中存储的文件和文件夹。 this.sharedStorageItems = await this.shareOperation.Data.GetStorageItemsAsync(); } catch (Exception ex) { NotifyUserBackgroundThread("Failed GetStorageItemsAsync - " + ex.Message, NotifyType.ErrorMessage); } } if (this.shareOperation.Data.Contains(dataFormatName)) { try { //获取 DataPackageView 对象中的文本. //此示例中 dataFormatName = "http://schema.org/Book", //在上一篇文章中(34、)中有此自定义格式 this.sharedCustomData = await this.shareOperation.Data.GetTextAsync(dataFormatName); } catch (Exception ex) { NotifyUserBackgroundThread("Failed GetTextAsync(" + dataFormatName + ") - " + ex.Message, NotifyType.ErrorMessage); } } if (this.shareOperation.Data.Contains(StandardDataFormats.Html)) { try { //获取 DataPackageView 对象中存储的 HTML。 this.sharedHtmlFormat = await this.shareOperation.Data.GetHtmlFormatAsync(); } catch (Exception ex) { NotifyUserBackgroundThread("Failed GetHtmlFormatAsync - " + ex.Message, NotifyType.ErrorMessage); } try { // 获取 HTML 内容中引用的数据(如图像)。 this.sharedResourceMap = await this.shareOperation.Data.GetResourceMapAsync(); } catch (Exception ex) { NotifyUserBackgroundThread("Failed GetResourceMapAsync - " + ex.Message, NotifyType.ErrorMessage); } } if (this.shareOperation.Data.Contains(StandardDataFormats.Bitmap)) { try { //设置 DataPackageView 中包含的位图图像 this.sharedBitmapStreamRef = await this.shareOperation.Data.GetBitmapAsync(); } catch (Exception ex) { NotifyUserBackgroundThread("Failed GetBitmapAsync - " + ex.Message, NotifyType.ErrorMessage); } } //在本示例中,我们只是把从分享源中获得的数据显示出来 //使用 dispatcher 方法返回到 UI 线程 await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { DataPackageTitle.Text = this.sharedDataTitle; DataPackageDescription.Text = this.sharedDataDescription; if (!String.IsNullOrEmpty(this.shareOperation.QuickLinkId)) { SelectedQuickLinkId.Text = this.shareQuickLinkId; } if (this.sharedThumbnailStreamRef != null) { // 打开一个进行随机访问的流。 //IRandomAccessStreamWithContentType : 支持随机访问指定的数据格式的输入和输出流中的数据。 IRandomAccessStreamWithContentType thumbnailStream = await this.sharedThumbnailStreamRef.OpenReadAsync(); BitmapImage bitmapImage = new BitmapImage(); bitmapImage.SetSource(thumbnailStream); ThumbnailHolder.Source = bitmapImage; ThumbnailArea.Visibility = Visibility.Visible; } if (this.sharedUri != null) { AddContentValue("Uri: ", this.sharedUri.AbsoluteUri); } if (this.sharedText != null) { AddContentValue("Text: ", this.sharedText); } if (this.sharedStorageItems != null) { // 显示将要被分享的文件的名称 StringBuilder fileNames = new StringBuilder(); for (int index = 0; index < this.sharedStorageItems.Count; index++) { fileNames.Append(this.sharedStorageItems[index].Name); if (index < this.sharedStorageItems.Count - 1) { fileNames.Append(", "); } } fileNames.Append("."); AddContentValue("StorageItems: ", fileNames.ToString()); } if (this.sharedCustomData != null) { //这是一个需要特别要小心的区域,从源应用程序解析数据时,避免缓冲区溢出。 //这个示例并不执行数据验证但将捕获抛出的任何异常。 try { StringBuilder receivedStrings = new StringBuilder(); // 将指定的 JSON 字符串分析成 JSON 值。 JsonObject customObject = JsonObject.Parse(this.sharedCustomData); if (customObject.ContainsKey("type")) { if (customObject["type"].GetString() == "http://schema.org/Book") { // 本示例解析的 Json 的格式类型为 : http://schema.org/Book receivedStrings.AppendLine("Type: " + customObject["type"].Stringify()); JsonObject properties = customObject["properties"].GetObject(); receivedStrings.AppendLine("Image: " + properties["image"].Stringify()); receivedStrings.AppendLine("Name: " + properties["name"].Stringify()); receivedStrings.AppendLine("Book Format: " + properties["bookFormat"].Stringify()); receivedStrings.AppendLine("Author: " + properties["author"].Stringify()); receivedStrings.AppendLine("Number of Pages: " + properties["numberOfPages"].Stringify()); receivedStrings.AppendLine("Publisher: " + properties["publisher"].Stringify()); receivedStrings.AppendLine("Date Published: " + properties["datePublished"].Stringify()); receivedStrings.AppendLine("In Language: " + properties["inLanguage"].Stringify()); receivedStrings.Append("ISBN: " + properties["isbn"].Stringify()); AddContentValue("Custom format data:" + Environment.NewLine, receivedStrings.ToString()); } else { NotifyUser("The custom format from the source app is not of type http://schema.org/Book", NotifyType.ErrorMessage); } } else { NotifyUser("The custom format from the source app doesn't contain a type", NotifyType.ErrorMessage); } } catch (Exception ex) { NotifyUser("Failed to parse the custom data - " + ex.Message, NotifyType.ErrorMessage); } } if (this.sharedHtmlFormat != null) { //获取代表 HTML 片段的字符串 。 string htmlFragment = HtmlFormatHelper.GetStaticFragment(this.sharedHtmlFormat); if (!String.IsNullOrEmpty(htmlFragment)) { AddContentValue("HTML: "); ShareWebView.Visibility = Visibility.Visible; ShareWebView.NavigateToString("" + htmlFragment + ""); } else { NotifyUser("GetStaticFragment failed to parse the HTML from the source app", NotifyType.ErrorMessage); } // 检查在资源映射表中是否有任何地方的图像。 if (this.sharedResourceMap.Count > 0) { ResourceMapValue.Text = ""; foreach (KeyValuePair item in this.sharedResourceMap) { ResourceMapValue.Text += "\nKey: " + item.Key; } ResourceMapArea.Visibility = Visibility.Visible; } } if (this.sharedBitmapStreamRef != null) { IRandomAccessStreamWithContentType bitmapStream = await this.sharedBitmapStreamRef.OpenReadAsync(); BitmapImage bitmapImage = new BitmapImage(); bitmapImage.SetSource(bitmapStream); ImageHolder.Source = bitmapImage; ImageArea.Visibility = Visibility.Visible; } }); }); }
页面中其它的辅助方法 :
private void QuickLinkSectionLabel_Tapped(object sender, TappedRoutedEventArgs e) { // Trigger the appropriate Checked/Unchecked event if the user taps on the text instead of the checkbox. AddQuickLink.IsChecked = !AddQuickLink.IsChecked; } private void AddQuickLink_Checked(object sender, RoutedEventArgs e) { QuickLinkCustomization.Visibility = Visibility.Visible; } private void AddQuickLink_Unchecked(object sender, RoutedEventArgs e) { QuickLinkCustomization.Visibility = Visibility.Collapsed; } async void ReportCompleted_Click(object sender, RoutedEventArgs e) { if (AddQuickLink.IsChecked.Equals(true)) { QuickLink quickLinkInfo = new QuickLink { Id = QuickLinkId.Text, Title = QuickLinkTitle.Text, // For QuickLinks, the supported FileTypes and DataFormats are set independently from the manifest. SupportedFileTypes = { "*" }, SupportedDataFormats = { StandardDataFormats.Text, StandardDataFormats.Uri, StandardDataFormats.Bitmap, StandardDataFormats.StorageItems, StandardDataFormats.Html, dataFormatName } }; try { StorageFile iconFile = await Package.Current.InstalledLocation.CreateFileAsync("assets\\user.png", CreationCollisionOption.OpenIfExists); quickLinkInfo.Thumbnail = RandomAccessStreamReference.CreateFromFile(iconFile); this.shareOperation.ReportCompleted(quickLinkInfo); } catch (Exception) { // Even if the QuickLink cannot be created it is important to call ReportCompleted. Otherwise, // if this is a long-running share, // the app will stick around in the long-running share progress list. this.shareOperation.ReportCompleted(); throw; } } else { this.shareOperation.ReportCompleted(); } } private void LongRunningShareLabel_Tapped(object sender, TappedRoutedEventArgs e) { // Trigger the appropriate Checked/Unchecked event if the user taps on the text instead of the checkbox. ExpandLongRunningShareSection.IsChecked = !ExpandLongRunningShareSection.IsChecked; } private void ExpandLongRunningShareSection_Checked(object sender, RoutedEventArgs e) { ExtendedSharingArea.Visibility = Visibility.Visible; } private void ExpandLongRunningShareSection_Unchecked(object sender, RoutedEventArgs e) { ExtendedSharingArea.Visibility = Visibility.Collapsed; } private void ReportStarted_Click(object sender, RoutedEventArgs e) { this.shareOperation.ReportStarted(); this.NotifyUser("Started...", NotifyType.StatusMessage); } private void ReportDataRetrieved_Click(object sender, RoutedEventArgs e) { this.shareOperation.ReportDataRetrieved(); this.NotifyUser("Data retrieved...", NotifyType.StatusMessage); } private void ReportSubmittedBackgroundTask_Click(object sender, RoutedEventArgs e) { this.shareOperation.ReportSubmittedBackgroundTask(); this.NotifyUser("Submitted background task...", NotifyType.StatusMessage); } private void ReportErrorButton_Click(object sender, RoutedEventArgs e) { this.shareOperation.ReportError(ReportError.Text); } async private void Footer_Click(object sender, RoutedEventArgs e) { await Windows.System.Launcher.LaunchUriAsync(new Uri(((HyperlinkButton)sender).Tag.ToString())); } private void NotifyUser(string strMessage, NotifyType type) { switch (type) { // Use the status message style. case NotifyType.StatusMessage: StatusBlock.Style = Resources["StatusStyle"] as Style; break; // Use the error message style. case NotifyType.ErrorMessage: StatusBlock.Style = Resources["ErrorStyle"] as Style; break; } StatusBlock.Text = strMessage; } async private void NotifyUserBackgroundThread(string message, NotifyType type) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { NotifyUser(message, type); }); } private void AddContentValue(string title, string description = null) { Run contentType = new Run(); contentType.FontWeight = FontWeights.Bold; contentType.Text = title; ContentValue.Inlines.Add(contentType); if (description != null) { Run contentValue = new Run(); contentValue.Text = description + Environment.NewLine; ContentValue.Inlines.Add(contentValue); } } } public enum NotifyType { StatusMessage, ErrorMessage };
运行上一篇(33、)中的分享源示例,选择分享图片,从电脑上选择完图片后,点击
“Share” 按钮,然后从分享面板的列表中选择本示例 (ShareTarget):