iOS远程推送
在这里插入图片描述APNS远程推送的流程:
1、app 注册到 APNS。
2、APNS 下发 devicetoken 给 app。
3、app 将 device token 发送给 app Server。
4、app Serve 将[消息+device token]发送给 APNS。
5、APNS 根据 device token 推送消息给iOS设备上的app。
实现上述步骤需要一个前提:应用程序的推送证书(开发环境&生产环境两类推送证书)和描述文件(Provisioning Profile)配置完备。苹果会在推送前根据描述文件和 App ID 等信息对应用程序的合法性进行验证。`
Objective-C相关代码
//推送相关逻辑
@interface AppDelegate (AppPush)<UNUserNotificationCenterDelegate>
- (void)registerRemoteNotifications:(UIApplication *)application;
@end
@implementation AppDelegate (AppPush)
- (void)registerRemoteNotifications:(UIApplication *)application {
if (@available(iOS 10, *)) {
UNUserNotificationCenter *notificationCenter = [UNUserNotificationCenter currentNotificationCenter];
notificationCenter.delegate = self;
// 申请权限
[notificationCenter requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSLog(@"申请权限granted = %d", granted);
if (!error && granted) {
NSLog(@"远程通知注册成功");
} else {
NSLog(@"远程通知注册失败error-%@", error);
}
}];
// 获取权限设置 可以获取到用户设定通知的信息
[notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"settings = %@", settings);
}];
} else if ([[UIDevice currentDevice] systemVersion].floatValue >= 8.0) {
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]];
}
// 注册远程通知,获得device Token
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
#pragma mark - <UIApplicationDelegate>
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// 将devicetoken发送给服务端
NSUInteger length = deviceToken.length;
const unsigned char *buffer = deviceToken.bytes;
NSMutableString *token = [NSMutableString stringWithCapacity:(length * 2)];
for (int i = 0; i < length; ++i) {
[token appendFormat:@"%02x", buffer[i]];
}
[kUserDefaults setObject:token forKey:kApp_DeviceToken];
[kUserDefaults synchronize];
NSLog(@"token = %@ ", token);
}
// 适配iOS10之前系统
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(@"didReceiveRemoteNotification-userInfo = %@",userInfo);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
completionHandler(UIBackgroundFetchResultNewData);
if (application.applicationState == UIApplicationStateActive) {
NSLog(@"点击推送唤起app userInfo = %@", userInfo);
} else {
NSLog(@"前台收到推送 userInfo = %@", userInfo);
}
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"didFailToRegisterForRemoteNotificationsWithError-error = %@",error);
}
#pragma mark - <UNUserNotificationCenterDelegate>
// app在前台收到通知时触发
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler API_AVAILABLE(ios(10.0)){
// 前台收到推送,也是可以跟后台收到推送一样,弹出横幅,播放声音并震动的。这要在completionHandler中传入相应的UNNotificationPresentationOptions
completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound |UNNotificationPresentationOptionAlert);
}
// 当用户点击通知时,会触发
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)){
completionHandler(); // 系统要求执行这个方法
}
#pragma mark - <private method>
@end
Swift相关代码
extension AppDelegate {
// MARK: - 注册远程推送
func registerRemoteNotifications(with application: UIApplication) {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.requestAuthorization(options: [.alert,.badge,.sound]) { (isGrand, error) in
DispatchQueue.main.async {
if error != nil && isGrand {
print("用户允许了推送权限")
}else{
print("用户拒绝了推送权限")
}
}
}
// 适配iOS10以前的设备
UIApplication.shared.registerUserNotificationSettings(.init(types:[.alert,.badge,.sound], categories:nil))
// 注册远程通知,获得device Token
UIApplication.shared.registerForRemoteNotifications()
}
// MARK: iOS10以前的设备 registerUserNotificationSettings会触发notificationSettings
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types.isEmpty {
print("用户拒绝了推送权限")
}else{
print("用户允许了推送权限")
}
}
// MARK: - <UIApplicationDelegate>
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// 将devicetoken发送给服务端
let deviceTokenString = deviceToken.reduce("",{$0 + String(format:"%02x",$1)})
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("didFailToRegisterForRemoteNotificationsWithError-error = \(error)")
}
// MARK: - 收到推送
// 适配iOS10之前系统
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
if application.applicationState == .inactive {
print("点击推送唤起app userInfo=\(userInfo)")
}else{
print("前台收到推送 userInfo=\(userInfo)")
}
}
// MARK: <UNUserNotificationCenterDelegate>
// MARK: app在前台收到通知时触发
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// 前台收到推送,也是可以跟后台收到推送一样,弹出横幅,播放声音并震动的。这要在completionHandler中传入相应的UNNotificationPresentationOptions
completionHandler([.sound,.alert])
}
// MARK: 当用户点击通知时,会触发
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
//handleUserResponse(userInfo:userInfo)
// 系统要求执行这个方法
completionHandler()
}
}
// MARK: - 如果app已经被杀死,那么app会被重新启动,我们需要在app加载完成后处理用户的响应。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let removePushUserInfo = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification]{
// 处理用户收到推送后的响应
NotificationUtil.shared.handleUserResponse(userInfo:removePushUserInfo as! [AnyHashable:Any])
}
return true
}
网友评论