1. 使用Cocoapods集成
1.1. 版本升级记录
*最新: 1.0.2 referee优化,减少注册失败率
- 1.0.0 兼容xcode11打包在ios13中deviceToken解析问题
- 0.1.0 兼容xcode11打包在ios13中deviceToken解析问题
0.0.9 修复bug
0.0.7 除去注册限频逻辑7
1.2. Podfile文件
在工程部录下创建Podfile
在Podfile文件中添加一下内容,请升级使用1.0.0及以上版本
source 'source 'https://github.com/cosmos33/MMSpecs'
pod 'PhotonPushSDK','~>1.0.0'在终端切到工程目录(Pofile文件同级),执行pod update命令
用xcode打开*.xcworkspace,运行工程
2. 在工程中直接使用PhotonPushSDK.frame及相关配置
到https://github.com/cosmos33/PhotonPushSDK-iOS 下载Framework
将Framework文件下的两个文件直接拖到工程中
2.1. 库引用检查
- 在导入时,Xcode正常情况下会自动添加引用,但是偶尔也会不添加,注意检查下图中的引用路径,如果报错找不到库或者头文件,一般都是下面的引用没有添加。
2.2. 添加系统依赖库
libc++.tbd
UserNotifications.framework
2.3. 开启推送功能
2.4. 后台运行权限设置
- 为了更好支持消息推送,提供更多的推送样式,提高消息到达率,需要配置后台运行权限:
2.5. Xcode10 建议开启Wifi信息授权
- 在 Xcode 10.x 以上,找到应用Target设置中的Capabilities -> Access WiFi Information,确认开关已经设为ON状态。
- 备注: 使用NotificationService,同样开启Access WiFi Information设置。
3. 编写代码集成
3.1. 初始化SDK并注册APNs
- 在[AppDelegate didFinishLaunchingWithOptions]方法中调用SDK初始化方法,传入Push平台分配的 AppID,同时,调用APNs注册方法,尝试获取APNs DeviceToken。示例代码如下:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[MoPushManager initSDK: APP_ID];
[MoPushManager setBuildStat:MOBuildStat_RELEASE];
#ifdef DEBUG
[MoPushManager setBuildStat:MOBuildStat_DEBUG];
#elif INHOUSE
[MoPushManager setBuildStat:MOBuildStat_INHOUSE];
#endif
[MoPushManager addCommandListener:@selector(onCommand:) target:self];
[self registerRemoteNotification];
return YES;
}
- (void) onCommand:(CallbackMessage*) message {
NSLog(@"AppDelegate callback ----->> cmd:%d, code: %d, message:%@", [message command],[message resultCode], [message message]);
}
- 注册APNs获取DeviceToken的流程,根据项目设置的不同以及手机系统版本的不同,注册代码会有所区别,可以参考如下方式进行适配:
/** 注册 APNs */
- (void)registerRemoteNotification {
/*
警告:Xcode8 需要手动开启"TARGETS -> Capabilities -> Push Notifications"
*/
/*
警告:该方法需要开发者自定义,以下代码根据 APP 支持的 iOS 系统不同,代码可以对应修改。
以下为演示代码,注意根据实际需要修改,注意测试支持的 iOS 系统都能获取到 DeviceToken
*/
if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 // Xcode 8编译会调用
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay) completionHandler:^(BOOL granted, NSError *_Nullable error) {
if (!error) {
NSLog(@"request authorization succeeded!");
}
}];
[[UIApplication sharedApplication] registerForRemoteNotifications];
#else // Xcode 7编译会调用
UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerForRemoteNotifications];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#endif
} else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerForRemoteNotifications];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeBadge);
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
}
}
3.2. 实现注册APNs
//接收appdelegate相关的回调
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
// 通过此可获取deviceToken
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
// 通过此处理接收到的push
// 注:在获取apns的内容中,file_path的路径需要额外注意其地址:可能是"http://push-task-target.oss-cn-beijing.aliyuncs.com/notify_icon/5135615a33384237b9f6612f2e9a236a/2116588-em345.png?Expires=1556525683&OSSAccessKeyId=LTAIZ1km10AKou8w&Signature=2m8gwBZBPB162jI3%2FcJsN9ynpSw%3D"或者"http://push-task-target.oss-cn-beijing.aliyuncs.com/notify_icon/5135615a33384237b9f6612f2e9a236a/2116588-em345.png",所以一定要处理好缓存地址的路径问题,缓存失败获取不到相关资源
}
// 使用ios10上版本提供的UNUserNotificationCenter
//同时需要实现 UNUserNotificationCenterDelegate 协议并实现其中的以下两个方法。
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
//iOS 10: App在前台获取到通知
// 注:在获取apns的内容中,file_path的路径需要额外注意其地址:可能是"http://push-task-target.oss-cn-beijing.aliyuncs.com/notify_icon/5135615a33384237b9f6612f2e9a236a/2116588-em345.png?Expires=1556525683&OSSAccessKeyId=LTAIZ1km10AKou8w&Signature=2m8gwBZBPB162jI3%2FcJsN9ynpSw%3D"或者"http://push-task-target.oss-cn-beijing.aliyuncs.com/notify_icon/5135615a33384237b9f6612f2e9a236a/2116588-em345.png",所以一定要处理好缓存地址的路径问题,缓存失败获取不到相关资源
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler{
// iOS 10: 点击通知进入App时触发
}
注:
苹果在ios10及以后提供的一个更加精准的处理,大概的分析如下(如果疑问,可查找相关的apple文档和资料)
在iOS10.0之前iOS用来接收远程通知只能通过
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
}
来进行远程通知的接收,但是无法正确判断远程通知带来的goto点击通知横幅的跳转逻辑。
只能判断在非 UIApplicationStateActive 状态下都会将goto保存,并在 applicationDidBecomeActive 和 viewDidAppear 的时候会进行跳转。但是这样操作有个问题,当app处于inactive的情况下,例如从顶部下滑进入通知中心后,收到一条带goto的远程通知不点击通知横幅也会跳转。所以寻找了新的解决方案。
通过实验了实现UNUserNotificationCenterDelegate的两个代理方法后,与之前的通知方法在收到通知和点击通知横幅之后的结果,如下:
实现willPresentNotification后收到
didReceiveRemoteNotification | willPresentNotification | |
---|---|---|
冷启 | \ | \ |
active | NO | YES |
inactive | NO | YES |
background | NO | NO |
实现didReceiveNotificationResponse后点击
didReceiveRemoteNotification | didReceiveNotificationResponse | |
---|---|---|
冷启 | NO | YES |
active | \ | \ |
inactive | NO | YES |
background | NO | YES |
未实现willPresentNotification后收到
didReceiveRemoteNotification | |
---|---|
冷启 | \ |
active | YES |
inactive | YES |
background | NO |
未实现didReceiveNotificationResponse后点击
didReceiveRemoteNotification | |
---|---|
冷启 | YES |
active | \ |
inactive | YES |
background | YES |
注: 代表不存在此种情况。 inactive 特指:应用使用期间,滑出推送栏。