Руководство. Отправка push-уведомлений в приложения Xamarin.Forms с помощью Центров уведомлений Azure через серверную службу
В этом руководстве вы используете Центры уведомлений Azure для отправки push-уведомлений в приложение Xamarin.Forms для Android и iOS.
Серверная часть веб-API
Эти операции обрабатываются с помощью пакета SDK для центров уведомлений для внутренних операций. Дополнительные сведения о общем подходе приведены в документации по регистрации из серверной части приложения документации.
В этом руководстве описаны следующие действия.
- настройка служб push-уведомлений и Центров уведомлений Azure.
- создание серверного приложения ASP.NET Core Web API.
- создание кроссплатформенного приложения Xamarin.Forms.
- настроить собственный проект Android для push-уведомлений.
- Настроить собственный проект iOS для push-уведомлений.
- протестировать решение.
Необходимые условия
Для выполнения дальнейших инструкций вам потребуется:
- подписке Azure, где можно создавать ресурсы и управлять ими.
- Компьютер Mac с Visual Studio для Mac установлен или компьютер под управлением Visual Studio 2019.
- пользователям Visual Studio 2019 также необходимо установить разработку мобильных приложений с помощью .NET и ASP.NET и рабочих нагрузок веб-разработки.
- Возможность запуска приложения на Android (физические или эмуляторные устройства) или iOS (только физические устройства).
Для Android необходимо иметь следующее:
- Разработчик разблокировал физическое устройство или эмулятор (с установленным API 26 и более поздних версий с установленными службами Google Play).
Для iOS необходимо:
- Активная учетной записи разработчика Apple.
- Физическое устройство iOS, зарегистрированное в учетной записи разработчика(под управлением iOS 13.0 и более поздних версий).
- сертификата разработки
.p12 , установленного в цепочке ключей , что позволяетзапускать приложение на физическом устройстве .
Заметка
Симулятор iOS не поддерживает удаленные уведомления, поэтому при изучении этого примера в iOS требуется физическое устройство. Однако для выполнения этого руководства не требуется запускать приложение как на Android, так и iOS.
Вы можете выполнить действия, описанные в этом примере с использованием первых принципов без предыдущего опыта. Тем не менее, вы получите преимущество от знакомства со следующими аспектами.
- портал разработчика Apple
- ASP.NET Core и веб-API
- консоль Google Firebase
- Microsoft Azure и отправлять push-уведомления в приложения iOS с помощью Центров уведомлений Azure.
- Xamarin и Xamarin.Forms.
Важный
Описанные действия относятся к Visual Studio для Mac. Можно следовать Visual Studio 2019, но могут возникнуть некоторые различия для согласования. Например, описания пользовательского интерфейса и рабочих процессов, имен шаблонов, конфигурации среды и т. д.
Настройка служб push-уведомлений и Центра уведомлений Azure
В этом разделе описано, как настроить Firebase Cloud Messaging (FCM) и службы push-уведомлений Apple (APNS). Затем вы создаете и настраиваете концентратор уведомлений для работы с этими службами.
Создание проекта Firebase и включение Firebase Cloud Messaging для Android
Войдите вконсоли Firebase
. Создайте проект Firebase, введющий PushDemo в качестве имени проекта. Заметка
Для вас будет создано уникальное имя. По умолчанию это состоит из нижнего регистра имени, указанного плюс созданного числа, разделенного дефисом. Это можно изменить, если вы хотите предоставить его по-прежнему глобально уникальным.
После создания проекта выберите Добавить Firebase в приложение Android.
На странице приложения Android
добавить Firebase выполните следующие действия. В поле имя пакета Androidвведите имя пакета. Например,
com.<organization_identifier>.<package_name>
.Выберите Зарегистрировать приложение.
Выберите Скачать google-services.json. Затем сохраните файл в локальную папку для последующего использования и нажмите кнопку Далее.
Выберите Далее.
Выберите Продолжить консоль
Заметка
Если кнопка
продолжить консоли не включена, из-за проверки установкинажмите кнопку Пропустить этот шаг .
В консоли Firebase выберите шестеренку для проекта. Затем выберите параметры проекта.
Заметка
Если вы не скачали файл google-services.json, его можно скачать на этой странице.
Перейдите на вкладку Cloud Messaging в верхней части. Скопируйте и сохраните ключа сервера
для последующего использования. Это значение используется для настройки концентратора уведомлений.
Регистрация приложения iOS для push-уведомлений
Чтобы отправить push-уведомления в приложение iOS, зарегистрируйте приложение в Apple, а также зарегистрируйтесь для push-уведомлений.
Если вы еще не зарегистрировали приложение, перейдите на портал подготовки iOS
в Центре разработчиков Apple. Войдите на портал с помощью идентификатора Apple ID, перейдите к сертификатам, идентификаторам & профилям, а затем выберите идентификаторы. Щелкните +, чтобы зарегистрировать новое приложение. На экране Регистрация нового идентификатора выберите идентификаторы приложений переключателя. Затем выберите Продолжить.
Обновите следующие три значения для нового приложения, а затем выберите Продолжить:
описание. Введите описательное имя приложения.
идентификатор пакета : введите идентификатор пакета формыcom. , как упоминалось вруководстве по распространению приложенийorganization_identifier . product_name . На следующем снимке экрана значение mobcat
используется в качестве идентификатора организации, а значение PushDemo используется в качестве имени продукта.страницы идентификатора приложения
push-уведомлений . Проверьте параметрpush-уведомлений в разделе Возможности .форма
Это действие создает идентификатор приложения и запросы, которые вы подтверждаете информацию. Выберите продолжить, а затем выберите Зарегистрировать, чтобы подтвердить новый идентификатор приложения.
После выбора регистрациивы увидите новый идентификатор приложения в виде элемента строки на странице Сертификатов, идентификаторов & профилей.
На странице "Сертификаты
идентификаторы" & профили в разделе "Идентификаторы" найдите созданный элемент строки идентификатор а приложения. Затем выберите строку, чтобы отобразить экран Изменить конфигурацию идентификатора приложения.
Создание сертификата для центров уведомлений
Сертификат необходим, чтобы центр уведомлений работал с службами push-уведомлений Apple (APNS) и может быть предоставлен одним из двух способов:
создание push-сертификата p12, который можно отправить непосредственно в центр уведомлений (исходного подхода)
создание сертификата p8, который можно использовать для проверки подлинности на основе маркеров (более новый и рекомендуемый подход)
Более новый подход имеет ряд преимуществ, как описано в проверке подлинности на основе токенов (HTTP/2) дляAPNS. Для конкретных сценариев требуется меньше шагов, но также требуется. Однако для обоих подходов были предоставлены шаги, так как они будут работать в целях этого руководства.
ВАРИАНТ 1. Создание push-сертификата p12, который можно отправить непосредственно в Центр уведомлений
На компьютере Mac запустите средство доступа к цепочке ключей. Его можно открыть из папки Служебные программы или папку Other на панели запуска.
Выберите
доступ к цепочке ключей , развернитепомощника по сертификату, а затем выберите Запросить сертификат из центра сертификации .Заметка
По умолчанию доступ к цепочке ключей выбирает первый элемент в списке. Это может быть проблема, если вы находитесь в категории сертификатов и Центр сертификации Apple По всему миру разработчиков не является первым элементом в списке. Убедитесь, что у вас есть элемент, отличный от ключа, или Центр сертификации Apple По всему миру разработчиков ключ выбран, прежде чем создавать CSR (запрос на подписи сертификатов).
Выберите
адрес электронной почты пользователя, введите значение общего имени , убедитесь, чтосохранено на диске , а затем нажмите кнопкуПродолжить . Оставьте адрес электронной почты ЦС пустым, так как он не требуется.Введите имя файла
запроса подписи сертификата (CSR) в сохранить как , выберите расположение вгде , а затем нажмите кнопкуСохранить .Это действие сохраняет CSR-файл в выбранном расположении. Расположение по умолчанию — desktop. Помните расположение, выбранное для файла.
Вернитесь на страницу сертификатов, идентификаторов & профилей на портале подготовки iOS, прокрутите страницу вниз до флажка push-уведомлений, а затем выберите Настроить для создания сертификата.
Появится появится окно TLS/SSL-сертификат ов службы push-уведомлений Apple. Нажмите кнопку создать сертификат в разделе Сертификат TLS/SSL.
Отображается экран создание нового сертификата.
Заметка
В этом руководстве используется сертификат разработки. При регистрации рабочего сертификата используется тот же процесс. Просто убедитесь, что при отправке уведомлений используется тот же тип сертификата.
Выберите Выбрать файл, перейдите к расположению, где вы сохранили CSR-файл, а затем дважды щелкните имя сертификата, чтобы загрузить его. Затем выберите Продолжить.
После создания сертификата на портале нажмите кнопку "Скачать". Сохраните сертификат и запомните расположение, в котором он сохранен.
Сертификат скачан и сохранен на компьютер в папке загрузки.
Заметка
По умолчанию скачанный сертификат разработки называется aps_development.cer.
Дважды щелкните скачанный push-сертификат aps_development.cer. Это действие устанавливает новый сертификат в цепочке ключей, как показано на следующем рисунке:
Заметка
Хотя имя в сертификате может отличаться, имя будет префиксировано с помощью push-служб Apple Development iOS и имеет соответствующий идентификатор пакета.
В access Control + Click на новом push-сертификате, созданном в категории сертификатов. Выберите экспорт, назовите файл, выберите формат p12 и нажмите кнопку Сохранить.
Вы можете защитить сертификат паролем, но пароль необязателен. Нажмите кнопку ОК, если вы хотите обойти создание пароля. Запишите имя файла и расположение экспортированного сертификата p12. Они используются для включения проверки подлинности с помощью APN.
Заметка
Имя и расположение файла p12 могут отличаться от того, что изображено в этом руководстве.
ВАРИАНТ 2. Создание сертификата p8, который можно использовать для проверки подлинности на основе токенов
Запишите следующие сведения:
- префикс идентификатора приложения
( идентификатор команды ) - идентификатор пакета
- префикс идентификатора приложения
Вернитесь в сертификаты, идентификаторы & профили, щелкните ключи.
Заметка
Если у вас уже есть ключ, настроенный для APNS, можно повторно использовать сертификат p8, скачанный сразу после его создания. В этом случае можно игнорировать шаги 3 через 5.
Нажмите кнопку + (или кнопку Создать ключ), чтобы создать новый ключ.
Укажите подходящее значение имени ключа, а затем проверьте параметр службы push-уведомлений Apple (APNS), а затем нажмите кнопку Продолжить, а затем Зарегистрировать на следующем экране.
Щелкните Скачать, а затем переместите файл p8 (префикс с AuthKey_) в безопасный локальный каталог, а затем щелкните Готово.
Заметка
Не забудьте сохранить p8-файл в безопасном месте (и сохранить резервную копию). После скачивания ключа его невозможно повторно скачать по мере удаления копии сервера.
На клавишищелкните созданный ключ (или существующий ключ, если вы решили использовать это).
Запишите значение идентификатора ключа
. Откройте сертификат p8 в подходящем приложении, например Visual Studio Code. Запишите значение ключа (между закрытым ключом -----BEGIN----- и -----END PRIVATE KEY-----).
ЗАКРЫТЫЙ КЛЮЧ -----BEGIN-----
<key_value>
-----END PRIVATE KEY-----Заметка
Это значение маркера , которое будет использоваться позже для настройки концентратора уведомлений.
В конце этих действий вам должны быть приведены следующие сведения для последующего использования в Настройка концентратора уведомлений с помощью сведений APNS:
- идентификатор команды (см. шаг 1)
- идентификатор пакета (см. шаг 1)
- идентификатор ключа (см. шаг 7)
- значение маркера (значение ключа p8, полученное на шаге 8)
Создание профиля подготовки для приложения
Вернитесь кпортала подготовки iOS
, выберите сертификаты, идентификаторы & профили , выберитепрофили в меню слева, а затем выберите, чтобы создать новый профиль. Появится экран Регистрация нового профиля подготовки. Выберите
разработки приложений iOS в разделе "Разработка " в качестве типа профиля подготовки, а затем выберите "Продолжить ".Затем выберите идентификатор приложения, созданный в раскрывающемся списке идентификатор приложения, и выберите Продолжить.
В окне Выбор сертификатов выберите сертификат разработки, используемый для подписывания кода, и выберите Продолжить.
Заметка
Этот сертификат не является push-сертификатом, созданным на предыдущем шаге . Это ваш сертификат разработки. Если он не существует, необходимо создать его, так как это предварительный для этого руководства. Сертификаты разработчика можно создавать на портале разработчиков Apple,с помощью Xcode или Visual Studio.
Вернитесь на страницу профилей
, идентификаторы & профилей , выберитепрофили в меню слева, а затем выберите, чтобы создать новый профиль. Появится экран Регистрация нового профиля подготовки. В окне Выбор сертификатов выберите созданный сертификат разработки. Затем выберите Продолжить.
Затем выберите устройства, которые будут использоваться для тестирования, и выберите Продолжить.
Наконец, выберите имя профиля в имя профиля подготовкии выберите Создать.
При создании нового профиля подготовки выберите Скачать. Помните расположение, в котором он сохранен.
Перейдите к расположению профиля подготовки и дважды щелкните его, чтобы установить его на компьютере разработки.
Создание центра уведомлений
В этом разделе описано, как создать концентратор уведомлений и настроить проверку подлинности с помощью APNS. Вы можете использовать push-сертификат p12 или проверку подлинности на основе маркеров. Если вы хотите использовать созданный центр уведомлений, можно перейти к шагу 5.
Войдите в Azure.
Щелкните Создать ресурс, а затем найдите и выберите Центр уведомлений, а затем щелкните Создать.
Обновите следующие поля, а затем щелкните Создать:
БАЗОВЫЕ СВЕДЕНИЯ
подписка : выберите целевую подписку из раскрывающегося списка
группа ресурсов : создать новую группу ресурсов (или выбрать существующую)СВЕДЕНИЯ О ПРОСТРАНСТВЕ ИМЕН
пространство имен центра уведомлений : Введите глобально уникальное имя для пространства имен центра уведомлений
Заметка
Убедитесь, что для этого поля выбран параметр "Создать новую".
СВЕДЕНИЯ ЦЕНТРА УВЕДОМЛЕНИЙ
Центр уведомлений : введите имя центра уведомлений
расположение: Выбрать подходящее расположение из раскрывающегося списка
ценовая категория : Сохранить параметр бесплатного по умолчаниюЗаметка
Если вы не достигли максимального количества центров на уровне "Бесплатный".
После подготовки Центра уведомлений
перейдите к ресурсу. Перейдите к новому центру уведомлений .
Выберите политики доступа из списка (в разделе MANAGE).
Запишите значения имени политики
вместе со значениями строки подключения .
Настройка центра уведомлений с помощью сведений APNS
В разделеслужб уведомлений
Заметка
Используйте рабочую для режима приложений только в том случае, если вы хотите отправлять push-уведомления пользователям, которые приобрели приложение из магазина.
ВАРИАНТ 1. Использование push-сертификата P12
Выберитесертификата
. Щелкните значок файла.
Выберите P12-файл, экспортируемый ранее, и выберите Открыть.
При необходимости укажите правильный пароль.
Выберите режим песочницы.
Выберите Сохранить.
ВАРИАНТ 2. Использование проверки подлинности на основе токенов
Выберите токена.
Введите следующие значения, полученные ранее:
- идентификатор ключа
- идентификатор пакета
- идентификатор команды
- маркера
Выберите песочницу.
Выберите Сохранить.
Настройка концентратора уведомлений с помощью данных FCM
- Выберите Google (GCM/FCM) в разделе "Параметры " меню слева.
- Введите ключ сервера , который вы указали из консоли Google Firebase.
- Выберите Сохранить на панели инструментов.
Создание серверного приложения веб-API ASP.NET Core
В этом разделе описано, как создать серверную часть веб-API
Создание веб-проекта
В Visual Studioвыберите файл>новый.
Выберите .NET Core>App>ASP.NET Core>API>Далее.
В диалоговом окне Настройка нового веб- API ASP.NET Core Web API выберите Target Framework.NET Core 3.1.
Введите PushDemoApi для имени проекта и выберите Создать.
Начните отладку (команда + ВВОД) для тестирования шаблонного приложения.
Заметка
Шаблонное приложение настроено для использования WeatherForecastController в качестве launchUrl. Этот параметр задан в Свойства>launchSettings.json.
Если вам будет предложено получить недопустимый сертификат разработки найден сообщение:
Щелкните Да, чтобы согласиться запустить средство dotnet dev-certs https, чтобы устранить эту проблему. Затем средство dotnet dev-certs https предложит ввести пароль для сертификата и пароля для цепочки ключей.
Щелкните Да при появлении запроса на установить и доверять новому сертификату, а затем введите пароль для цепочки ключей.
Разверните папку контроллеров
, а затем удалите WeatherForecastController.cs .Удаление WeatherForecast.cs.
Настройте локальные значения конфигурации с помощью средства Secret Manager. Разделение секретов из решения гарантирует, что они не в конечном итоге в системе управления версиями. Откройте терминал перейдите в каталог файла проекта и выполните следующие команды:
dotnet user-secrets init dotnet user-secrets set "NotificationHub:Name" <value> dotnet user-secrets set "NotificationHub:ConnectionString" <value>
Замените значения заполнителей собственным именем концентратора уведомлений и значениями строки подключения. Вы записали их в разделе создания центра уведомлений. В противном случае их можно найти в Azure.
NotificationHub:Name:
См.в сводке Essentials в верхней частиобзора . NotificationHub:ConnectionString:
См. defaultFullSharedAccessSignature в политиках доступаЗаметка
В рабочих сценариях можно просмотреть такие варианты, как Azure KeyVault для безопасного хранения строки подключения. Для простоты секреты будут добавлены в параметры приложения службы приложений Azure .
Проверка подлинности клиентов с помощью ключа API (необязательно)
Ключи API не так безопасны, как маркеры, но достаточно для целей этого руководства. Ключ API можно легко настроить с помощью ASP.NET ПО промежуточного слоя.
Добавьте ключ API в значения локальной конфигурации.
dotnet user-secrets set "Authentication:ApiKey" <value>
Заметка
Замените значение заполнителя собственным и запишите его.
Элемент управления щелкните в проектеPushDemoApi , выберитесоздать папку в меню"Добавить ", а затем выберитеДобавить проверки подлинностив качестве имени папки .Элемент управления щелкните в папке проверки подлинности, а затем выберите Создать файл... в меню"Добавить ".Выберите
Общие пустого класса , введитеApiKeyAuthOptions.cs дляимени, а затем нажмите кнопку Создать добавить следующую реализацию.using Microsoft.AspNetCore.Authentication; namespace PushDemoApi.Authentication { public class ApiKeyAuthOptions : AuthenticationSchemeOptions { public const string DefaultScheme = "ApiKey"; public string Scheme => DefaultScheme; public string ApiKey { get; set; } } }
Добавьте еще один пустой класс в папку проверки подлинности с именем ApiKeyAuthHandler.cs, а затем добавьте следующую реализацию.
using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace PushDemoApi.Authentication { public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions> { const string ApiKeyIdentifier = "apikey"; public ApiKeyAuthHandler( IOptionsMonitor<ApiKeyAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) {} protected override Task<AuthenticateResult> HandleAuthenticateAsync() { string key = string.Empty; if (Request.Headers[ApiKeyIdentifier].Any()) { key = Request.Headers[ApiKeyIdentifier].FirstOrDefault(); } else if (Request.Query.ContainsKey(ApiKeyIdentifier)) { if (Request.Query.TryGetValue(ApiKeyIdentifier, out var queryKey)) key = queryKey; } if (string.IsNullOrWhiteSpace(key)) return Task.FromResult(AuthenticateResult.Fail("No api key provided")); if (!string.Equals(key, Options.ApiKey, StringComparison.Ordinal)) return Task.FromResult(AuthenticateResult.Fail("Invalid api key.")); var identities = new List<ClaimsIdentity> { new ClaimsIdentity("ApiKeyIdentity") }; var ticket = new AuthenticationTicket( new ClaimsPrincipal(identities), Options.Scheme); return Task.FromResult(AuthenticateResult.Success(ticket)); } } }
Добавьте еще один
пустой класс вApiKeyAuthenticationBuilderExtensions.cs папку проверки подлинности, а затем добавьте следующую реализацию. using System; using Microsoft.AspNetCore.Authentication; namespace PushDemoApi.Authentication { public static class AuthenticationBuilderExtensions { public static AuthenticationBuilder AddApiKeyAuth( this AuthenticationBuilder builder, Action<ApiKeyAuthOptions> configureOptions) { return builder .AddScheme<ApiKeyAuthOptions, ApiKeyAuthHandler>( ApiKeyAuthOptions.DefaultScheme, configureOptions); } } }
Заметка
Этот метод расширения упрощает код конфигурации ПО промежуточного слоя в Startup.cs что делает его более удобочитаемым и, как правило, проще следовать.
В Startup.csобновите метод ConfigureServices, чтобы настроить проверку подлинности ключа API под вызовом служб . Метод AddControllers.
using PushDemoApi.Authentication; using PushDemoApi.Models; using PushDemoApi.Services; public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme; options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme; }).AddApiKeyAuth(Configuration.GetSection("Authentication").Bind); }
По-прежнему в
Startup.cs обновите методConfigure , чтобывызвать метод UseAuthentication иМетоды расширения UseAuthorization вIApplicationBuild er приложения. Убедитесь, что эти методы вызываются после UseRouting и до приложения. UseEndpoints.public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
Заметка
Вызов UseAuthentication регистрирует ПО промежуточного слоя, которое использует ранее зарегистрированные схемы проверки подлинности (из ConfigureServices). Это необходимо вызвать перед любым ПО промежуточного слоя, которое зависит от проверки подлинности пользователей.
Добавление зависимостей и настройка служб
ASP.NET Core поддерживает шаблон внедрения зависимостей (DI) программного обеспечения, который является способом достижения инверсии управления (IoC) между классами и их зависимостями.
Использование концентратора уведомлений и пакета SDK для центров уведомлений для внутренних операций инкапсулируется в службе. Служба зарегистрирована и доступна с помощью подходящей абстракции.
Элемент управления + щелкните в папке зависимостей, а затем выберите Управление пакетами NuGet....
Выполните поиск Microsoft.Azure.NotificationHubs и убедитесь, что он установлен.
Щелкните Добавить пакеты, а затем щелкните Принять при появлении запроса на принятие условий лицензии.
Элемент управления щелкните в проектеPushDemoApi , выберитесоздать папку в меню"Добавить ", а затем щелкнитеДобавить с помощью моделейв качестве имени папки .Элемент управления Щелкните в папке модели, а затем выберитеСоздать файл... в менюДобавить .Выберите
Общие пустого класса , введитеPushTemplates.cs дляимени, а затем нажмите кнопку Создать добавить следующую реализацию.namespace PushDemoApi.Models { public class PushTemplates { public class Generic { public const string Android = "{ \"notification\": { \"title\" : \"PushDemo\", \"body\" : \"$(alertMessage)\"}, \"data\" : { \"action\" : \"$(alertAction)\" } }"; public const string iOS = "{ \"aps\" : {\"alert\" : \"$(alertMessage)\"}, \"action\" : \"$(alertAction)\" }"; } public class Silent { public const string Android = "{ \"data\" : {\"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\"} }"; public const string iOS = "{ \"aps\" : {\"content-available\" : 1, \"apns-priority\": 5, \"sound\" : \"\", \"badge\" : 0}, \"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\" }"; } } }
Заметка
Этот класс содержит полезные данные уведомления с маркерами для универсальных и автоматических уведомлений, необходимых для этого сценария. Полезные данные определяются вне установки, чтобы разрешить экспериментирование без необходимости обновлять существующие установки через службу. Обработка изменений в установках таким образом выходит за рамки этого руководства. Для рабочей среды рассмотрите возможность пользовательских шаблонов.
Добавьте еще один
пустой класс в папку моделейс именем DeviceInstallation.cs , а затем добавьте следующую реализацию.using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace PushDemoApi.Models { public class DeviceInstallation { [Required] public string InstallationId { get; set; } [Required] public string Platform { get; set; } [Required] public string PushChannel { get; set; } public IList<string> Tags { get; set; } = Array.Empty<string>(); } }
Добавьте еще один пустой класс в папку Models с именем NotificationRequest.cs, а затем добавьте следующую реализацию.
using System; namespace PushDemoApi.Models { public class NotificationRequest { public string Text { get; set; } public string Action { get; set; } public string[] Tags { get; set; } = Array.Empty<string>(); public bool Silent { get; set; } } }
Добавьте еще один
пустой класс в папку моделей с именемNotificationHubOptions.cs , а затем добавьте следующую реализацию.using System.ComponentModel.DataAnnotations; namespace PushDemoApi.Models { public class NotificationHubOptions { [Required] public string Name { get; set; } [Required] public string ConnectionString { get; set; } } }
Добавьте новую папку в проект PushDemoApi с именем Services.
Добавьте пустого интерфейса
в папку служб с именем INotificationService.cs , а затем добавьте следующую реализацию.using System.Threading; using System.Threading.Tasks; using PushDemoApi.Models; namespace PushDemoApi.Services { public interface INotificationService { Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token); Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token); Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token); } }
Добавьте
пустой класс в папку служб с именемNotificationHubsService.cs , а затем добавьте следующий код для реализации интерфейсаINotificationService :using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.NotificationHubs; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using PushDemoApi.Models; namespace PushDemoApi.Services { public class NotificationHubService : INotificationService { readonly NotificationHubClient _hub; readonly Dictionary<string, NotificationPlatform> _installationPlatform; readonly ILogger<NotificationHubService> _logger; public NotificationHubService(IOptions<NotificationHubOptions> options, ILogger<NotificationHubService> logger) { _logger = logger; _hub = NotificationHubClient.CreateClientFromConnectionString( options.Value.ConnectionString, options.Value.Name); _installationPlatform = new Dictionary<string, NotificationPlatform> { { nameof(NotificationPlatform.Apns).ToLower(), NotificationPlatform.Apns }, { nameof(NotificationPlatform.Fcm).ToLower(), NotificationPlatform.Fcm } }; } public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token) { if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) || string.IsNullOrWhiteSpace(deviceInstallation?.Platform) || string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel)) return false; var installation = new Installation() { InstallationId = deviceInstallation.InstallationId, PushChannel = deviceInstallation.PushChannel, Tags = deviceInstallation.Tags }; if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform)) installation.Platform = platform; else return false; try { await _hub.CreateOrUpdateInstallationAsync(installation, token); } catch { return false; } return true; } public async Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token) { if (string.IsNullOrWhiteSpace(installationId)) return false; try { await _hub.DeleteInstallationAsync(installationId, token); } catch { return false; } return true; } public async Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token) { if ((notificationRequest.Silent && string.IsNullOrWhiteSpace(notificationRequest?.Action)) || (!notificationRequest.Silent && (string.IsNullOrWhiteSpace(notificationRequest?.Text)) || string.IsNullOrWhiteSpace(notificationRequest?.Action))) return false; var androidPushTemplate = notificationRequest.Silent ? PushTemplates.Silent.Android : PushTemplates.Generic.Android; var iOSPushTemplate = notificationRequest.Silent ? PushTemplates.Silent.iOS : PushTemplates.Generic.iOS; var androidPayload = PrepareNotificationPayload( androidPushTemplate, notificationRequest.Text, notificationRequest.Action); var iOSPayload = PrepareNotificationPayload( iOSPushTemplate, notificationRequest.Text, notificationRequest.Action); try { if (notificationRequest.Tags.Length == 0) { // This will broadcast to all users registered in the notification hub await SendPlatformNotificationsAsync(androidPayload, iOSPayload, token); } else if (notificationRequest.Tags.Length <= 20) { await SendPlatformNotificationsAsync(androidPayload, iOSPayload, notificationRequest.Tags, token); } else { var notificationTasks = notificationRequest.Tags .Select((value, index) => (value, index)) .GroupBy(g => g.index / 20, i => i.value) .Select(tags => SendPlatformNotificationsAsync(androidPayload, iOSPayload, tags, token)); await Task.WhenAll(notificationTasks); } return true; } catch (Exception e) { _logger.LogError(e, "Unexpected error sending notification"); return false; } } string PrepareNotificationPayload(string template, string text, string action) => template .Replace("$(alertMessage)", text, StringComparison.InvariantCulture) .Replace("$(alertAction)", action, StringComparison.InvariantCulture); Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, CancellationToken token) { var sendTasks = new Task[] { _hub.SendFcmNativeNotificationAsync(androidPayload, token), _hub.SendAppleNativeNotificationAsync(iOSPayload, token) }; return Task.WhenAll(sendTasks); } Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, IEnumerable<string> tags, CancellationToken token) { var sendTasks = new Task[] { _hub.SendFcmNativeNotificationAsync(androidPayload, tags, token), _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token) }; return Task.WhenAll(sendTasks); } } }
Заметка
Выражение тега, предоставленное для SendTemplateNotificationAsync, ограничено 20 тегами. Это ограничение ограничено 6 для большинства операторов, но выражение содержит только OR (||) в этом случае. Если в запросе существует более 20 тегов, они должны быть разделены на несколько запросов. Дополнительные сведения см. в документации по
выражения маршрутизации и тегов. В
Startup.cs обновите методConfigureServices , чтобы добавить NotificationHubsServiceNotificationHubsService в качестве единой реализации INotificationService .using PushDemoApi.Models; using PushDemoApi.Services; public void ConfigureServices(IServiceCollection services) { ... services.AddSingleton<INotificationService, NotificationHubService>(); services.AddOptions<NotificationHubOptions>() .Configure(Configuration.GetSection("NotificationHub").Bind) .ValidateDataAnnotations(); }
Создание API уведомлений
Элемент управления щелкните в папке контроллеров, а затем выберите Создать файл... в менюДобавить .Выберитекласс контроллера веб-API
ASP.NET Core , введите NotificationsController дляимени, а затем нажмите кнопку Создать .Заметка
Если вы используете Visual Studio 2019, выберите контроллер API с помощью шаблона действий чтения и записи.
Добавьте следующие пространства имен в начало файла.
using System.ComponentModel.DataAnnotations; using System.Net; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using PushDemoApi.Models; using PushDemoApi.Services;
Обновите шаблонный контроллер, чтобы он был производным от ControllerBase и украшен атрибутом ApiController.
[ApiController] [Route("api/[controller]")] public class NotificationsController : ControllerBase { // Templated methods here }
Заметка
Базовый класс контроллера
обеспечивает поддержку представлений, но в этом случае это не требуется, поэтому вместо этого можно использовать ControllerBase ControllerBase. Если вы используете Visual Studio 2019, этот шаг можно пропустить. Если вы решили завершить проверку подлинности клиентов
с помощью раздела ключа API, необходимо также украсить notificationsControllerс помощью атрибута авторизовать . [Authorize]
Обновите конструктор, чтобы принять зарегистрированный экземпляр INotificationService в качестве аргумента и назначить его элементу чтения.
readonly INotificationService _notificationService; public NotificationsController(INotificationService notificationService) { _notificationService = notificationService; }
В
launchSettings.json (в папке свойств) измените launchUrl сна api/notifications , чтобы он соответствовал URL-адресу, указанному в атрибутеRegistrationsController Route .Запустите отладку (команда + ВВОД) для проверки работы приложения с новым NotificationsController и возвращает состояние 401 Unauthorized.
Заметка
Visual Studio может не запускать приложение в браузере автоматически. Вы будете использовать Postman для тестирования API с этой точки.
На новой вкладке Postman задайте для запроса GET. Введите приведенный ниже адрес, заменив заполнитель
httpsapplicationUrl applicationUrl , найденный вlaunchSettings.json свойств. <applicationUrl>/api/notifications
Заметка
applicationUrl должен быть "https://localhost:5001" для профиля по умолчанию. Если вы используете IIS (по умолчанию в Visual Studio 2019 в Windows), следует использовать applicationUrl, указанные в элементе iisSettings. Если адрес неверный, вы получите ответ 404.
Если вы решили выполнить аутентификацию клиентов с помощью раздела ключа API, обязательно настройте заголовки запроса, чтобы включить значение apikey.
Ключ Ценность apikey <your_api_key> Нажмите кнопку "Отправить
". Заметка
Вы должны получить состояние
200 OK с некоторыми содержимого JSON .Если вы получаете предупреждение
проверки SSL-сертификата , можно переключить проверку проверки SSL-сертификата запроса впараметровPostman . Замените методы шаблонного класса в NotificationsController.cs следующим кодом.
[HttpPut] [Route("installations")] [ProducesResponseType((int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)] public async Task<IActionResult> UpdateInstallation( [Required]DeviceInstallation deviceInstallation) { var success = await _notificationService .CreateOrUpdateInstallationAsync(deviceInstallation, HttpContext.RequestAborted); if (!success) return new UnprocessableEntityResult(); return new OkResult(); } [HttpDelete()] [Route("installations/{installationId}")] [ProducesResponseType((int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)] public async Task<ActionResult> DeleteInstallation( [Required][FromRoute]string installationId) { var success = await _notificationService .DeleteInstallationByIdAsync(installationId, CancellationToken.None); if (!success) return new UnprocessableEntityResult(); return new OkResult(); } [HttpPost] [Route("requests")] [ProducesResponseType((int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)] public async Task<IActionResult> RequestPush( [Required]NotificationRequest notificationRequest) { if ((notificationRequest.Silent && string.IsNullOrWhiteSpace(notificationRequest?.Action)) || (!notificationRequest.Silent && string.IsNullOrWhiteSpace(notificationRequest?.Text))) return new BadRequestResult(); var success = await _notificationService .RequestNotificationAsync(notificationRequest, HttpContext.RequestAborted); if (!success) return new UnprocessableEntityResult(); return new OkResult(); }
Создание приложения API
Теперь вы создадите приложения API
Щелкните Создать ресурс, а затем найдите и выберите приложение API, а затем щелкните Создать.
Обновите следующие поля, а затем щелкните Создать.
имя приложения :
Введите глобально уникальное имя приложения APIподписка :
Выберите тот же целевой подписки, в которую вы создали концентратор уведомлений.Группа ресурсов :
Выберите ту же группу ресурсов, в которую вы создали концентратор уведомлений.план или расположение службы приложений :
Создание плана службы приложенийЗаметка
Переход от параметра по умолчанию к плану, который включает поддержку SSL-. В противном случае при работе с мобильным приложением необходимо выполнить соответствующие действия, чтобы предотвратить блокировку запросов http.
Application Insights:
Сохраните предлагаемый параметр (новый ресурс будет создан с помощью этого имени) или выберите существующий ресурс.После подготовки приложения API
перейдите к ресурсу. Запишите свойство URL-адреса
в сводке Essentials в верхней частиобзора. Этот URL-адрес — это серверная конечная точка, которая будет использоваться далее в этом руководстве. Заметка
URL-адрес использует имя приложения API, указанное ранее, с форматом
https://<app_name>.azurewebsites.net
.Выберите конфигурации
в списке (в разделепараметров ). Для каждого из приведенных ниже параметров щелкните
Параметр нового приложения , чтобы ввести имяи значение , а затем нажмите кнопкуОК .Имя Ценность Authentication:ApiKey
<api_key_value> NotificationHub:Name
<hub_name_value> NotificationHub:ConnectionString
<hub_connection_string_value> Заметка
Это те же параметры, которые вы определили ранее в параметрах пользователя. Их можно скопировать. Параметр проверки подлинности :ApiKey требуется только в том случае, если вы решили выполнить проверку подлинности клиентов с помощью раздела ключа API. В рабочих сценариях можно просмотреть такие варианты, как Azure KeyVault. Они добавлены в качестве параметров приложения для простоты в этом случае.
После добавления всех параметров приложения нажмите кнопку Сохранить, а затем продолжить.
Публикация серверной службы
Затем вы развернете приложение в приложении API, чтобы сделать его доступным на всех устройствах.
Заметка
Следующие действия относятся к Visual Studio для Mac. Если вы используете Visual Studio 2019 в Windows, поток публикации будет отличаться. См. статью Публикации в Службе приложений Azure в Windows.
Измените конфигурацию с отладки на выпуск, если это еще не сделано.
Элемент управления + щелкните проект PushDemoApi, а затем выберите Опубликовать в Azure... в меню публикации.
Следуйте потоку проверки подлинности, если появится запрос на это. Используйте учетную запись, используемую в предыдущем создайте приложение API.
Выберите приложение API службы приложений Azure, созданное ранее в списке в качестве целевого объекта публикации, а затем щелкните Опубликовать.
После завершения работы мастера он публикует приложение в Azure, а затем открывает приложение. Запишите URL-адрес , если это еще не сделано. Этот URL-адрес — это серверная конечная точка, которая используется далее в этом руководстве.
Проверка опубликованного API
В Postman откройте новую вкладку, задайте для запроса PUT и введите указанный ниже адрес. Замените заполнитель базовым адресом, который вы заметили в предыдущем опубликовать серверную службу раздела.
https://<app_name>.azurewebsites.net/api/notifications/installations
Заметка
Базовый адрес должен быть в формате
https://<app_name>.azurewebsites.net/
Если вы решили выполнить аутентификацию клиентов с помощью раздела ключа API, обязательно настройте заголовки запроса, чтобы включить значение apikey.
Ключ Ценность apikey <your_api_key> Выберите параметр
необработанных длятекста, а затем выберите JSON из списка параметров форматирования, а затем добавьте некоторые заполнителисодержимое JSON :{}
Щелкните Отправить.
Заметка
Вы должны получить 422 UnprocessableEntity состояние от службы.
Выполните шаги 1–4 еще раз, но на этот раз укажите конечную точку запросов, чтобы проверить получение ответа 400 недопустимых запросов.
https://<app_name>.azurewebsites.net/api/notifications/requests
Заметка
Пока не удается протестировать API с использованием допустимых данных запроса, так как для этого потребуются сведения, относящиеся к платформе, из клиентского мобильного приложения.
Создание кроссплатформенного приложения Xamarin.Forms
В этом разделе описано, как создать Xamarin.Forms мобильное приложение, реализующее push-уведомления кроссплатформенным способом.
Он позволяет зарегистрировать и отменить регистрацию из центра уведомлений с помощью созданной серверной службы.
Оповещение отображается при указании действия и приложение находится на переднем плане. В противном случае уведомления отображаются в центре уведомлений.
Заметка
Обычно вы выполняете действия регистрации (и дерегистрации) во время соответствующего момента жизненного цикла приложения (или как часть первого запуска) без явного регистрации или отмены регистрации входных данных. Однако в этом примере потребуются явные входные данные пользователя, которые позволяют просматривать и тестировать эту функцию более легко.
Создание решения Xamarin.Forms
В
Visual Studio создайте новое решениеXamarin.Forms с помощьюприложения пустых форм в качестве шаблона и ввода PushDemo дляимени проекта. Заметка
В диалоговом окне Настройка приложения пустых форм убедитесь, что идентификатор организации соответствует значению, используемому ранее, и что проверяются android и целевые объекты iOS.
элемент управления + щелкните в решении PushDemo, а затем выберите Обновить пакеты NuGet.
элемент управления + щелкните в решении PushDemo, а затем выберите Управление пакетами NuGet...
Выполните поиск Newtonsoft.Json и убедитесь, что он установлен.
Щелкните Добавить пакеты, а затем щелкните Принять при появлении запроса на принятие условий лицензии.
Создайте и запустите приложение на каждой целевой платформе (Command + ВВОД) для тестирования шаблонного приложения на устройстве.
Реализация кроссплатформенных компонентов
Элемент управления + щелкните в проекте PushDemo, выберите Создать папку в меню Добавить, а затем щелкните Добавить с помощью моделей в качестве имени папки.
Элемент управления Щелкните в папке модели, а затем выберитеСоздать файл... в менюДобавить .Выберите Общие>пустой класс, введите DeviceInstallation.cs, а затем добавьте следующую реализацию.
using System.Collections.Generic; using Newtonsoft.Json; namespace PushDemo.Models { public class DeviceInstallation { [JsonProperty("installationId")] public string InstallationId { get; set; } [JsonProperty("platform")] public string Platform { get; set; } [JsonProperty("pushChannel")] public string PushChannel { get; set; } [JsonProperty("tags")] public List<string> Tags { get; set; } = new List<string>(); } }
Добавьте пустого перечисления
в папку моделей с именем PushDemoAction.cs со следующей реализацией.namespace PushDemo.Models { public enum PushDemoAction { ActionA, ActionB } }
Добавьте новую папку в проект pushDemo
с именем Services , а затем добавьте в неепустой класс с именемServiceContainer.cs со следующей реализацией.using System; using System.Collections.Generic; namespace PushDemo.Services { public static class ServiceContainer { static readonly Dictionary<Type, Lazy<object>> services = new Dictionary<Type, Lazy<object>>(); public static void Register<T>(Func<T> function) => services[typeof(T)] = new Lazy<object>(() => function()); public static T Resolve<T>() => (T)Resolve(typeof(T)); public static object Resolve(Type type) { { if (services.TryGetValue(type, out var service)) return service.Value; throw new KeyNotFoundException($"Service not found for type '{type}'"); } } } }
Заметка
Это сокращенная версия класса ServiceContainer из репозитория XamCAT. Он будет использоваться в качестве контейнера IoC (inversion of Control).
Добавьте пустой интерфейс в папку служб с именем IDeviceInstallationService.cs, а затем добавьте следующий код.
using PushDemo.Models; namespace PushDemo.Services { public interface IDeviceInstallationService { string Token { get; set; } bool NotificationsSupported { get; } string GetDeviceId(); DeviceInstallation GetDeviceInstallation(params string[] tags); } }
Заметка
Этот интерфейс будет реализован и загрузится каждым целевым объектом позже, чтобы предоставить функциональные возможности для конкретной платформы и DeviceInstallation сведения, необходимые серверной службе.
Добавьте еще один пустой интерфейс в папку служб с именем INotificationRegistrationService.cs, а затем добавьте следующий код.
using System.Threading.Tasks; namespace PushDemo.Services { public interface INotificationRegistrationService { Task DeregisterDeviceAsync(); Task RegisterDeviceAsync(params string[] tags); Task RefreshRegistrationAsync(); } }
Заметка
Это будет обрабатывать взаимодействие между клиентом и серверной службой.
Добавьте еще один
пустой интерфейс в папку службс именем INotificationActionService.cs , а затем добавьте следующий код.namespace PushDemo.Services { public interface INotificationActionService { void TriggerAction(string action); } }
Заметка
Это используется в качестве простого механизма для централизованной обработки действий уведомлений.
Добавьте
пустой интерфейс в папку службс именем IPushDemoNotificationActionService.cs , наследуемой отINotificationActionService , с следующей реализацией.using System; using PushDemo.Models; namespace PushDemo.Services { public interface IPushDemoNotificationActionService : INotificationActionService { event EventHandler<PushDemoAction> ActionTriggered; } }
Заметка
Этот тип предназначен для приложения PushDemo и использует перечисление PushDemoAction для определения действия, активируемого строго типизированным образом.
Добавьте пустого класса
в папку служб NotificationRegistrationService.cs службNotificationRegistrationService.cs , реализуяINotificationRegistrationService со следующим кодом.using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using PushDemo.Models; using Xamarin.Essentials; namespace PushDemo.Services { public class NotificationRegistrationService : INotificationRegistrationService { const string RequestUrl = "api/notifications/installations"; const string CachedDeviceTokenKey = "cached_device_token"; const string CachedTagsKey = "cached_tags"; string _baseApiUrl; HttpClient _client; IDeviceInstallationService _deviceInstallationService; public NotificationRegistrationService(string baseApiUri, string apiKey) { _client = new HttpClient(); _client.DefaultRequestHeaders.Add("Accept", "application/json"); _client.DefaultRequestHeaders.Add("apikey", apiKey); _baseApiUrl = baseApiUri; } IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>()); public async Task DeregisterDeviceAsync() { var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey) .ConfigureAwait(false); if (cachedToken == null) return; var deviceId = DeviceInstallationService?.GetDeviceId(); if (string.IsNullOrWhiteSpace(deviceId)) throw new Exception("Unable to resolve an ID for the device."); await SendAsync(HttpMethod.Delete, $"{RequestUrl}/{deviceId}") .ConfigureAwait(false); SecureStorage.Remove(CachedDeviceTokenKey); SecureStorage.Remove(CachedTagsKey); } public async Task RegisterDeviceAsync(params string[] tags) { var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags); await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation) .ConfigureAwait(false); await SecureStorage.SetAsync(CachedDeviceTokenKey, deviceInstallation.PushChannel) .ConfigureAwait(false); await SecureStorage.SetAsync(CachedTagsKey, JsonConvert.SerializeObject(tags)); } public async Task RefreshRegistrationAsync() { var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey) .ConfigureAwait(false); var serializedTags = await SecureStorage.GetAsync(CachedTagsKey) .ConfigureAwait(false); if (string.IsNullOrWhiteSpace(cachedToken) || string.IsNullOrWhiteSpace(serializedTags) || string.IsNullOrWhiteSpace(DeviceInstallationService.Token) || cachedToken == DeviceInstallationService.Token) return; var tags = JsonConvert.DeserializeObject<string[]>(serializedTags); await RegisterDeviceAsync(tags); } async Task SendAsync<T>(HttpMethod requestType, string requestUri, T obj) { string serializedContent = null; await Task.Run(() => serializedContent = JsonConvert.SerializeObject(obj)) .ConfigureAwait(false); await SendAsync(requestType, requestUri, serializedContent); } async Task SendAsync( HttpMethod requestType, string requestUri, string jsonRequest = null) { var request = new HttpRequestMessage(requestType, new Uri($"{_baseApiUrl}{requestUri}")); if (jsonRequest != null) request.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json"); var response = await _client.SendAsync(request).ConfigureAwait(false); response.EnsureSuccessStatusCode(); } } }
Заметка
Аргумент apiKey требуется только в том случае, если вы решили выполнить проверку подлинности клиентов с помощью раздела ключа API.
Добавьте пустого класса
в папку служб с именем PushDemoNotificationActionService.cs реализацииIPushDemoNotificationActionService со следующим кодом.using System; using System.Collections.Generic; using System.Linq; using PushDemo.Models; namespace PushDemo.Services { public class PushDemoNotificationActionService : IPushDemoNotificationActionService { readonly Dictionary<string, PushDemoAction> _actionMappings = new Dictionary<string, PushDemoAction> { { "action_a", PushDemoAction.ActionA }, { "action_b", PushDemoAction.ActionB } }; public event EventHandler<PushDemoAction> ActionTriggered = delegate { }; public void TriggerAction(string action) { if (!_actionMappings.TryGetValue(action, out var pushDemoAction)) return; List<Exception> exceptions = new List<Exception>(); foreach (var handler in ActionTriggered?.GetInvocationList()) { try { handler.DynamicInvoke(this, pushDemoAction); } catch (Exception ex) { exceptions.Add(ex); } } if (exceptions.Any()) throw new AggregateException(exceptions); } } }
Добавьте пустой класс в проект PushDemo с Config.cs следующей реализацией.
namespace PushDemo { public static partial class Config { public static string ApiKey = "API_KEY"; public static string BackendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT"; } }
Заметка
Это используется в качестве простого способа сохранения секретов из системы управления версиями. Эти значения можно заменить как часть автоматической сборки или переопределить их с помощью локального частичного класса. Вы сделаете это на следующем шаге.
Поле ApiKey требуется только в том случае, если вы решили выполнить проверку подлинности клиентов с помощью раздела ключа API.
Добавьте еще один пустой класс в проект PushDemo на этот раз с именем Config.local_secrets.cs со следующей реализацией.
namespace PushDemo { public static partial class Config { static Config() { ApiKey = "<your_api_key>"; BackendServiceEndpoint = "<your_api_app_url>"; } } }
Заметка
Замените значения заполнителей собственными. При создании серверной службы необходимо заметить их. URL-адрес приложения API
должен быть . Не забудьте добавить *.local_secrets.*
в файл Gitignore, чтобы избежать фиксации этого файла.Поле ApiKey требуется только в том случае, если вы решили выполнить проверку подлинности клиентов с помощью раздела ключа API.
Добавьте пустой класс в проект PushDemo с Bootstrap.cs следующей реализацией.
using System; using PushDemo.Services; namespace PushDemo { public static class Bootstrap { public static void Begin(Func<IDeviceInstallationService> deviceInstallationService) { ServiceContainer.Register(deviceInstallationService); ServiceContainer.Register<IPushDemoNotificationActionService>(() => new PushDemoNotificationActionService()); ServiceContainer.Register<INotificationRegistrationService>(() => new NotificationRegistrationService( Config.BackendServiceEndpoint, Config.ApiKey)); } } }
Заметка
Метод Begin будет вызываться каждой платформой при запуске приложения в реализации IDeviceInstallationService.
Аргумент конструктора apiKey NotificationRegistrationServiceapiKey требуется только в том случае, если вы решили выполнить проверку подлинности клиентов с помощью раздела ключа API.
Реализация кроссплатформенного пользовательского интерфейса
В проекте pushDemo
откройте MainPage.xaml и замените элемент управленияStackLayout следующим образом.<StackLayout VerticalOptions="EndAndExpand" HorizontalOptions="FillAndExpand" Padding="20,40"> <Button x:Name="RegisterButton" Text="Register" Clicked="RegisterButtonClicked" /> <Button x:Name="DeregisterButton" Text="Deregister" Clicked="DeregisterButtonClicked" /> </StackLayout>
Теперь в MainPage.xaml.csдобавьте поле резервного поля для хранения ссылки на реализацию INotificationRegistrationService.
readonly INotificationRegistrationService _notificationRegistrationService;
В конструкторе
MainPage устраните реализациюINotificationRegistrationService с помощьюServiceContainer и назначьте его полю .notificationRegistrationService public MainPage() { InitializeComponent(); _notificationRegistrationService = ServiceContainer.Resolve<INotificationRegistrationService>(); }
Реализуйте обработчики событий для
RegisterButton икнопки DeregisterButton события clicked , вызывающиесоответствующие методы регистрации deregister .void RegisterButtonClicked(object sender, EventArgs e) => _notificationRegistrationService.RegisterDeviceAsync().ContinueWith((task) => { ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device registered"); }); void DeregisterButtonClicked(object sender, EventArgs e) => _notificationRegistrationService.DeregisterDeviceAsync().ContinueWith((task) => { ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device deregistered"); }); void ShowAlert(string message) => MainThread.BeginInvokeOnMainThread(() => DisplayAlert("PushDemo", message, "OK").ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }));
Теперь в App.xaml.csубедитесь, что на следующие пространства имен ссылаются следующие пространства имен.
using PushDemo.Models; using PushDemo.Services; using Xamarin.Essentials; using Xamarin.Forms;
Реализуйте обработчик событий для события IPushDemoNotificationActionServiceActionTriggered.
void NotificationActionTriggered(object sender, PushDemoAction e) => ShowActionAlert(e); void ShowActionAlert(PushDemoAction action) => MainThread.BeginInvokeOnMainThread(() => MainPage?.DisplayAlert("PushDemo", $"{action} action received", "OK") .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }));
В конструкторе
app устраните реализациюIPushNotificationActionService с помощью ServiceServiceContainer и подпишитесь на событиеIPushDemoNotificationAction ActionTriggered .public App() { InitializeComponent(); ServiceContainer.Resolve<IPushDemoNotificationActionService>() .ActionTriggered += NotificationActionTriggered; MainPage = new MainPage(); }
Заметка
Это просто для демонстрации получения и распространения действий push-уведомлений. Как правило, они будут обрабатываться автоматически, например переход к определенному представлению или обновлению некоторых данных, а не отображение оповещения через корневую страницу, MainPage в этом случае.
Настройка собственного проекта Android для push-уведомлений
Проверка имени и разрешений пакета
В
PushDemo.Android откройтепараметры проекта приложения Androidиз раздела "Сборка ". Убедитесь, что имя пакета
соответствует значению, используемому в проекте консоли Firebase PushDemo. Имя пакета было в формате com.<organization>.pushdemo
.Установите для
минимальной версии Android значениеуровня API 8.0 (уровень API 26) и целевой версии Android для последней уровня API .Заметка
Для целей этого руководства поддерживаются только те устройства, на которых запущены уровня API 26 и более поздних версий.
Убедитесь, что разрешения INTERNET и READ_PHONE_STATE включены в обязательных разрешений.
Нажмите кнопку ОК
Добавление базовых и пакетов Xamarin Google Play Services и Xamarin.Firebase.Messaging
В
PushDemo.Android элемент управления щелкните в папке пакетов, а затем выберите Управление пакетами NuGet... .Выполните поиск Xamarin.GooglePlayServices.Base (не ) и убедитесь, что он установлен.
Выполните поиск Xamarin.Firebase.Messaging и убедитесь, что он установлен.
Щелкните
Добавить пакеты , а затем щелкнитеПринять при появлении запроса на принятие условий лицензии.
Добавление JSON-файла служб Google
Элемент управления + щелкните в проекте
PushDemo.Android
, а затем выберите существующий файл... в меню "Добавить".Выберите скачанный ранее файл google-services.json при настройке проекта PushDemo в консоли Firebase и нажмите кнопку Открыть.
При появлении запроса выберите Копировать файл в каталог.
Элемент управления Щелкните в файлеgoogle-services.json из проекта, а затем убедитесь, что GoogleServicesJson задано какдействие сборки.
Обработка push-уведомлений для Android
элемент управления щелкните в проекте, выберите создать папку в меню"Добавить ", а затем щелкнитеДобавить с помощью службв качестве имени папки .Элемент управления щелкните в папке служб, а затем выберите Создать файл... в меню"Добавить ".Выберите
Общие пустого класса , введитеDeviceInstallationService.cs дляимени, а затем нажмите кнопку Создать добавить следующую реализацию.using System; using Android.App; using Android.Gms.Common; using PushDemo.Models; using PushDemo.Services; using static Android.Provider.Settings; namespace PushDemo.Droid.Services { public class DeviceInstallationService : IDeviceInstallationService { public string Token { get; set; } public bool NotificationsSupported => GoogleApiAvailability.Instance .IsGooglePlayServicesAvailable(Application.Context) == ConnectionResult.Success; public string GetDeviceId() => Secure.GetString(Application.Context.ContentResolver, Secure.AndroidId); public DeviceInstallation GetDeviceInstallation(params string[] tags) { if (!NotificationsSupported) throw new Exception(GetPlayServicesError()); if (string.IsNullOrWhiteSpace(Token)) throw new Exception("Unable to resolve token for FCM"); var installation = new DeviceInstallation { InstallationId = GetDeviceId(), Platform = "fcm", PushChannel = Token }; installation.Tags.AddRange(tags); return installation; } string GetPlayServicesError() { int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Application.Context); if (resultCode != ConnectionResult.Success) return GoogleApiAvailability.Instance.IsUserResolvableError(resultCode) ? GoogleApiAvailability.Instance.GetErrorString(resultCode) : "This device is not supported"; return "An error occurred preventing the use of push notifications"; } } }
Заметка
Этот класс предоставляет уникальный идентификатор (используя Secure.AndroidId) в рамках полезных данных регистрации концентратора уведомлений.
Добавьте еще один
пустой класс в папку службс именем PushNotificationFirebaseMessagingService.cs , а затем добавьте следующую реализацию.using Android.App; using Android.Content; using Firebase.Messaging; using PushDemo.Services; namespace PushDemo.Droid.Services { [Service] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class PushNotificationFirebaseMessagingService : FirebaseMessagingService { IPushDemoNotificationActionService _notificationActionService; INotificationRegistrationService _notificationRegistrationService; IDeviceInstallationService _deviceInstallationService; IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = ServiceContainer.Resolve<IPushDemoNotificationActionService>()); INotificationRegistrationService NotificationRegistrationService => _notificationRegistrationService ?? (_notificationRegistrationService = ServiceContainer.Resolve<INotificationRegistrationService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>()); public override void OnNewToken(string token) { DeviceInstallationService.Token = token; NotificationRegistrationService.RefreshRegistrationAsync() .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }); } public override void OnMessageReceived(RemoteMessage message) { if(message.Data.TryGetValue("action", out var messageAction)) NotificationActionService.TriggerAction(messageAction); } } }
В MainActivity.csубедитесь, что в верхней части файла добавлены следующие пространства имен.
using System; using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using Android.Runtime; using Firebase.Iid; using PushDemo.Droid.Services; using PushDemo.Services;
В MainActivity.csзадайте LaunchMode значение SingleTop, чтобы MainActivity не будет создано повторно при открытии.
[Activity( Label = "PushDemo", LaunchMode = LaunchMode.SingleTop, Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
Добавьте частные свойства и соответствующие поля резервной копии для хранения ссылки на реализацию
IPushNotificationActionService иIDeviceInstallationService. IPushDemoNotificationActionService _notificationActionService; IDeviceInstallationService _deviceInstallationService; IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = ServiceContainer.Resolve<IPushDemoNotificationActionService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>());
Реализуйте интерфейс IOnSuccessListener, чтобы получить и сохранить маркер Firebase.
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener { ... public void OnSuccess(Java.Lang.Object result) => DeviceInstallationService.Token = result.Class.GetMethod("getToken").Invoke(result).ToString(); }
Добавьте новый метод с именем
ProcessNotificationActions , который проверяет, имеет ли заданноенамерение дополнительное значение с именем действие . Условно активируйте это действие с помощью реализации IPushDemoNotificationActionService.void ProcessNotificationActions(Intent intent) { try { if (intent?.HasExtra("action") == true) { var action = intent.GetStringExtra("action"); if (!string.IsNullOrEmpty(action)) NotificationActionService.TriggerAction(action); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } }
Переопределите метод onNewIntent
для вызова метода ProcessNotificationActions .protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); ProcessNotificationActions(intent); }
Заметка
Так как
LaunchMode для действия задано значение SingleTop ,Намерение будет отправлено в существующий экземплярдействия через Метод OnNewIntent вместо методаOnCreate , поэтому необходимо обрабатывать входящее намерение как вOnCreate , так иметоды OnNewIntent .Обновите метод OnCreate, чтобы сразу после
Bootstrap.Begin
вызоваbase.OnCreate
передать реализацию IDeviceInstallationService.Bootstrap.Begin(() => new DeviceInstallationService());
В том же методе условным вызовом GetInstanceId в экземпляре FirebaseApp сразу после вызова
Bootstrap.Begin
, добавление MainActivity в качестве IOnSuccessListener.if (DeviceInstallationService.NotificationsSupported) { FirebaseInstanceId.GetInstance(Firebase.FirebaseApp.Instance) .GetInstanceId() .AddOnSuccessListener(this); }
По-прежнему в OnCreateвызовите ProcessNotificationActions сразу после вызова
LoadApplication
передачи текущего Намерения.... LoadApplication(new App()); ProcessNotificationActions(Intent);
Заметка
Необходимо повторно зарегистрировать приложение при каждом запуске и остановить его от сеанса отладки, чтобы продолжить получение push-уведомлений.
Настройка собственного проекта iOS для push-уведомлений
Настройка Info.plist и Entitlements.plist
Убедитесь, что вы вошли в учетную запись разработчика Apple в настройках Visual Studio>...>публикации>учетных записей разработчик ов Apple и скачаны соответствующие сертификат и профиль подготовки. Эти ресурсы должны были быть созданы в рамках предыдущих шагов.
В
PushDemo.iOS откройтеInfo.plist и убедитесь, что bundleIdentifierсоответствует значению, которое использовалось для соответствующего профиля подготовки на портале разработчиков Apple . BundleIdentifier был в форматеcom.<organization>.PushDemo
.В том же файле задайте минимальную версию системы значение 13.0.
Заметка
Для целей этого руководства поддерживаются только те устройства, которые работают iOS 13.0 и более поздних версий.
Откройте параметры проекта для PushDemo.iOS (дважды щелкните проект).
В параметрах проектав разделе Сборка >подписывание пакета iOS убедитесь, что учетная запись разработчика выбрана в разделе Team. Затем убедитесь, что выбран параметр "Автоматическое управление подписыванием", а профиль подписывания и подготовки автоматически выбраны.
Заметка
Если сертификат подпис и
и профиль подготовки не выбраны автоматически, выберите подготовки вручную, а затем щелкните параметры подписи пакета . Убедитесь, что подписывание удостоверения иPushDemo конкретный профиль подготовки выбран для профиля подготовкидля отладки иконфигурации выпуска , гарантируя, чтоiPhone выбран дляплатформы платформы.В
PushDemo.iOS откройтеразрешения.p list и убедитесь, чтовключить push-уведомления проверяется при просмотре на вкладкеправ . Затем убедитесь, что для параметра среды APSзадано значение разработки при просмотре на вкладке источника.
Обработка push-уведомлений для iOS
Элемент управления + Щелкните в проекте PushDemo.i OS, выберите Создать папку в меню "Добавить", а затем "Добавить" с помощью служб в качестве имени папки.
Элемент управления щелкните в папке служб, а затем выберите Создать файл... в меню"Добавить ".Выберите
Общие пустого класса , введитеDeviceInstallationService.cs дляимени, а затем нажмите кнопку Создать добавить следующую реализацию.using System; using PushDemo.Models; using PushDemo.Services; using UIKit; namespace PushDemo.iOS.Services { public class DeviceInstallationService : IDeviceInstallationService { const int SupportedVersionMajor = 13; const int SupportedVersionMinor = 0; public string Token { get; set; } public bool NotificationsSupported => UIDevice.CurrentDevice.CheckSystemVersion(SupportedVersionMajor, SupportedVersionMinor); public string GetDeviceId() => UIDevice.CurrentDevice.IdentifierForVendor.ToString(); public DeviceInstallation GetDeviceInstallation(params string[] tags) { if (!NotificationsSupported) throw new Exception(GetNotificationsSupportError()); if (string.IsNullOrWhiteSpace(Token)) throw new Exception("Unable to resolve token for APNS"); var installation = new DeviceInstallation { InstallationId = GetDeviceId(), Platform = "apns", PushChannel = Token }; installation.Tags.AddRange(tags); return installation; } string GetNotificationsSupportError() { if (!NotificationsSupported) return $"This app only supports notifications on iOS {SupportedVersionMajor}.{SupportedVersionMinor} and above. You are running {UIDevice.CurrentDevice.SystemVersion}."; if (Token == null) return $"This app can support notifications but you must enable this in your settings."; return "An error occurred preventing the use of push notifications"; } } }
Заметка
Этот класс предоставляет уникальный идентификатор (используя значение UIDevice.IdentifierForVendor) и полезные данные регистрации концентратора уведомлений.
Добавьте новую папку в проект
PushDemo.iOS с именем расширения, а затем добавьте в нее пустой класс с помощью следующей реализации.NSDataExtensions.cs using System.Text; using Foundation; namespace PushDemo.iOS.Extensions { internal static class NSDataExtensions { internal static string ToHexString(this NSData data) { var bytes = data.ToArray(); if (bytes == null) return null; StringBuilder sb = new StringBuilder(bytes.Length * 2); foreach (byte b in bytes) sb.AppendFormat("{0:x2}", b); return sb.ToString().ToUpperInvariant(); } } }
В AppDelegate.csубедитесь, что в начало файла добавлены следующие пространства имен.
using System; using System.Diagnostics; using System.Threading.Tasks; using Foundation; using PushDemo.iOS.Extensions; using PushDemo.iOS.Services; using PushDemo.Services; using UIKit; using UserNotifications; using Xamarin.Essentials;
Добавьте частные свойства и соответствующие поля резервной копии для хранения ссылки на реализации IPushDemoNotificationActionService, INotificationRegistrationServiceи реализации IDeviceInstallationService.
IPushDemoNotificationActionService _notificationActionService; INotificationRegistrationService _notificationRegistrationService; IDeviceInstallationService _deviceInstallationService; IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = ServiceContainer.Resolve<IPushDemoNotificationActionService>()); INotificationRegistrationService NotificationRegistrationService => _notificationRegistrationService ?? (_notificationRegistrationService = ServiceContainer.Resolve<INotificationRegistrationService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>());
Добавьте метод RegisterForRemoteNotifications
для регистрации параметров уведомлений пользователей, а затем для удаленных уведомлений с APNS. void RegisterForRemoteNotifications() { MainThread.BeginInvokeOnMainThread(() => { var pushSettings = UIUserNotificationSettings.GetSettingsForTypes( UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, new NSSet()); UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings); UIApplication.SharedApplication.RegisterForRemoteNotifications(); }); }
Добавьте метод CompleteRegistrationAsync, чтобы задать значение свойства
IDeviceInstallationService.Token
. Обновите регистрацию и кэшируйте маркер устройства, если он был обновлен с момента последнего хранения.Task CompleteRegistrationAsync(NSData deviceToken) { DeviceInstallationService.Token = deviceToken.ToHexString(); return NotificationRegistrationService.RefreshRegistrationAsync(); }
Добавьте метод ProcessNotificationActions
для обработки данных уведомлений NSDictionary и условного вызоваNotificationActionService.TriggerAction .void ProcessNotificationActions(NSDictionary userInfo) { if (userInfo == null) return; try { var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString; if (!string.IsNullOrWhiteSpace(actionValue?.Description)) NotificationActionService.TriggerAction(actionValue.Description); } catch (Exception ex) { Debug.WriteLine(ex.Message); } }
Переопределите метод
RegisteredForRemoteNotifications , передав аргумент deviceToken методуCompleteRegistrationA sync.public override void RegisteredForRemoteNotifications( UIApplication application, NSData deviceToken) => CompleteRegistrationAsync(deviceToken).ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; });
Переопределите метод
ReceivedRemoteNotification, передав аргумент userInfo методуProcessNotificationActions .public override void ReceivedRemoteNotification( UIApplication application, NSDictionary userInfo) => ProcessNotificationActions(userInfo);
Переопределите метод FailedToRegisterForRemoteNotifications для записи ошибки.
public override void FailedToRegisterForRemoteNotifications( UIApplication application, NSError error) => Debug.WriteLine(error.Description);
Заметка
Это очень много заполнителя. Необходимо реализовать правильную обработку журналов и ошибок для рабочих сценариев.
Обновите метод FinishedLaunching
Bootstrap.Begin
, чтобы сразу после вызоваForms.Init
передать реализацию IDeviceInstallationService.Bootstrap.Begin(() => new DeviceInstallationService());
В том же методе условно запрашивает авторизацию и регистрируется для удаленных уведомлений сразу после
Bootstrap.Begin
.if (DeviceInstallationService.NotificationsSupported) { UNUserNotificationCenter.Current.RequestAuthorization( UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound, (approvalGranted, error) => { if (approvalGranted && error == null) RegisterForRemoteNotifications(); }); }
По-прежнему в FinishedLaunching вызовите ProcessNotificationActions сразу после вызова
LoadApplication
, если аргумент параметров содержит аргумент UIApplication.LaunchOptionsRemoteNotificationKey передачи итогового объекта userInfo.using (var userInfo = options?.ObjectForKey( UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary) ProcessNotificationActions(userInfo);
Тестирование решения
Теперь вы можете протестировать отправку уведомлений через серверную службу.
Отправка тестового уведомления
Откройте новую вкладку в Postman.
Задайте для запроса POSTи введите следующий адрес:
https://<app_name>.azurewebsites.net/api/notifications/requests
Если вы решили выполнить аутентификацию клиентов с помощью раздела ключа API, обязательно настройте заголовки запроса, чтобы включить значение apikey.
Ключ Ценность apikey <your_api_key> Выберите параметр
необработанных длятекста, а затем выберите JSON из списка параметров форматирования, а затем добавьте некоторые заполнителисодержимое JSON :{ "text": "Message from Postman!", "action": "action_a" }
Нажмите кнопку код, которая находится под кнопкой Сохранить в правом верхнем углу окна. Запрос должен выглядеть примерно так, как показано в следующем примере при отображении
HTML- (в зависимости от того, включен ли заголовок apikey). POST /api/notifications/requests HTTP/1.1 Host: https://<app_name>.azurewebsites.net apikey: <your_api_key> Content-Type: application/json { "text": "Message from backend service", "action": "action_a" }
Запустите приложение pushDemo
на одной или обеих целевых платформах ( Android иiOS ).Заметка
Если вы тестируете Android убедитесь, что вы не работаете в отладкеили если приложение было развернуто, запустив приложение, принудительно закройте приложение и запустите его снова с средства запуска.
В приложении PushDemo нажмите кнопку Зарегистрировать.
Вернитесь в Postman, закройте окно создания фрагментов кода (если это еще не сделано), а затем нажмите кнопку Отправить.
Убедитесь, что вы получите ответ
200 OK в , а оповещение отображается в приложении сPostman действие ActionA, полученное .Закройте приложение pushDemo
, а затем нажмите кнопку Отправить еще раз в .Postman Убедитесь, что вы получите ответ 200 OK в Postman еще раз. Убедитесь, что уведомление отображается в области уведомлений для приложения PushDemo с правильным сообщением.
Коснитесь уведомления, чтобы убедиться, что оно открывает приложение и отображает действие ActionA, полученное оповещение.
В Postmanизмените текст предыдущего запроса, чтобы отправить автоматическое уведомление, указывающее action_b вместо action_a для значения действия.
{ "action": "action_b", "silent": true }
При открытии приложения нажмите кнопку Отправить в Postman.
Убедитесь, что в
появитPostman ся ответ , полученное.ОК 200 ОК, а недействие ActionA Закройте приложение pushDemo
, а затем нажмите кнопку Отправить еще раз в .Postman Убедитесь, что вы получите ответ 200 ОК в Postman и что автоматическое уведомление не отображается в области уведомлений.
Устранение неполадок
Нет ответа от серверной службы
При локальном тестировании убедитесь, что серверная служба запущена и использует правильный порт.
Если тестирование на приложения API Azure, проверьте, запущена ли служба и была развернута и запущена без ошибок.
Убедитесь, что вы правильно указали базовый адрес в Postman или в конфигурации мобильного приложения при тестировании через клиент. Базовый адрес должен быть https://<api_name>.azurewebsites.net/
или https://localhost:5001/
при локальном тестировании.
Не получая уведомления в Android после запуска или остановки сеанса отладки
Убедитесь, что вы снова зарегистрируетесь после запуска или остановки сеанса отладки. Отладчик приведет к созданию нового маркера Firebase. Также необходимо обновить установку центра уведомлений.
Получение кода состояния 401 из серверной службы
Убедитесь, что вы задаете заголовок запроса apikey
Если при локальном тестировании эта ошибка возникает, убедитесь, что значение ключа, определенное в конфигурации клиента, соответствует значению
Если вы тестируетеприложения API
Заметка
Если вы создали или изменили этот параметр после развертывания серверной службы, необходимо перезапустить службу, чтобы она вступила в силу.
Если вы решили не выполнять проверку подлинности клиентов
Получение кода состояния 404 из серверной службы
Убедитесь, что конечная точка и метод HTTP-запроса верны. Например, конечные точки должны быть примерно следующими:
-
[PUT]
https://<api_name>.azurewebsites.net/api/notifications/installations
-
[DELETE]
https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
-
[POST]
https://<api_name>.azurewebsites.net/api/notifications/requests
Или при локальном тестировании:
-
[PUT]
https://localhost:5001/api/notifications/installations
-
[DELETE]
https://localhost:5001/api/notifications/installations/<installation_id>
-
[POST]
https://localhost:5001/api/notifications/requests
При указании базового адреса в клиентском приложении убедитесь, что он заканчивается /
. Базовый адрес должен быть https://<api_name>.azurewebsites.net/
или https://localhost:5001/
при локальном тестировании.
Не удается зарегистрировать и отображается сообщение об ошибке центра уведомлений
Убедитесь, что тестовое устройство имеет сетевое подключение. Затем определите код состояния ответа Http, задав точку останова, чтобы проверить значение свойства StatusCode
Ознакомьтесь с предыдущими предложениями по устранению неполадок, применимыми в зависимости от кода состояния.
Задайте точку останова в строках, возвращающих эти определенные коды состояния для соответствующего API. Затем попробуйте вызвать серверную службу при локальной отладке.
Убедитесь, что серверная служба работает должным образом с помощью Postman с помощью соответствующей полезных данных. Используйте фактические полезные данные, созданные клиентским кодом для платформы.
Просмотрите разделы конфигурации для конкретной платформы, чтобы убедиться, что никаких шагов не было пропущено. Убедитесь, что подходящие значения разрешаются для installation id
и token
переменных для соответствующей платформы.
Не удается устранить идентификатор сообщения об ошибке устройства
Просмотрите разделы конфигурации для конкретной платформы, чтобы убедиться, что никаких шагов не было пропущено.
Связанные ссылки
- Обзор Центров уведомлений Azure
- установка Visual Studio для Mac
- установка Xamarin в Windows
- пакет SDK Центров уведомлений для внутренних операций
- пакет SDK для центров уведомлений на сайте GitHub
- Регистрация с помощью серверной части приложения
- управления регистрацией
- Работа с тегами
- Работа с пользовательскими шаблонами
Дальнейшие действия
Теперь вы должны иметь базовое приложение Xamarin.Forms, подключенное к центру уведомлений через серверную службу, и может отправлять и получать уведомления.
Скорее всего, вам потребуется адаптировать пример, используемый в этом руководстве, чтобы соответствовать собственному сценарию. Кроме того, рекомендуется реализовать более надежную обработку ошибок, логику повторных попыток и ведение журнала.
Центра приложений Visual Studio можно быстро включить в мобильные приложения, предоставляющие аналитику и диагностику для устранения неполадок.