通常来说项目中的推送功能一般是使用第三方来实现,可以极大的降低开发时间及成本,下面就简单介绍下关于极光推送的一个简易封装使用
集成步骤及使用注意点
/* 远程推送集成指南 (使用极光SDK)
1、准备生产、开发环境.p12文件 http://docs.jpush.io/client/ios_tutorials/#ios_1
2、下载需要集成SDK http://docs.jpush.io/resources/#sdk
2.1 下载 JPush-iOS-SDK ,得到一个lib 和一个Demo,将lib 导入项目中;
libz.tbd ---》 注:Xcode7需要的是libz.tbd;Xcode7以下版本是libz.dylib
2.2 同时创建并配置PushConfig.plist文件在 SDK目录下
2.2 注册帐号:https://www.jpush.cn;
2.3 添加应用名,上传对应环境的.p12文件;此步完成后得到一对字符串 AppKey 和 MasterSecret;
3、在 AppDelegate.m 中复制如下代码:
------AppDelegate.m 的调用示例------------------------------------------------------------
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//配置推送
[ZQPushManager configurePushWithOptions:launchOptions];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[ZQPushManager registerDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[ZQPushManager handleRemoteNotification:userInfo];
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler
{
[ZQPushManager handleRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification
{
[ZQPushManager handleLocalNotificationForRemotePush:notification];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[ZQPushManager configurePushWithOptions:nil];
}
- (void)applicationWillResignActive:(UIApplication *)application {
[ZQPushManager sharedManager].justInBack = YES;
}
------AppDelegate.m 的调用完成----------------------------------------------------------
4、打包给测试开发、生产环境,发布appstore配置;
测试地址包:端口地址为测试环境,证书使用开发证书,测试手机直接连接电脑安装;
正式地址包(避免线上正式用户收到):端口地址为正式环境,证书使用生产证书,测试手机用ad-hoc包安装;
发布appstore:端口地址为正式,证书使用生产证书,发布;
4.1 PushConfig.plist配置说明;
APS_FOR_PRODUCTION (备用参数,暂时不需要配置):0表示开发证书,1表示生产证书;
CHANNEL(不需要配置):在工程 - TARGETS - BuildSetting - SearchPaths - User Header Search Paths
添加PushConfig.plist在工程中的相对路径(列如:$(SRCROOT)/plugIn/JPush/PushConfig.Plist,plugIn、JPush为文件夹))
APP_KEY:配置为极光开发或者生产AppKey;
注意:极光目前通过同一个账号来区分开发和生产环境,而我们后台是通过两个极光账号区别环境(测试账号对应极光开发环境,正式账号对应生产环境),极光并不通过账号来区分ios的环境。
4.2 ZQPushManager.m里在clickRemoteNotification里配置app端口地址;
5、细节注意:
method_2 didReceiveLocalNotification
method_1 didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:
* 在iOS7.0之后,在前台收到远程通知,或者点击了后台的通知,都会调用method_1的方法 ,userInfo就是收到的通知,可根据需要做相应的处理;
5.1 后台收到的远程通知,会自动下拉弹出,而前台收到时,不会弹出,需要单独处理,一般的做法有3种:
5.1.1 转化成本地通知,丢到通知栏;
5.1.2 转化成AlertView弹出;
5.1.3 定义一个和系统通知一样的效果弹出; (PS:这个我还没实现 )
5.2 判断用户是否允许通知;
5.2 5.1.1转换成本地通知时,会调用一次method_2;点击通知栏的本地通知时会再调用一次,要做区分;
5.3 未获得通知授权时候的跳转: @"prefs:root=NOTIFICATIONS_ID&path=com.365sji.iChanl";
5.4 应用内注销远程通知;发送一条极光指定的通知 kJPFNetworkDidCloseNotification;
5.5 开启和注销之间的快速转换:
当用户前往5.2,就判断可能重新激活通知,此时在willEnterForground重新注册通知;
*/
- 创建一个Nsobjct 的类 ( ZQLPushManager )
.h文件
#import <Foundation/Foundation.h>
@interface ZQLPushManager : NSObject
@property (nonatomic) BOOL justInBack;
@property (nonatomic) BOOL clickNotification;
+ (ZQLPushManager *)shareManager;
/// 配置推送
+ (void)configurePushWithOptions:(NSDictionary*)launchOptions;
///注册token
+ (void)registerDeviceToken:(NSData *)deviceToken;
/// 操作收到的远程消息
+ (void)handleRemoteNotification:(NSDictionary*)notification;
/// 远程消息操作完成
+ (void)handleRemoteNotification:(NSDictionary*)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
///处理远程通知转化而来的本地通知
+ (void)handleLocalNotificationForRemotePush:(UILocalNotification*)notification;
/// 处理消息内容
+ (void)clickRemoteNotification:(NSDictionary*)notification;
///清理角标
+ (void)clearBadge;
///是否开启了允许通知
+ (BOOL)isOpenRemoteNotification;
///取消注册通知
+ (void)unregisterRemoteNotifications;
///允许/取消允许通知switch事件 on == 允许通知
+ (void)changeRemotePushState:(UISwitch*)sender;
@end
** .m文件**
#import "ZQLPushManager.h"
#import "JPUSHService.h"
@implementation ZQLPushManager
static ZQLPushManager* manager = nil;
+(ZQLPushManager *)shareManager
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[ZQLPushManager alloc] init];
});
return manager;
}
- (instancetype)init
{
self = [super init];
if (self) {
self.justInBack = NO;
self.clickNotification = NO;
}
return self;
}
/// 配置推送
+ (void)configurePushWithOptions:(NSDictionary*)launchOptions
{
if (![DataManager sharedManager].allowRemotePush){ // 如果用户不允许通知
return;
}else{
// 注册
[self registerRemoteNotification];
[DataManager sharedManager].remotePushStateMaybeChange = NO;
}
// 初始化
[JPUSHService setupWithOption:launchOptions];
// 设置tag和标签
// [self setTagsAndAlias];
// 如果通过点击推送通知启动应用
if (launchOptions != nil) {
NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil) {
[self clickRemoteNotification:dictionary];
[self clearBadge];
}
}
}
/// 注册远程通知
+ (void)registerRemoteNotification
{
// Required
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
//可以添加自定义categories
[JPUSHService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)
categories:nil];
} else {
//categories 必须为nil
[JPUSHService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)
categories:nil];
}
}
///在前台和状态栏收到远程消息
+(void)handleRemoteNotification:(NSDictionary*)notification fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler
{
[ZQLPushManager handleRemoteNotification:notification];
//获取通知的标题和描述
NSString* messageTitle = [[notification objectForKey:@"aps"]objectForKey:@"alert"];
NSString* description = [notification objectForKey:@"videoDesc"];
// 应用从后台点击消息进入
if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive && ([ZQLPushManager shareManager].justInBack)){
[ZQLPushManager clickRemoteNotification:notification];
}else{ //正在通知栏或前台
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.userInfo = notification;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.alertBody = description;
[ZQLPushManager shareManager].clickNotification = NO;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
// 应用正在前台
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
#warning 后续自定义通知效果,仿原生;
// 如果当前控制器不是视频播放控制器
// if (![DataManager sharedManager].isMovieDetailVC) {
kSelfWeak;
UIAlertView* alert = [UIAlertView alertViewWithTitle:messageTitle message:description cancelButtonTitle:@"取消" otherButtonTitles:@[@"前往"] onDismiss:^(NSInteger buttonIndex, NSString *buttonTitle) {
if ([buttonTitle isEqualToString:@"前往"]) {
[weakSelf clickRemoteNotification:notification];
}
} onCancel:^{
[weakSelf clearBadge];
}];
[alert show];
}
// }
}
completionHandler(UIBackgroundFetchResultNewData);
}
///处理远程通知转化而来的本地通知
+ (void)handleLocalNotificationForRemotePush:(UILocalNotification*)notification
{
if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive&&[ZQLPushManager shareManager].justInBack)
{ // 如果用户点击通知进入
[ZQLPushManager clickRemoteNotification:notification.userInfo];
}
[ZQLPushManager shareManager].clickNotification = YES;
}
/// 处理消息
+ (void)clickRemoteNotification:(NSDictionary*)notification
{
[ZQLPushManager shareManager].justInBack = NO;
[self clearBadge];
NSString* videoType = [notification objectForKey:@"videoType"];
NSString* videoTypeValue = [notification objectForKey:@"videoTypeValue"];
UIViewController* destinationVC = nil;
// 如果是通过messageId跳转
if ([[NSString stringBySpaceTrim:videoTypeValue] isEqualToString:@""]) {
NSString* messageId = [notification objectForKey:@"messageId"];
NSString* contentStr = isTrueEnvironment ? @"view/messageDetails.html?newsId=" : @"daziboApp/view/messageDetails.html?newsId=";
NSString* urlStr = [NSString stringWithFormat:@"%@://%@/%@%@",kHttpHead,kServerResourceHost, contentStr,messageId];
NSLog(@"**************%@",urlStr);
// destinationVC = [[XYWebVC alloc] initWithURLString:urlStr];
// destinationVC.navigationItem.title = @"消息";
}else if ([videoType isEqualToString:@"1"]) { //如果是视频ID
// destinationVC = [[MovieDetialVC alloc] initWithVideoId:videoTypeValue];
}else if ([videoType isEqualToString:@"2"]){ //如果是视频网址
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:videoTypeValue]];
// destinationVC = [[XYWebVC alloc] initWithURLString:videoTypeValue];
}else{
return;
}
id rootVC = [[UIApplication sharedApplication] keyWindow].rootViewController;
if ([rootVC isKindOfClass:[CLNavigationController class]]) {
CLNavigationController * navc = (CLNavigationController *)rootVC;
[navc pushViewController:destinationVC animated:YES];
}else{
[rootVC presentViewController:destinationVC animated:YES completion:^{
}];
}
}
///清除角标
+ (void)clearBadge
{
[JPUSHService resetBadge];
[UIApplication sharedApplication].applicationIconBadgeNumber = 1;
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
}
/// 设置tag和标签
+ (void)setTagsAndAlias
{
[JPUSHService setAlias:@"159" callbackSelector:nil object:nil];
[JPUSHService setTags:[NSSet set] callbackSelector:nil object:nil];
[JPUSHService setTags:[NSSet set] alias:nil callbackSelector:nil target:nil];
}
+ (BOOL)isOpenRemoteNotification
{
BOOL isOpenNotification;
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
isOpenNotification = !([[UIApplication sharedApplication]currentUserNotificationSettings].types == 0) ;
} else {
isOpenNotification = !([[UIApplication sharedApplication]enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone);
}
return isOpenNotification;
}
+ (void)unregisterRemoteNotifications
{
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
[[NSNotificationCenter defaultCenter] postNotificationName:kJPFNetworkDidCloseNotification object:nil];
}
+ (void)changeRemotePushState:(UISwitch*)sender
{
if (!sender.on){ //关闭通知
[ZQLPushManager unregisterRemoteNotifications];
}else{ // 打开通知
// 先检查用户在手机设置中是否打开了小自播通知
// 如果未打开,提示用户打开
if (![ZQLPushManager isOpenRemoteNotification]) {
UIAlertView* alert = [UIAlertView alertViewWithTitle:@"提示" message:@"请在 设置 - 通知 中找到iChanl应用,\n勾选允许通知" cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] onDismiss:^(NSInteger buttonIndex, NSString *buttonTitle) {
[DataManager sharedManager].remotePushStateMaybeChange = YES;
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=NOTIFICATIONS_ID&path=com.365sji.iChanl"]];
} onCancel:^{
sender.on = NO;
[DataManager sharedManager].allowRemotePush = sender.on;
}];
[alert show];
}else{ //如果已打开,马上注册推送通知
[ZQLPushManager configurePushWithOptions:nil];
}
[DataManager sharedManager].allowRemotePush = sender.on;
}
}
/* 调用极光API */
+ (void)registerDeviceToken:(NSData *)deviceToken
{
[JPUSHService registerDeviceToken:deviceToken];
}
+ (void)handleRemoteNotification:(NSDictionary*)notification
{
[JPUSHService handleRemoteNotification:notification];
}