Я делаю последние штрихи к приложению, которое пишу на основе Bing Maps / TomTom Starter Kit, который я опубликовал несколько недель назад. В этом приложении вы можете просматривать текущее изображение с любой из 13 000 камер наблюдения в США и Канаде, но сам Starter Kit предназначен для отображения практически любого типа данных, имеющих компонент широты и долготы.
Когда я начал задумываться о том, как улучшить возможности этого набора для начинающих, идея интеграции контракта на совместное использование выглядела как легкая задача: найти друга, супруга или другого существа, готового отправиться в путь? Выполните поиск местоположения (Starter Kit уже реализует контракт на поиск), найдите камеру или камеры в их маршруте и отправьте быстрое электронное письмо со снимком трафика, с которым они могут столкнуться — что-то вроде этого:
Совместное использование является довольно мощным способом повысить эффективность вашего приложения (и тем самым привлечь больше пользователей), и на самом деле довольно просто интегрировать его в любое приложение. Вот что я должен был сделать с Starter Kit (подробности коммитов на GitHub вы найдете для подробностей):
- Определите обратный вызов, чтобы ответить на запрос обмена.
- Подключите обратный вызов к событию DataRequested, которое Windows 8 инициирует при запросе общего доступа к приложению.
- Контрольная работа! (здесь я приведу несколько советов, чтобы сэкономить время — надеюсь!)
Определите обратный вызов для ответа на запрос на обмен
Я добавил код, который следует в LeftPanel.xaml.cs, поскольку этот элемент управления содержит данные, которыми я хочу поделиться — изображение. Тем не менее, данные на самом деле являются частью ViewModel для всей страницы, поэтому я мог бы включить их туда.
Вот код, за которым следует более или менее построчное описание:
public async void GetSharedData(DataTransferManager sender, DataRequestedEventArgs args) { try { var currentCam = MappableListView.SelectedItem as APIMASH_TomTom.TomTomCameraViewModel; if (currentCam != null) { DataRequestDeferral deferral = args.Request.GetDeferral(); args.Request.Data.Properties.Title = String.Format("TomTom Camera: {0}", currentCam.CameraId); args.Request.Data.Properties.Description = currentCam.Name; // share a file var file = await StorageFile.CreateStreamedFileAsync( String.Format("{0}_{1}.jpg", currentCam.CameraId, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")), async stream => { await stream.WriteAsync(currentCam.ImageBytes.AsBuffer()); await stream.FlushAsync(); stream.Dispose(); }, null); args.Request.Data.SetStorageItems(new List<IStorageItem> { file }); // share as bitmap InMemoryRandomAccessStream raStream = new InMemoryRandomAccessStream(); await raStream.WriteAsync(currentCam.ImageBytes.AsBuffer()); await raStream.FlushAsync(); args.Request.Data.SetBitmap( RandomAccessStreamReference.CreateFromStream(raStream)); deferral.Complete(); } else { args.Request.FailWithDisplayText("Select a camera to share its image."); } } catch (Exception ex) { args.Request.FailWithDisplayText(ex.Message); } }
Строка 1 | Подпись здесь — это подпись события DataRequested, которая будет размещена на главной странице. |
Линии 5-6 | Это приложение показывает только изображение с камеры, поэтому, если оно не отображается в данный момент, пользователь просто увидит стандартное сообщение о том, что ему нечего делиться, и текст в строке 36. |
Линия 9 | Поскольку в последующей реализации есть некоторая дополнительная асинхронная работа, отсрочку получают и затем помечают как завершенную (строка 32), когда работа завершена. |
Линии 11 — 12 | Эти строки задают текст, который вы увидите в чудо-кнопке «Поделиться» при первом запуске, и ниже будут перечислены приложения, способные обрабатывать форматы данных, которыми это приложение делится. Название требуется; если он не указан, вы увидите довольно общее сообщение: «Произошла проблема с данными из…». |
Линии 14 — 23 | Этот раздел довольно тупого кода на самом деле имеет мало общего с самим общим доступом, но необходим для преобразования данных изображения из байтового массива (в ViewModel) в IStorageItem, чтобы его можно было передавать другим приложениям, которые могут поделиться этим тип контента. |
Линия 24 | Одним из типов данных, которыми вы можете поделиться, является файл, и вот код, который предоставляет файл (в данном случае растровое изображение) другим приложениям, которые способны получать файл или файлы в рамках контракта на совместное использование. , |
Линии 27 — 29 | Этот код в некоторой степени аналогичен строкам 14-23, за исключением того, что здесь цель состоит в том, чтобы преобразовать необработанные байты изображения в RandomAccessStreamReference , который необходим методу SetBitmap для совместного использования тех же данных, что и изображение (по сравнению с файлом). |
Линия 30 | Здесь то же самое изображение является растровым. Совместное использование в нескольких форматах дает вам возможность обратиться к большему количеству приложений, поскольку некоторые могут принять один формат, но не другой. |
Строка 32 | Теперь, когда обработка завершена, завершите отсрочку. |
Линия 36 | Как упоминалось ранее, это всего лишь подсказка для тех, кто пытается поделиться, когда нет выбранной камеры. Без этого возможности поиска менее обнаружимы. |
Строка 41 | Если что-то действительно плохое происходит, вы можете предоставить небольшую диагностическую помощь или дальнейшие указания в тексте, который появляется во всплывающей подсказке. |
Это покрывает фактический обмен данными — сложная часть. Все, что осталось, это подключить этот обратный вызов, чтобы он срабатывал при каждом запросе на обмен.
Подключите обратный вызов к событию DataRequested
DataTransferManager dtm = DataTransferManager.GetForCurrentView(); dtm.DataRequested += LeftPanel.GetSharedData;
Да, вот и все; ДВА строки кода. Один, который захватывает ссылку на DataTransferManager, а другой — для установки обратного вызова, используемого при запросе данных. Этот обратный вызов, конечно, является кодом, обсужденным выше.
Сложность здесь не в коде, а в том, где его разместить. DataTransferManger является применение в масштабах, и может быть только один обработчик событий прилагаются. Теперь, если приложение собирается использовать одну и ту же вещь независимо от того, где в приложении перемещался пользователь, вы можете настроить этот обратный вызов в объекте приложения или, возможно, в конструкторе страницы. В этом случае, однако, я не думаю, что имеет смысл пытаться делиться с экрана результатов поиска, так как контент, которым нужно делиться (изображение с камеры), не был логически доступен в этом контексте.
Вместо этого эти две строки кода появляются в событии OnNavigatedTo файла MainPage.xaml.cs, и есть аналогичный кодовый куплет, который отключает обработчик события в событии OnNavigatedFrom . Это освобождает меня от необходимости предоставлять различные реализации общего доступа для разных страниц приложения.
На самом деле, вы можете захотеть предоставить реализацию страницы результатов поиска самостоятельно, даже если вы ничего от нее не поделитесь. Если вы попробуете код, вы заметите, что запрос на обмен, инициированный в то время, когда вы находитесь на странице результатов поиска, указывает «Это приложение не может поделиться». Ну, это не совсем так, но это происходит потому, что нет обратного вызова DataRequested . Добавляя тот, который просто вызывает FailWithDisplayText, вы можете предоставить более полезное сообщение пользователю.
Контрольная работа! (и несколько извлеченных уроков).
- Я часто использую симулятор Visual Studio для тестирования своих приложений, и мне потребовалось некоторое время, чтобы понять, что почтовое приложение Windows 8 не играет хорошей роли в качестве общего ресурса в симуляторе. Конечно, это одно из первых приложений, которое вы можете попробовать! Если вы получаете о-о-очень полезное сообщение «Что-то пошло не так, и это приложение не может поделиться сейчас», попробуйте запустить приложение, ориентированное на локальный компьютер. Что бы это ни стоило, мне показалось, что все работает хорошо, когда я делюсь со SkyDrive в симуляторе.
- Обязательно запросите отсрочку, если вы выполняете асинхронную работу, когда собираете свой контент. Возможно, вы захотите пойти по пути использования SetDataProvider, который подходит для сценариев, когда для обмена данными требуется гораздо больше ресурсов или времени для сборки.
- Работа с файлами и потоками кажется действительно сложной и болезненной — на самом деле это не связано с «обменом», но если вы делитесь содержимым изображения, вам придется манипулировать им в соответствующих форматах, таких как RandomAccessStreamReferences и IStorageFiles . Если вы хорошо знакомы с пакетом .NET System.IO , вы можете испытать еще большее разочарование, поскольку WinRT предоставляет другой набор асинхронных файловых интерфейсов, которые не всегда соответствуют тому, к чему вы привыкли.
Хорошая новость заключается в том, что существуют вспомогательные методы расширения, помогающие соединить синхронный доступ к файлам на основе COM, который вы знаете и любите, к новым асинхронным реализациям. Чтобы получить в этих методах расширения, таких как AsInputStream иAsOutputStream , вам нужно использовать WindowsRuntimeStreamExtensions, которые являются частью System.IO . Я нашел метод AsBuffer довольно ключевым тоже.
- Для готового тестового приложения с общим доступом загрузите образец целевого приложения с общим доступом и установите его. Затем, когда вы тестируете свое приложение, оно будет отображаться как цель общего доступа и отображать контент, который вы предоставляете — например, заголовок, описание, имя файла и т. Д. Есть сопутствующее приложение для обмена контентом, которое может быть полезным в качестве модели для вашего собственный код
- Мое приложение Starter KIt не участвует в качестве общего ресурса (только в качестве источника), но я обнаружил, что многие люди недоумевают, как тестировать и отлаживать приложения, которые запускаются в результате действий в других приложениях, таких как обмен или активация протокола . Здесь есть несколько рекомендаций , но ключ в том, чтобы отложить запуск сеанса отладки:
- C # / VB : настройка «Не запускать, а отлаживать мой код при запуске» на вкладке «Отладка» диалогового окна свойств проекта Магазина Windows.
- C ++ и JavaScript : выберите «Нет» в списке «Запустить приложение» на странице свойств «Отладка»
Надеюсь, я дал вам несколько идей о том, как сделать ваше собственное приложение уникальным и привлекательным. Имейте в виду , что методы , описанные здесь , могут быть применены к большинству, если не все, из других Starter Kits в проекте APIMASH .