一、个推的集成
1.个推的集成可以参考个推的集成文档。
2.初步集成的代码如下:
APPDelegate.h
#import <UIKit/UIKit.h>
// 个推SDK头文件和相关信息宏(测试)
#import "GeTuiSdk.h"
#define kGtAppId @"个推平台登记应用后的AppId"
#define kGtAppKey @"个推平台登记应用后的AppKey"
#define kGtAppSecret @"个推平台登记应用后的AppSecret"
@interface AppDelegate : UIResponder <UIApplicationDelegate, GeTuiSdkDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
APPDelegate.m
#import "ViewController.h"
// iOS10 及以上需导入 UserNotifications.framework
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
#import <UserNotifications/UserNotifications.h>
#endif
@interface AppDelegate ()<UNUserNotificationCenterDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// [ GTSdk ]:是否运行电子围栏Lbs功能和是否SDK主动请求用户定位
[GeTuiSdk lbsLocationEnable:YES andUserVerify:YES];
// [ GTSdk ]:自定义渠道
[GeTuiSdk setChannelId:@"GT-Channel"];
// [ GTSdk ]:使用APPID/APPKEY/APPSECRENT启动个推
[GeTuiSdk startSdkWithAppId:kGtAppId appKey:kGtAppKey appSecret:kGtAppSecret delegate:self];
// 注册APNs - custom method - 开发者自定义的方法
[self registerRemoteNotification];
// 启动页延时加载
[NSThread sleepForTimeInterval:3.0];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init] ];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
[IQKeyboardManager sharedManager].enable = YES;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#pragma mark ========= 个推相关代码 ==========
- (NSString *)formateTime:(NSDate *)date {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm:ss"];
NSString *dateTime = [formatter stringFromDate:date];
return dateTime;
}
#pragma mark - background fetch 唤醒
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// [ GTSdk ]:Background Fetch 恢复SDK 运行
[GeTuiSdk resume];
completionHandler(UIBackgroundFetchResultNewData);
}
#pragma mark - 用户通知(推送) _自定义方法
/** 注册远程通知 */
- (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] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
#endif
} else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
} else {
UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeBadge);
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
}
}
#pragma mark - 远程通知(推送)回调
/** 远程通知注册成功委托 */
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", token);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"token" message:token delegate:nil cancelButtonTitle:@"cancle" otherButtonTitles:@"ok", nil];
[alertView show];
// [ GTSdk ]:向个推服务器注册deviceToken
[GeTuiSdk registerDeviceToken:token];
}
/** 远程通知注册失败委托 */
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"%@", error.localizedDescription);
}
#pragma mark - APP运行中接收到通知(推送)处理 - iOS 10以下版本收到推送
/** APP已经接收到“远程”通知(推送) - (App运行在后台) */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
// [ GTSdk ]:将收到的APNs信息传给个推统计
[GeTuiSdk handleRemoteNotification:userInfo];
// 显示APNs信息到页面
NSString *record = [NSString stringWithFormat:@"[APN]%@, %@", [NSDate date], userInfo];
NSLog(@"%@", record);
completionHandler(UIBackgroundFetchResultNewData);
}
#pragma mark - iOS 10中收到推送消息
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// iOS 10: App在前台获取到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSLog(@"willPresentNotification:%@", notification.request.content.userInfo);
// 根据APP需要,判断是否要提示用户Badge、Sound、Alert
completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
}
// iOS 10: 点击通知进入App时触发
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSLog(@"didReceiveNotification:%@", response.notification.request.content.userInfo);
[GeTuiSdk resetBadge]; //重置角标计数
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; // APP 清空角标
// [ GTSdk ]:将收到的APNs信息传给个推统计
[GeTuiSdk handleRemoteNotification:response.notification.request.content.userInfo];
completionHandler();
}
#endif
#pragma mark - GeTuiSdkDelegate
/** SDK启动成功返回cid */
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId {
// [ GTSdk ]:个推SDK已注册,返回clientId
NSLog(@">>[GTSdk RegisterClient]:%@", clientId);
}
/** SDK收到透传消息回调 */
- (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {
// [ GTSdk ]:汇报个推自定义事件(反馈透传消息)
[GeTuiSdk sendFeedbackMessage:90001 andTaskId:taskId andMsgId:msgId];
// 数据转换
NSString *payloadMsg = nil;
if (payloadData) {
payloadMsg = [[NSString alloc] initWithBytes:payloadData.bytes length:payloadData.length encoding:NSUTF8StringEncoding];
}
// 页面显示日志
NSString *record = [NSString stringWithFormat:@" %@, %@%@", [self formateTime:[NSDate date]], payloadMsg, offLine ? @"<离线消息>" : @""];
NSLog(@"%@", record);
// 控制台打印日志
NSString *msg = [NSString stringWithFormat:@"%@ : %@%@", [self formateTime:[NSDate date]], payloadMsg, offLine ? @"<离线消息>" : @""];
NSLog(@">>[GTSdk ReceivePayload]:%@, taskId: %@, msgId :%@", msg, taskId, msgId);
}
/** SDK收到sendMessage消息回调 */
- (void)GeTuiSdkDidSendMessage:(NSString *)messageId result:(int)result {
// 页面显示:上行消息结果反馈
NSString *record = [NSString stringWithFormat:@"Received sendmessage:%@ result:%d", messageId, result];
NSLog(@"%@", record);
}
/** SDK遇到错误回调 */
- (void)GeTuiSdkDidOccurError:(NSError *)error {
// 页面显示:个推错误报告,集成步骤发生的任何错误都在这里通知,如果集成后,无法正常收到消息,查看这里的通知。
NSLog(@"%@",error.localizedDescription);
// [_viewController logMsg:[NSString stringWithFormat:@">>>[GexinSdk error]:%@", [error localizedDescription]]];
}
/** SDK运行状态通知 */
- (void)GeTuiSDkDidNotifySdkState:(SdkStatus)aStatus {
// 页面显示更新通知SDK运行状态
NSLog(@"%d", aStatus);
// [_viewController updateStatusView:self];
}
/** SDK设置推送模式回调 */
- (void)GeTuiSdkDidSetPushMode:(BOOL)isModeOff error:(NSError *)error {
// 页面显示错误信息
if (error) {
NSLog(@"%@", error.localizedDescription);
return;
}
// [_viewController logMsg:[NSString stringWithFormat:@">>>[GexinSdkSetModeOff]: %@", isModeOff ? @"开启" : @"关闭"]];
//
// // 页面更新按钮事件
// UIViewController *vc = _naviController.topViewController;
// if ([vc isKindOfClass:[ViewController class]]) {
// ViewController *nextController = (ViewController *) vc;
// [nextController updateModeOffButton:isModeOff];
// }
}
@end
至此,基本的代码集成就完成了,可以进行相关的测试了。
二、个推平台需要做的准备
1.上传APNs的.p12证书,关于证书的请求和转换可以参考如下链接:http://docs.getui.com/mobile/ios/apns/
2.完成证书上传后,我们就可以运行程序了。运行程序我们需要拿到注册推送服务器完成后的设备的:device token。
运行程序按后的截图如下:
网友评论