iOS
Всплывающие уведомления
Поиск…
Синтаксис
- UIUserNotificationSettings.types: UIUserNotificationType // Битовая маска типов уведомлений, которые разрешено использовать вашему приложению
- UIUserNotificationSettings.categories: Установить // Зарегистрированные группы действий приложения
параметры
параметр | Описание |
---|---|
USERINFO | Словарь, содержащий информацию о удаленном уведомлении, потенциально включающий номер значка для значка приложения, звуковой сигнал оповещения, предупреждающее сообщение, идентификатор уведомления и пользовательские данные. |
Регистрация устройства для Push-уведомлений
Чтобы зарегистрировать устройство для push-уведомлений, добавьте следующий код в файл didFinishLaunchingWithOptions
методе didFinishLaunchingWithOptions
:
стриж
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if UIDevice.currentDevice().systemVersion.compare(v, options: .NumericSearch) == NSOrderedAscending {
// Register for Push Notitications, if running iOS < 8
if application.respondsToSelector("registerUserNotificationSettings:") {
let types:UIUserNotificationType = (.Alert | .Badge | .Sound)
let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
} else {
// Register for Push Notifications before iOS 8
application.registerForRemoteNotificationTypes(.Alert | .Badge | .Sound)
}
} else {
var center = UNUserNotificationCenter.currentNotificationCenter()
center.delegate = self
center.requestAuthorizationWithOptions((UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge)) {(granted: Bool, error: NSError) -> Void in
if !error {
UIApplication.sharedApplication().registerForRemoteNotifications()
// required to get the app to do anything at all about push notifications
print("Push registration success.")
} else {
print("Push registration FAILED")
print("ERROR: \(error.localizedFailureReason!) - \(error.localizedDescription)")
print("SUGGESTIONS: \(error.localizedRecoveryOptions) - \(error.localizedRecoverySuggestion!)")
})
}
return true
}
Objective-C
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
if( SYSTEM_VERSION_LESS_THAN( @"10.0" ) )
{
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
// iOS 8 Notifications
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
}
else
{
// iOS < 8 Notifications
[application registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}
}
else
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error)
{
if( !error )
{
[[UIApplication sharedApplication] registerForRemoteNotifications]; // required to get the app to do anything at all about push notifications
NSLog( @"Push registration success." );
}
else
{
NSLog( @"Push registration FAILED" );
NSLog( @"ERROR: %@ - %@", error.localizedFailureReason, error.localizedDescription );
NSLog( @"SUGGESTIONS: %@ - %@", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );
}
}];
}
//to check if your App lunch from Push notification
//---------------------------------------------------
//Handel Push notification
if (launchOptions != nil)
{
// Here app will open from pushnotification
//RemoteNotification
NSDictionary* dictionary1 = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
//LocalNotification
NSDictionary* dictionary2 = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (dictionary1 != nil)
{
//RemoteNotification Payload
NSLog(@"Launched from push notification: %@", dictionary1);
//here handle your push notification
}
if (dictionary2 != nil)
{
NSLog(@"Launched from dictionary2dictionary2dictionary2 notification: %@", dictionary2);
double delayInSeconds = 7;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// [self addMessageFromRemoteNotification:dictionary2 updateUI:NO];
});
}
}
else
{}
//------------------------------------------------
Вышеприведенный код попытается связаться с сервером APN для получения токена устройства (предварительные запросы - это то, что APN включены в профиле инициализации iOS).
Как только он устанавливает надежное соединение с сервером APN, сервер предоставляет вам токен устройства.
После добавления вышеприведенного кода добавьте эти методы в класс AppDelegate
:
стриж
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
print("DEVICE TOKEN = \(deviceToken)")
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print(error)
}
Objective-C
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString * deviceTokenString = [[[[deviceToken description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""];
NSLog(@"The generated device token string is : %@",deviceTokenString);
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(@"Failed to get token, error: %@", error.description);
}
Вышеупомянутые методы вызывают в соответствии с сценарием успешности регистрации или сбоя.
Вызов сценария успеха:
стриж
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
print("DEVICE TOKEN = \(deviceToken)")
}
В Swift3:
@objc(userNotificationCenter:willPresentNotification:withCompletionHandler:) @available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
{
//To show notifications in foreground.
print("Userinfo2 \(notification.request.content.userInfo)")
}
Objective-C
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
if(application.applicationState == UIApplicationStateInactive) {
NSLog(@"Inactive - the user has tapped in the notification when app was closed or in background");
//do some tasks
[self handelPushNotification:userInfo];
}
else if (application.applicationState == UIApplicationStateBackground) {
NSLog(@"application Background - notification has arrived when app was in background");
[self handelPushNotification:userInfo];
}
else {
NSLog(@"application Active - notication has arrived while app was opened");
//Show an in-app banner
//do tasks
}
}
Вызов сценария сбоя:
стриж
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print(error)
}
Objective-C
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
Заметка
Если ни один из вышеперечисленных методов не вызван, ваше устройство не может создать надежное соединение с сервером APN, что может быть связано с проблемами доступа в Интернет.
Проверка того, что ваше приложение уже зарегистрировано для Push Notification
стриж
let isPushEnabled = UIApplication.sharedApplication().isRegisteredForRemoteNotifications()
Регистрация для (не интерактивного) Push-уведомления
Логику регистрации для push-уведомления рекомендуется добавлять в AppDelegate.swift
поскольку функции обратного вызова (успех, сбой) будут называться их. Для регистрации выполните следующие действия:
let application = UIApplication.sharedApplication()
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
Затем будет вызываться функция обратного вызова didRegisterUserNotificationSettings
, и в этом случае вы просто запускаете регистр следующим образом:
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
application.registerForRemoteNotifications()
}
И в этом случае будет отображаться системное предупреждение с запросом на получение уведомления о push-уведомлении. Будут вызываться одна из следующих функций обратного вызова:
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var tokenString = ""
for i in 0..<deviceToken.length {
tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
print("Push token: \(tokenString)")
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("didFailToRegisterForRemoteNotificationsWithError: \(error)")
}
В очень редких случаях не вызываются функции отказа или неудачи. Это происходит, когда у вас проблемы с подключением к Интернету или недоступна песочница APNS. Система выполняет вызов API для APNS, чтобы сделать некоторую проверку, так как это не приведет к тому, что ни одна из двух функций callbacks не будет вызвана. Посетите статус системы Apple, чтобы убедиться, что все в порядке.
Обращение с Push Push
Как только пользователь нажимает на push-уведомление, будет вызвана следующая функция обратного вызова. Вы можете разобрать JSON, чтобы получить какую-либо конкретную информацию, отправленную из бэкэнд, которая поможет вам в глубокой привязке:
стриж
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("Received notification: \(userInfo)")
}
Цель C
- (void)application:(UIApplication *)application didReceiveRemoteNotification: (NSDictionary *)userInfo
{
NSLog(@"Received notification: %@", userInfo);
}
iOS 10
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
// iOS 10 will handle notifications through other methods
NSLog(@"Received notification: %@", userInfo);
if( SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO( @"10.0" ) )
{
NSLog( @"iOS version >= 10. Let NotificationCenter handle this one." );
// set a member variable to tell the new delegate that this is background
return;
}
NSLog( @"HANDLE PUSH, didReceiveRemoteNotification: %@", userInfo );
// custom code to handle notification content
if( [UIApplication sharedApplication].applicationState == UIApplicationStateInactive )
{
NSLog( @"INACTIVE" );
completionHandler( UIBackgroundFetchResultNewData );
}
else if( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground )
{
NSLog( @"BACKGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
else
{
NSLog( @"FOREGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSLog( @"Handle push from foreground" );
// custom code to handle push while app is in the foreground
NSLog(@"%@", notification.request.content.userInfo);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler
{
NSLog( @"Handle push from background or closed" );
// if you set a member variable in didReceiveRemoteNotification, you will know if this is from closed or background
NSLog(@"%@", response.notification.request.content.userInfo);
}
Регистрация идентификатора приложения для использования с Push-уведомлениями
Вещи, которые нужно
- Платное членство в программе Apple Developer Program
- Действительный идентификатор и идентификатор приложения для вашего приложения (например, com.example.MyApp), который не используется нигде
- Доступ к developer.apple.com и членскому центру
- Устройство iOS для тестирования (поскольку Push Notifications не работают на Simulator)
Включение доступа APN для идентификатора приложения в Apple Developer Center
1 Войти в developer.apple.com Центр участников (ссылка на главной странице)
2- Перейдите в раздел «Сертификаты»
3- Выберите «Идентификатор приложения» с левой панели
4- Нажмите «+» вверху справа
5- Добавлен флажок Добавить идентификатор приложения с Push Notifications
6- Нажмите на созданный идентификатор приложения и выберите «Изменить».
7 - Нажмите «Настроить» в панели «Push Push»
8 - Откройте приложение Access Keychain Access на вашем Mac
9- В меню «Доступ к цепочке ключей» выберите «Ассистент сертификата» -> «Запросить сертификат» из центра сертификации
10- Введите свою почту в первом текстовом поле
11- Введите свое имя во втором текстовом поле
12 - Оставьте адрес электронной почты CA пустым
13- Выберите «Сохранено на диск», а не «Отправлено по электронной почте» в CA
14 - Нажмите «Продолжить» и загрузите сгенерированный файл
15- Загрузите сгенерированный файл Apple и откройте его, пока доступ к Keychain Access открыт
Включение доступа APN в Xcode
1- Выберите свой проект
Вкладка «Свойства»
3- Найти Push-уведомления и включить его
4-Найти фоновый режим и включить его и проверить удаленные уведомления
Отмена регистрации от Push-уведомлений
Чтобы отменить регистрацию с удаленных уведомлений программно, вы можете использовать
Objective-C
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
стриж
UIApplication.sharedApplication().unregisterForRemoteNotifications()
это похоже на настройку вашего телефона и ручное отключение уведомлений для приложения.
ПРИМЕЧАНИЕ. В редких случаях вам может понадобиться (например: когда ваше приложение больше не поддерживает push-уведомления)
Если вы просто хотите разрешить пользователю временно отключать уведомления. Вы должны реализовать метод удаления маркера устройства в базе данных вашего сервера. иначе, если вы только отключите уведомление локально на своем устройстве, ваш сервер по-прежнему будет отправлять сообщения.
Установка значка значка значка приложения
Используйте следующий фрагмент кода, чтобы установить номер значка из вашего приложения (предположим, что someNumber
был объявлен ранее):
Objective-C
[UIApplication sharedApplication].applicationIconBadgeNumber = someNumber;
стриж
UIApplication.shared.applicationIconBadgeNumber = someNumber
Чтобы полностью удалить значок, просто установите someNumber = 0
.
Тестирование push-уведомлений
Всегда полезно проверить, как работают push-уведомления даже до того, как у вас будет готовна ваша серверная часть, чтобы убедиться, что все правильно настроено на вашей стороне. Очень легко отправить себе push-уведомление, используя следующий PHP-скрипт.
- Сохраните сценарий как файл (например, send_push.php) в той же папке, что и ваш сертификат (разработка или производство)
- Отредактируйте его, чтобы поместить токен вашего устройства, пароль из сертификата
- Выберите правильный путь для открытия соединения, dev_path или prod_path (здесь используется сценарий «Открыть соединение с APNS-сервером»)
- cd в папку в терминале и запустить команду 'php send_push'
- Получать уведомление на своем устройстве
<?php
// Put your device token here (without spaces):
$deviceToken = '20128697f872d7d39e48c4a61f50cb11d77789b39e6fc6b4cd7ec80582ed5229';
// Put your final pem cert name here. it is supposed to be in the same folder as this script
$cert_name = 'final_cert.pem';
// Put your private key's passphrase here:
$passphrase = '1234';
// sample point
$alert = 'Hello world!';
$event = 'new_incoming_message';
// You can choose either of the paths, depending on what kind of certificate you are using
$dev_path = 'ssl://gateway.sandbox.push.apple.com:2195';
$prod_path = 'ssl://gateway.push.apple.com:2195';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $cert_name);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
$dev_path, $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
// it should be as short as possible
// if the notification doesnt get delivered that is most likely
// because the generated message is too long
$body['aps'] = array(
'alert' => $alert,
'sound' => 'default',
'event' => $event
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
Создание сертификата .pem из вашего .cer-файла для перехода к разработчику сервера
Сохранить aps.cer в папке
Откройте «Доступ к ключам» и экспортируйте ключ, находящийся под этим сертификатом, в файл .p12 (назовите его key.p12). Для этого щелкните правой кнопкой мыши и выберите «Экспорт». Сохраните его в той же папке, что и в шаге 1. При экспорте вам будет предложено ввести пароль. Сделайте что-нибудь и запомните.
cd в эту папку в терминале и выполнить следующие команды:
Преобразовать .cer в сертификат .pem
openssl x509 -in aps.cer -inform der -out aps.pem
- Преобразуйте свой ключ в формат .pem. Чтобы открыть ключ, введите пароль, который вы его экспортировали, из брелка на шаге 2. Затем введите другой пароль, который защитит экспортированный файл. Вам будет предложено ввести его дважды для подтверждения.
openssl pkcs12 -nocerts -out key.pem -in key.p12
- Объединение файлов в один файл
cat key.pem aps.pem > final_cert.pem
- Конечный результат final_cert.pem. Передайте его разработчикам сервера с паролем с шага 5, чтобы они могли использовать защищенный сертификат.