美文网首页
推送后传

推送后传

作者: _feiyu_2100 | 来源:发表于2018-05-04 13:49 被阅读62次
带我飞.jpg

前言:推送功能为了提醒用户或者提高应用留活率。关于推送有很多第三方,比如极光,融云,信鸽,其原理也是相同利用APNS推送机制 。今天写这篇文章的主要目的是为了推送,但是关于推送的文章、博客很多,所以重点还是讲推送后续-------推送后的页面跳转功能。

主要以极光推送为例
准备条件:极光账号、苹果开发账号、一部手机、一个xcode
虽然使用的第三方推送我们也要明白其原理啦
苹果APNS推送原理:


苹果APNS推送原理.jpg

Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的缩写,也就是苹果的推送服务器。
上图可以分为三个阶段:
第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

而使用极光,极光代替了应用的服务器,极光推送原理 jpush_ios.png

从上图可以看出,JPush iOS Push 包括 2 个部分,APNs 推送(代理),与 JPush 应用内消息。红色部分是 APNs 推送,JPush 代理开发者的应用(需要基于开发者提供的应用证书),向苹果 APNs 服务器推送。由 APNs Server 推送到 iOS 设备上。蓝色部分是 JPush 应用内推送部分,即 App 启动时,内嵌的 JPush SDK 会开启长连接到 JPush Server,从而 JPush Server 可以推送消息到 App 里。

第一步:申请一个极光账号;https://www.jiguang.cn/
第二步:创建推送证书:https://docs.jiguang.cn/jpush/client/iOS/ios_cer_guide/
第三步:在极光推送后台创建一个应用,并将自己创建的推送证书放上去。
第四步:导入极光推送的SDK并配置环境https://docs.jiguang.cn/jpush/client/iOS/ios_guide_new/
如果后期发现自己收不到推送消息,检查2、3、4步是否证书有效、证书的bundleid是否与程序配置一样、是否开启Application Target的Capabilities->Push Notifications选项、是否支持Http传输方法

<key>NSAppTransportSecurity</key>
  <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
  </dict>

第五步:代码时刻
1.在 AppDelegate.m 引用头文件

// 引入JPush功能所需头文件
#import "JPUSHService.h"
// iOS10注册APNs所需头文件
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif

2.添加Delegate

@interface AppDelegate ()<JPUSHRegisterDelegate>

@end

3.添加初始化APNs代码、JPush代码

 -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//初始化APNs代码
 JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
  entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound;
  if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
    // 可以添加自定义categories
    // NSSet<UNNotificationCategory *> *categories for iOS10 or later
    // NSSet<UIUserNotificationCategory *> *categories for iOS8 and iOS9
  }
  [JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
//JPush代码
// 如需继续使用pushConfig.plist文件声明appKey等配置内容,请依旧使用[JPUSHService setupWithOption:launchOptions]方式初始化。

  [JPUSHService setupWithOption:launchOptions appKey:appKey
                        channel:channel
               apsForProduction:isProduction
          advertisingIdentifier:advertisingId];
//初始化控制器代码
//...
   return;
}
  • appKey
    • 选择 Web Portal上 的应用 ,点击“设置” 获取其 appkey 值。请确保应用内配置的 appkey 与 Portal 上创建应用后生成的 appkey 一致。
  • channel
    • 指明应用程序包的下载渠道,为方便分渠道统计,具体值由你自行定义,如:App Store。
  • apsForProduction
    • 1.3.1版本新增,用于标识当前应用所使用的APNs证书环境。
    • 0 (默认值)表示采用的是开发证书,1 表示采用生产证书发布应用。
    • 注:此字段的值要与Build Settings的Code Signing配置的证书环境一致。
  • advertisingIdentifier

4.请在AppDelegate.m实现该回调方法并添加回调方法中的代码

//注册APNs成功并上报DeviceToken
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

  /// Required - 注册 DeviceToken
  [JPUSHService registerDeviceToken:deviceToken];
}
//实现注册APNs失败接口
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  //Optional
  NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error);
}

#pragma mark- JPUSHRegisterDelegate

// iOS 10 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
  // Required
  NSDictionary * userInfo = notification.request.content.userInfo;
  if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    [JPUSHService handleRemoteNotification:userInfo];
  }
  completionHandler(UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以选择设置
}

// iOS 10 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
  // Required
  NSDictionary * userInfo = response.notification.request.content.userInfo;
  if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    [JPUSHService handleRemoteNotification:userInfo];
  }
  completionHandler();  // 系统要求执行这个方法
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

  // Required, iOS 7 Support
  [JPUSHService handleRemoteNotification:userInfo];
  completionHandler(UIBackgroundFetchResultNewData);
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

  // Required,For systems with less than or equal to iOS6
  [JPUSHService handleRemoteNotification:userInfo];
}
//清除角标
- (void)applicationWillEnterForeground:(UIApplication *)application {
   [application setApplicationIconBadgeNumber:0];
    //设置服务器角标为0
    [JPUSHService setBadge:0];
    
}

