Контракты
Операции, выполняемые длительное время
Когда вы запустите пример реализации целевого приложение и нажмете на чудо-кнопку Общий доступ, находясь в подходящем приложении-источнике данных, внизу будет небольшой разворачиваемый элемент, подписанный как "Поддержка общего доступа, требующего большого количества времени" ("Long-running Share Support"). Если вы развернете этот элемент, вы увидите некоторые дополнительные элементы управления и много описаний, как показано на рис. 1.6. Кнопки, показанные здесь, связаны с другими методами объекта ShareOperation наряду с reportCompleted. Это помогает Windows точно понять, как операция общего доступа обрабатывается внутри целевого приложения: reportStarted, reportDataRetrieved, reportSubmittedBackgroundTask, и reportError. Как вы можете видеть из рис. 1.6, это имеет отношение к тому, чтобы сообщить Windows, когда приложение закончит, так сказать, готовить обед, и система может вымыть посуду и убраться на кухне.
- reportStarted сообщает Windows, что ваша операция общего доступа может занять некоторое время, как в случае, если вы отправляете данные из пакета в другое место, или просто отправляете в виде вложения электронной почты большие изображения и тому подобное. Этот метод показывает, что вы приняли весь необходимый ввод пользователя и что панель общего доступа может быть закрыта.
- reportDataRetrieved сообщает Windows, что вы извлекли из пакета данных все, что вам нужно, и он, таким образом, может быть освобожден. Если вы, например, вызывали MSApp.createBlobFromRandomAccessStream для потока изображения, полученный большой двоичный объект теперь содержит копию изображения, которая является локальной для целевого приложения. Если вы используете изображения из свойства пакета resourceMap, с другой стороны, вам не нужно вызывать reportDataRetrieved до тех пор, пока вы явным образом не сделаете копию данных, на которые ссылаются URI внутри пакета данных. В любом случае, если вам нужно сохранять пакет в течение всей операции, вам не нужно вызывать этот метод, так как позже вы вызовете reportCompleted для освобождения пакета.
- reportSubmittedBackgroundTask говорит Windows о том, что вы начали фоновую передачу данных с использованием класса Windows.Networking.BackgroundTransfer.BackgroundUploader (http://msdn.microsoft.com/library/windows/apps/windows.networking.backgroundtransfer.backgrounduploader.aspx). Как следует из описания, приведенного на рис. 12.6., это позволяет Windows знать, что она может приостановить целевое приложение и не беспокоиться об операции общего доступа. Если вы вызываете этот метод, работая с локальной копией данных для загрузки, пройдите дальше и вызовите метод reportCompleted, таким образом Windows сможет освободить пакет. В противном случае дождитесь окончания передачи данных.
- reportError позволяет Windows узнать, не произошла ли ошибка в течение операции общего доступа.
Рис. 1.6. Развернутое окно, демонстрирующее поддержку общего доступа, требующего большого количества времени, в примере целевого приложения. Кнопка Repopt Completed (Сообщить о завершении) отображается всегда и не является специфической для подобных операций, несмотря на ее расположение в пользовательском интерфейсе примера. Не позвольте этому вас запутать!
Быстрые ссылки
Последний аспект контракта Общий доступ, который нам осталось изучить, это то, о чем мы уже упоминали раньше: быстрые ссылки (quicklinks). Они служат для более рациональной реализации операций общего доступа, таким образом, что пользователям не нужно повторно вводить информацию в целевые приложения. Например, если пользователь часто передает данные конкретным людям по электронной почте, каждый контакт может выступать в роли быстрой ссылки для приложения электронной почты. Если пользователь обычно отправляет данные разным людям или группам людей посредством приложения для работы с социальными сетями, эти люди, или группы, так же могут быть представлены в виде быстрых ссылок. И, так как эти целевые объекты более специфичны для конкретного пользователя, чем обычные цели общего доступа, пользовательский интерфейс чудо-кнопки Общий доступ выводит их в верхней части списка (рис. 1.7).
Каждая быстрая ссылка связана с конкретным целевым приложением и обслуживается им, просто предоставляя идентификатор для этого целевого приложения. Когда целевое приложение активируется посредством быстрой ссылки, оно использует идентификатор для получения данных, связанных с данной быстрой ссылкой и осуществляет предварительное заполнение или иную настройку пользовательского интерфейса. Важно понимать, что быстрые ссылки содержат только идентификатор, таким образом, целевое приложение должно хранить и получать связанные с ним данные из каких-то других источников, обычно из локальных данных приложения, где идентификатор является именем файла, именем контейнера параметров и так далее. Целевое приложение может так же использовать для этой цели перемещаемые данные приложения или облачные данные, но сами быстрые ссылки не перемещаются на другие устройства – они ограничены локальным использованием. Таким образом, имеет смысл хранить связанные с ними данными локально.
Сами по себе быстрые ссылки – это лишь экземпляры класса Windows.ApplicationModel.DataTransfer.Quicklink (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.quicklink.aspx). Их создают с помощью оператора new и затем заполняют их свойства title, thumbnail, supportedDataFormats, supportedFileTypes, и id. Форматы данных и типы файлов – это то, что Windows использует для того, чтобы определить, следует ли показывать конкретные быстрые ссылки в списке целевых объектов для данных, предоставляемых в общий доступ из приложения-источника (независимо от объявлений в манифесте). Свойства title и thumbnail используются для отображения быстрых ссылок в интерфейсе чудо-кнопки Общий доступ, id – это то, что передается целевому приложению при выборе быстрой ссылки.
Совет. Для эскизов (thumbnail), используйте изображение, которое способно точно представить быструю ссылку (например, фотографию из контакта), вместо изображения, соответствующего целевому приложению. Это помогает отличить быструю ссылку от общего элемента для вызова целевого приложения.
Затем приложение регистрирует быструю ссылку в системе, передавая ее методу ShareOperation.reportCompleted. Так как это единственный способ регистрации быстрых ссылок, это говорит нам о том, что создание быстрой ссылки всегда происходит как часть другой операции общего доступа. Это способо создания конкретных целей, которые могут сберечь пользователю немного времени и вдохновить его на использование вашего целевого приложения снова в будущем.
Посмотрим, как все это работает в примере целевого приложения для общего доступа. Для начала, когда вы активируете чудо-кнопку Общий доступ и выбираете приложение-пример, вы увидите, что оно предоставляет флаг для создания быстрой ссылки (рис. 1.7). Когда вы устанавливаете этот флаг, он предоставляет поля, в которые вы можете ввести идентификатор (id) и заголовок (title) (эскиз (thumbnail) просто использует приложение по умолчанию). Когда вы нажимаете на кнопку Report completed (Сообщить о завершении), вызывается метод reportCompleted и быстрая ссылка регистрируется в системе. При последующих обращениях к чудо-кнопке Общий доступ, при наличии у приложения-источника подходящих данных, эта быстрая ссылка появится в списке, как показано на рис. 1.8, а название приложения, обслуживающего быструю ссылку всегда отображается под заданным заголовком быстрой ссылки.
Рис. 1.7. Элементы управления для создания быстрой ссылки в примере целевого приложения для общего доступа
Рис. 1.8. Быстрая ссылка для приложения из примера целевого приложения для общего доступа появляется в списке целевых объектов чудо-кнопки Общий доступ
Вот как в этом примере создается быстрая ссылка в функции reportCompleted (js/target.js), которая связана с кнопкой Report completed (Сообщить о завершении) (некоторые проверки ошибок опущены):
if (addQuickLink) { var quickLink = new Windows.ApplicationModel.DataTransfer.ShareTarget.QuickLink(); var quickLinkId = document.getElementById("quickLinkId").value; quickLink.id = quickLinkId; var quickLinkTitle = document.getElementById("quickLinkTitle").value; quickLink.title = quickLinkTitle; // Для быстрых ссылок поддерживаемые типы файлов (FileTypes) и форматы данных (DataFormats) задаются независимо // от манифеста var dataFormats = Windows.ApplicationModel.DataTransfer.StandardDataFormats; quickLink.supportedFileTypes.replaceAll(["*"]); quickLink.supportedDataFormats.replaceAll([dataFormats.text, dataFormats.uri, dataFormats.bitmap, dataFormats.storageItems, dataFormats.html, customFormatName]); // Подготавливаем значок для QuickLink Windows.ApplicationModel.Package.current.installedLocation.getFileAsync( "images\\user.png").done(function (iconFile) { quickLink.thumbnail = Windows.Storage.Streams.RandomAccessStreamReference .createFromFile(iconFile); shareOperation.reportCompleted(quickLink); });
Опять же, здесь лишь создается объект QuickLink, устанавливаются его свойства (возможно, более точно передающий его смысл эскиз, такой, как изображение из контактных сведений), и он передается в reportCompleted. В примере целевого приложения вы можете заметить, что для быстрой ссылки не хранятся локальные данные, в данном случае достаточно свойств самой быстрой ссылки. Большинство целевых приложений, однако, скорее всего будут хранить некоторые данные для быстрой ссылки, связанные с ее свойством quicklink.id и загружающие данные, когда приложение активировано посредством быстрой ссылки.
Когда приложение активируется таким способом, объект eventArgs.detail.shareOperation в обработчике события активации будет содержать quicklinkId. Целевое приложение из примера просто отображает этот идентификатор, однако, на практике его обычно используют для загрузки данных приложения и предварительного заполнения пользовательского интерфейса:
// Если приложение было активировано через быструю ссылку, QuickLink, показать QuickLinkId if (shareOperation.quickLinkId !== "") { document.getElementById("selectedQuickLinkId").innerText = shareOperation.quickLinkId; document.getElementById("quickLinkArea").className = "hidden"; }
Обратите внимание на то, что когда приложение активируется с помощью быстрой ссылки, оно не отображает интерфейс для создания быстрой ссылки, так как подобные действия избыточны. Однако, если пользователь нуждается в редактировании информации, связанной с быстрой ссылкой, вы можете предоставить ему возможность обновлять быструю ссылку, что означает обновление данных, которые вы сохранили с соответствующим идентификатором, или создание новой быстрой ссылки с новым идентификатором.
Буфер обмена
Еще до того, как был придуман контракт Общий доступ, механизм, который мы знакм как буфер обмена (clipboard) представлял собой яркий пример средства для организации обмена данными между приложениями. И хотя сегодня он не может привлечь к себе большого внимания, он по-прежнему остается проверенным и надежным средством для обмена данными.
Для приложений Магазина Windows взаимодействие с буфером обмена построено на том же самом механизме DataPackage, который мы уже видели в применении его к механизму общего доступа. Поэтому все, что мы узнали о заполнении этого пакета, об использовании пользовательских форматов, об использовании отложенного рендеринга применимо и к буферу обмена. В самом деле, если вы делаете данные доступными в буфере обмена, вам следует убедиться, что те же данные доступны для контракта Общий доступ!
Вопрос заключается в том, как подключить команды, наподобие команд Копировать, Вырезать, Вставить, из панели приложения, контекстного меню или инициированные сочетаниями клавиш, которые приложению следует предоставить для собственного содержимого (многие элементы управления автоматически работают с буфером обмена). Для этих целей мы можем обратиться к классу Windows.ApplicationMode.DataTransfer.Clipboard (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.datatransfer.clipboard.aspx).
Как показано в примере "Буфер обмена" (http://code.msdn.microsoft.com/windowsapps/Clipboard-App-sample-309ec122), этот процесс достаточно прост. В частности, для копирования и вырезания:
- Создайте новый Windows.ApplicationModel.DataTransfer.DataPackage (или используйте MSApp.createDataPackage или MSApp.createDataPackageFromSelection), и заполните его нужными данными.
var dataPackage = new Windows.ApplicationModel.DataTransfer.DataPackage(); dataPackage.setText(textValue); //...
- (Не обязательно) установите свойство пакета requestedOperation в значение из DataPackageOperation (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.datatransfer.datapackageoperation.aspx): copy, move , link, или none (последнее используется для отложенного рендеринга). Отметим, что эти значения можно комбинировать, используя побитовый оператор ИЛИ. Например:
var dpo = Windows.ApplicationModel.DataTransfer.DataPackageOperation; dataPackage.requestedOperation = dpo.copy | dpo.move | dpo.link;
- Передайте пакет данных Windows.ApplicationMode.DataTransfer.Clipboard.setContent:
Windows.ApplicationModel.DataTransfer.Clipboard.setContent(dataPackage);
Для выполнения операции вставки:
-
Вызовите Windows.ApplicationMode.DataTransfer.Clipboard.getContent для получения пакета данных только для чтения, который называется DataPackageView (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.datatransfer.datapackageview.aspx):
var dataView = Windows.ApplicationModel.DataTransfer.Clipboard.getContent();
- Проверьте, с помощью метода contains, содержит ли он форматы, которые вы можете принять (в качестве альтернативы, вы можете проверить содержимое вектора availableFormats):
if (dataView.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats. text)) { //... }
- Получите данные, используя методы get*, такие, как getTextAsync, getBitmapAsync, и getDataAsync (для пользовательских форматов). Вставляя HTML вы так же можете использовать метод getResourceMapAsync для получения URI ресурсов. Свойства представления, наподобие thumbnail, так же полезны, как и значение или значения requestedOperation.
dataView.getTextAsync().done(function (text) { // Принимаем данные }
Если вы, в любое время, захотите очистить содержимое буфера обмена, воспользуйтесь методом clear класса Clipboard. Так же вы можете убедиться в том, что данные доступны другим приложениям даже при закрытии вашего приложения, вызвав метод flush (он инициирует любые операции отложенного рендеринга, которые вы предусмотрели).
Приложения, которые используют буфер обмена, так же нуждаются в информации о том, когда нужно активировать или деактивировать команду вставки в зависимости от доступных форматов. В любое время вы можете получить отображение пакета данных из буфера обмена и использовать его метод contains или свойство availableFormats и принять соответствующее решение. Так же вам следует прослушивать событие contentChanged (это событие WinRT) объекта Clipboard, которое будет выполнено, когда ваше приложение, или какое-то другое приложение, вызовет метод setContetn буфера обмена. Во время, заданное параметром time, вы активируете или деактивируете команды. Конечно, вы не будете принимать эти события, если ваше приложение приостановлено, поэтому, если вы хотите обновить сведения о состоянии этих команд, выполните это в обработчике возобновления работы.
Пример работы с буфером обмена предоставляет примеры этих сценариев, в том числе, копирование и вставку текста и HTML (Сценарий 1); копирование и вставку изображения (Сценарий 2); копирование и вставу файлов (Сценарий 3); и очистку буфера обмена, перечисление форматов и обработку contentChanged (Сценарий 4).
Отменим, в итоге, что данные, которые могут быть вставлены, могут поступить откуда угодно. Приложениям, которые могут принимать данные из буфера обмена, следует, как и целевым приложениям в операциях общего доступа к данным, рассматривать полученное содержимое как потенциально опасное и предпринимать необходимые меры.