百度云推送实现全过程

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容