5.根据不同参数进行页面跳转。关于这个跳转有很多方法,自己也尝试过很多种,以前通常在AppDelegate跳转,但推送页面返回时候效果不够好,所以我现在基本上在AppDelegate接受推送消息后以通知方式传给TabBarViewController,TabBarViewController(如果页面中没有用到TabBarViewController,也可以使用其他ViewController作为过度跳转)监听到通知后进行页面跳转和交互。
例如:一个APP有启动页面、有推送、有登录操作


应用流程图.png

主要代码片段
AppDelegate.m内收到推送消息时发送出通知

//用户点击了通知进入app
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler NS_AVAILABLE_IOS(10.0){
    NSDictionary * userInfo = response.notification.request.content.userInfo;

    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"PresentView" object:self userInfo:userInfo];
        
    } else {
        // 判断为本地通知
    }
}

//基于iOS 7 及以上的系统版本,如果是使用 iOS 7 的 Remote Notification 特性那么处理函数需要使用
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
    // Required, iOS 7 Support
    [JPUSHService handleRemoteNotification:userInfo];
    completionHandler(UIBackgroundFetchResultNewData);
    if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
        //应用不属于前台
        [[NSNotificationCenter defaultCenter] postNotificationName:@"PresentView" object:self userInfo:userInfo];
    }else{
        //应用属于前台
    }
    
}

BaseTabBarViewController.h内监听通知

- (void)viewDidLoad {
    [super viewDidLoad];
    [self addChildViewControllerWithClassname:[HomeViewController description] imagename:@"home_noselect" selectedimagename:@"home_select" title:@"主页"];
    [self addChildViewControllerWithClassname:[NewViewController description] imagename:@"new_noselect" selectedimagename:@"new_select"title:@"资讯"];
    [self addChildViewControllerWithClassname:[MeViewController description] imagename:@"me_noselect" selectedimagename:@"me_select" title:@"我的"];
    //消息推送通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(presentView:) name:@"PresentView" object:nil];
}
- (void)presentView:(NSNotification *)notification{
    NSLog(@"推送--------------%@", notification.userInfo);
    if ([notification.userInfo[@"push_id"] isEqualToString:@"1"]) {
        PushDetailOneViewController *oneVC = [[PushDetailOneViewController alloc] init];
        oneVC.idStr = notification.userInfo[@"push_id"];
        UINavigationController *nav = self.viewControllers[self.selectedIndex];
        [nav pushViewController:oneVC animated:YES];
        
    }else if ([notification.userInfo[@"push_id"] isEqualToString:@"2"]){
        PushDetailTwoViewController *twoVC = [[PushDetailTwoViewController alloc] init];
        twoVC.idStr = notification.userInfo[@"push_id"];
        UINavigationController *nav = self.viewControllers[self.selectedIndex];
        [nav pushViewController:twoVC animated:YES];
    }else if ([notification.userInfo[@"push_id"] isEqualToString:@"3"]){
        PushDetailThressViewController *thressVC = [[PushDetailThressViewController alloc] init];
        thressVC.idStr = notification.userInfo[@"push_id"];
        UINavigationController *nav = self.viewControllers[self.selectedIndex];
        [nav pushViewController:thressVC animated:YES];
    }
}

demo:https://github.com/guofeifeifei/jpush
推送原理参考文章:https://blog.csdn.net/yuxiang19876021/article/details/52217187

相关文章

  • 推送后传

    前言:推送功能为了提醒用户或者提高应用留活率。关于推送有很多第三方,比如极光,融云,信鸽,其原理也是相同利用APN...

  • 后传,

    自从嘉陵关大战以后,千仞雪被唐三囚禁,而胡列娜去一个山村隐居。此时的胡列娜已经和之前不一样了,虽然她比唐三大了将近...

  • 桃花后传

    她是桃花仙子留于世间唯一的后人,他是神女留于人间的神子,是神的人子女。他们之间的相遇会是怎样的呢? 初见太子 ...

  • 需求后传

    自己一个人玩玩具,特别投入。 中午放学的时候,告诉我,他今天和三个小朋友一起玩了,而且是奥特曼的游戏,特开心,每个...

  • 神鸟后传

    神鸟的事传到了一个富商那里,他想:要是我能捉住神鸟,那该多好啊,于是他贴出公告:“凡是捉住神鸟者,赏千金,马万匹。...

  • 项羽后传

    大一古代汉语作业2012 天汉六年,项羽率二十六骑东渡乌江。 逝者如斯,也像是一条无形的界,隔开了他和他的王座。水...

  • 《厨神后传》

    话说当年他得到了厨神的真传,就辞别师傅回到家乡开了一家饭馆。没多久,那道招牌菜就远近闻名,店里的生意也越来越红火。...

  • 汤姆后传

    汤姆在王宫里过得非常开心,可他觉得自己总是总像一个大忙人一样,因为他自从喝了变大药水后,既要跟王子、公主...

  • 封神后传

    作者 南山牧林 这是一部对先秦古典《山海经》的致敬之作。 了解《山海经》这部著作的人都知道,它里面记载的内容包罗...

  • 悟空后传

    自从阿紫死后,天机仪被毁,我也渐渐变得颓废起来,我时常拿着那根铁棒,站在云巅之上,俯视,眺望着这片正在重建...

网友评论

      本文标题:推送后传

      本文链接:https://www.haomeiwen.com/subject/lijglftx.html