美文网首页SwiftObject-CAndroid
百度云推送实现全过程

百度云推送实现全过程

作者: wangyu2488 | 来源:发表于2017-01-20 11:32 被阅读1664次

    2017年1月12日
    一.百度云推送
    目前免费(cocoapod不支持)
    1.效果图:
    如果程序在后台(主页面tab在第一个),收到通知后的效果 【操作流程:点击鲜花通知-点击返回】


    Paste_Image.png

    如果程序默认是开启状态,效果图如下:【操作流程:点击立即前往-点击返回】

    Paste_Image.png
    2.如何加载第三方库,参考官网文档
    基本原理图:
    Paste_Image.png
    其实苹果用的是deviceToken,我们在如下接口获取到deviceToken后 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

    注册到百度云库里面,百度云会返回一个对应token的userid(之后就是以这个做设备识别)。也就是百度云对应的 getChannelId,appd客户端获取后,发送到appServer既可(该值我们是和账号绑定的,所以后台要设置绑定关系),这样appServer就可以通过这个id来推送消息了(群发的不需要id)。
    2.创建好应用后,关键是如下制作证书上传
    具体参照如下:苹果push证书制作全过程(含测试过程)
    二.实现(工程和代码相关设置)
    1.工程设置

    Paste_Image.png Paste_Image.png

    百度云SDK


    Paste_Image.png

    2.代码设置
    头文件设置

    //  AppDelegate.m
    #import "BPush.h"
    #ifdef NSFoundationVersionNumber_iOS_9_x_Max
    #import <UserNotifications/UserNotifications.h>
    #endif
    
    static BOOL isBackGroundActivateApplication;
    

    第一步:程序启动接口 绑定api key(百度 无账号登录体系)

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //初始化百度推送组件
        [self startBaiDuPush:launchOptions];
        return YES;
    }
    
    - (void)startBaiDuPush:(NSDictionary *)launchOptions
    {
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
    #ifdef NSFoundationVersionNumber_iOS_9_x_Max
            UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    
            [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge)
                                  completionHandler:^(BOOL granted, NSError * _Nullable error) {
                                      // Enable or disable features based on authorization.
                                      if (granted) {
                                          [[UIApplication sharedApplication] registerForRemoteNotifications];
                                      }
                                  }];
    #endif
        }
        else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
            UIUserNotificationType myTypes = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
    
            UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:myTypes categories:nil];
            [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        }else {
            UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeSound;
            [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
        }
    
        //#warning 测试 开发环境 时需要修改BPushMode为BPushModeDevelopment 需要修改Apikey为自己的Apikey
        BPushMode pMode =  BPushModeDevelopment;
    #ifdef HuBPushModeProduction_ON
        pMode = BPushModeProduction;
    #endif
        NSString *key = Baidu_PUSH_API_KEY;
        [BPush registerChannel:launchOptions apiKey:key pushMode:pMode withFirstAction:@"打开" withSecondAction:@"回复" withCategory:@"test" useBehaviorTextInput:YES isDebug:YES];
    
        // 禁用地理位置推送 需要再绑定接口前调用。
        [BPush disableLbs];
    
        // App 是用户点击推送消息启动
        NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        if (userInfo) {
            [BPush handleNotification:userInfo];
        }
        //角标清0  角标结合我们自己的逻辑不能清空
    //    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
    }
    
    // 在 iOS8 系统中,还需要添加这个方法。通过新的 API 注册推送服务
    - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
    {
        [application registerForRemoteNotifications];
    }
    

    第二步:将苹果返回的deviceToken,注册如百度库,接着绑定,之后都用channel_id 替代deviceToken

    //获取手机唯一标示  消息中心push 主推想
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
        [BPush registerDeviceToken:deviceToken];
        //绑定
        [BPush bindChannelWithCompleteHandler:^(id result, NSError *error) {
            if (error) return ;
            if (result) {
                // 确认绑定成功
                if ([result[@"error_code"]intValue]!=0) {
                    return;
                }
                // 获取channel_id
                NSString *BaiDu_Channel_id = [BPush getChannelId];
    
                [[NSUserDefaults standardUserDefaults]setObject:BaiDu_Channel_id forKey:@"BaiDu_Channel_id"];
            }
        }];
    }
    
    // 当 DeviceToken 获取失败时,系统会回调此方法
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
    {
        NSLog(@"DeviceToken 获取失败,原因:%@",error);
    }
    

    第三步:处理通知接口

    // ios7后的新接口, 此方法是 用户点击了通知,应用在前台 或者开启后台并且应用在后台 时调起
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    {
        // App 收到推送的通知
        [BPush handleNotification:userInfo];
        _ps_Type=[userInfo[@"psType"] intValue];//自定义type消息(和后台约定)
        NSString *message = userInfo[@"aps"][@"alert"];
    
        completionHandler(UIBackgroundFetchResultNewData);
    
        // 应用在前台,不跳转页面,让用户选择。
        if (application.applicationState == UIApplicationStateActive) {
            [self showAlertView:message];
        }
    //    杀死状态下,直接跳转到需要添置跳转页面。
        if (application.applicationState == UIApplicationStateInactive && !isBackGroundActivateApplication)
        {
            [self dealPushMessage:_ps_Type];
        }
        // 应用在后台。当后台设置aps字段里的 content-available 值为 1 并开启远程通知激活应用的选项
        if (application.applicationState == UIApplicationStateBackground) {
            // 此处可以选择激活应用提前下载邮件图片等内容。
            isBackGroundActivateApplication = YES;
            [self showAlertView:message];
        }
    }
    

    3.1添加个人处理相关个性化页面

    - (void)showAlertView:(NSString *)message
    {
        UIAlertView *alertView =[[UIAlertView alloc]initWithTitle:@"消息提醒" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"立即前往", nil];
        [alertView show];
    }
    
    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
        if (buttonIndex == 1) {
            [self dealPushMessage:_ps_Type];
        }
    }
    
    //程序主界面首页底部menutar类型
    typedef NS_ENUM(NSInteger, HuMainPageMenuBarType) {
        HuMainPageMenuBarTypeWardPatient  = 1,//病区患者
        HuMainPageMenuBarTypeEducationClass  = 2,//宣教课程
        HuMainPageMenuBarTypePersonalCenter  = 3,//个人中心
    };
    - (void)dealPushMessage:(HuMessagePushType)pushType
    {
        if (![HuConfigration loginStatus]) {
            loginViewController * loginVC = [[loginViewController alloc] init];
            [[[UIApplication sharedApplication] delegate] window].rootViewController = loginVC;
        }
        else
        {
            switch (pushType) {
                case HuMessagePushTypeMain:
                {
                    [self goToMainPage:HuMainPageMenuBarTypeWardPatient];
                }
                    break;
               case HuMessagePushTypeDonateFlowerMessage:
                {
                    [self gotoViewControllerStr:@"FlowerMessViewController" WithMenuBar:HuMainPageMenuBarTypePersonalCenter];
                }
                    break;
                case HuMessagePushTypeSystemMessage:
                {
                    [kNotificationCenter postNotificationName:kNotificationRed object:nil];
                    [self gotoViewControllerStr:@"SystemMessagesViewController" WithMenuBar:HuMainPageMenuBarTypePersonalCenter];
                }
                    break;
    
                default:
                    break;
            }
    
        }
    }
    
    - (void)gotoViewControllerStr:(NSString*)vcStr WithMenuBar:(HuMainPageMenuBarType)type
    {
        [self goToMainPage:type];
        NSInteger i = type - 1;
          //选择对应的控制器数组,在将其push进入
        UINavigationController *nav = [[_customVc childViewControllers] objectAtIndex:i];
        UIViewController *vc = [[NSClassFromString(vcStr) alloc] init];
        [nav pushViewController:vc animated:YES];
        [_customVc hiddenTabBar];
    
    }
    
    - (void)goToMainPage:(HuMainPageMenuBarType)type
    {
        if (!_customVc)
        {
            CustomMyViewController *custom = [[CustomMyViewController alloc]init];
            custom.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
            _window.rootViewController = custom;
            _customVc = custom;
        }
        if(type >= HuMainPageMenuBarTypeWardPatient  && type <= HuMainPageMenuBarTypePersonalCenter){
              //将主页底部点击下班设置正确
            [_customVc tabMenuBarWithType:type];
        }
    }
    

    第四步.如果获取的channel_id,需要跟对应的账号绑定,我们就需要程序账号登录后,告诉后台appServer绑定关系。之后推送相关都从后台appServer发起。
    程序程序之后主界面 绑定下就可以

    - (void)viewDidLoad
    {
       [self bindChannelIdWithAccount];
    }
    
    - (void)bindChannelIdWithAccount
    {
        NSString *BaiDu_Channel_id = [[NSUserDefaults standardUserDefaults]objectForKey:@"BaiDu_Channel_id"];
        NSDictionary *param = @{@"deviceChannelId":BaiDu_Channel_id};
    
        NSString *url=[NSString stringWithFormat:@"%@/api/testModle/bindDevice",quanQaunURL];
        [QQRequest post:url param:param view:nil success:^(NSDictionary *dic) {
        } error:nil failure:nil];
    }
    

    三.其他
    1.请求Push 常见错误码
    BPushErrorCode_Success = 0,
    BPushErrorCode_MethodTooOften = 22, // 调用过于频繁
    BPushErrorCode_NetworkInvalible = 10002, // 网络连接问题
    BPushErrorCode_InternalError = 30600, // 服务器内部错误
    BPushErrorCode_MethodNodAllowed = 30601, // 请求方法不允许
    BPushErrorCode_ParamsNotValid = 30602, // 请求参数错误
    BPushErrorCode_AuthenFailed = 30603, // 权限验证失败
    BPushErrorCode_DataNotFound = 30605, // 请求数据不存在
    BPushErrorCode_RequestExpired = 30606, // 请求时间戳验证超时
    BPushErrorCode_BindNotExists = 30608, // 绑定关系不存在
    2.目前暂时没用到(以后可能会设计,给特点标签的设备推送消息)
    标签组播:推送给打上某一个标签的一组设备。为iOS设备打标签需要通过调用iOS客户端SDK中的setTags方法来设置所属的Tag 每个应用最多可以定义10000个标签;每个标签对应的设备数没有限制

    3.后台推送参数添加content-available: 1 (静默推送)【暂时也没用】

    4.ios9新特性 【 暂时也没用】


    Paste_Image.png

    5.ios10富文本消息 【暂时也没用】


    Paste_Image.png

    2016年11月16日
    一.百度云推送测试流程总结
    第一步:登录如下账号(百度云网站部署状态改变,不会影响生产的<生产上客服推送是另一套机制推送>,代码推送状态修改就会有影响了)
    http://push.baidu.com/

    Paste_Image.png

    二.代码断点调试 获取百度返回的 BaiDu_Channel_id

    Paste_Image.png

    三.一般指定设备id 推送消息


    Paste_Image.png

    正常现象:

    Paste_Image.png

    ps:
    注意测试的时候appid一定要选对


    Paste_Image.png Paste_Image.png

    如果您发现本文对你有所帮助,如果您认为其他人也可能受益,请把它分享出去。

    相关文章

      网友评论

      • 1b78a68bf73d:百度云推送已经黄了,服务端能推送成功,客户端接收不到,官方qq群和公众号都没了
        1b78a68bf73d:@wangyu2488 我们打算换腾讯信鸽,说是能兼容华为,小米的通道,不过他们的人工客服也不应答了,有点惴惴不安
        研发组的小仙女:我也出现了你说的问题:服务端能推送成功,客户端接收不到,服务端推送后,不走回调的方法,你的也一样吗
        wangyu2488:@美索不达米亚的鳄鱼 我们已经用极光了
      • 那仅有的执著:你好,如果我和接口联调,需要些接口的话,需要写在哪里?求指教,谢谢。
        wangyu2488:不是很明白什什么意思 , 一般都是自己的appServer来触发消息推送接口,一般也在后台(也可以本地app触发,比较少用到)

      本文标题:百度云推送实现全过程

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