iOS下Cordova添加百度推送及相关问题
今天我们要讲的内容主要是针对 Cordova 环境下添加百度推送时产生的问题及处理
因为项(jia)目(fang)需要,选择的百度推送添加到 app 中,当然,你们就算百度也能找到 Cordova 的百度推送插件,无脑安装就可以……
不过嘛,本着求人不如求己(其实是嫌麻烦不想弄+想踩坑)的原则我要说的是我个人手动添加调试百度推送的过程以及坑
首先,百度云推送中心弄SDK,看官方文档,介些基本操作就不说多了,不会就转行吧
创建测试 demo,添加推送证书
然后就是正常的创建操作,这里要说的是他这个证书,百度家不走寻常路不需要我们的 p12 文件,而是要我们 p12 再生成的 pem 文件,这个着实恶心到我了,而更恶心的是这个东西百度家还很诡异的因为 Mac 系统版本高于 10.12.6 的 openssl 版本是 2.x.x,百度推送不接受高于 0.9.8 的 openssl 生成的 pem。
EXM???
没办法,我只好去openssl历史版本库中去找 openssl 0.9.8zh 版本下载安装
下载 openssl 0.9.8zh -> 解压下载的压缩包 -> cd 你解压后的压缩包目录
执行命令
./Configure darwin64-x86_64-cc --prefix=/usr/local/openssl --shared
这一步可能会遇到没有权限创建openssl文件夹的问题,可以手动到/usr/local/下创建一个openssl文件夹,然后在执行命令(不知道的话就随便开个文件夹 shift+command+g(windows 键盘的 command 就是 win 键) 然后输入 /usr/local/ 回车就到了)
然后
make && make install
openssl将会出现在这个路径下:/usr/local/openssl/bin/openssl,命令行查看下版本:
/usr/local/openssl/bin/openssl version
显示0.9.8zh就成功了
然后 p12 生成 pem
/usr/local/openssl/bin/openssl pkcs12 -in 开发/生产.p12 -out 开发/生产.pem -nodes
保存好,把对应的 pem 文件给百度传上去就可以了(出处)
然后是项目添加 BPush,这个用官方 Demo 里的就行,根据你个人的项目需求自行选择 normalversion / idfaversion 二者区别是 如果你用 idfaversion 的话在审核的时候你是要选 广告标识符 为“是”的,另外文件夹里的 test.caf 也不需要(一音乐文件,不懂他用在什么地方,反正我是不需要)
放到项目里后,在 appdelegate 文件中导入
#import "BPush.h"
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif
以及文件中涉及推送的那一大串代码(较长,请仔细甄别):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// iOS10 下需要使用新的 API
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) {
[application 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
// 在 App 启动时注册百度云推送服务,需要提供 Apikey
[BPush registerChannel:launchOptions apiKey:@"UYTrEvcwTxIDaAPgEuijvNMz"pushMode:BPushModeProduction withFirstAction:@"打开" withSecondAction:@"关闭" withCategory:@"test" useBehaviorTextInput:YES isDebug:YES];
// 禁用地理位置推送 需要再绑定接口前调用。
[BPush disableLbs];
// App 是用户点击推送消息启动
NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (userInfo) {
[BPush handleNotification:userInfo];
}
#if TARGET_IPHONE_SIMULATOR
Byte dt[32] = {0xc6, 0x1e, 0x5a, 0x13, 0x2d, 0x04, 0x83, 0x82, 0x12, 0x4c, 0x26, 0xcd, 0x0c, 0x16, 0xf6, 0x7c, 0x74, 0x78, 0xb3, 0x5f, 0x6b, 0x37, 0x0a, 0x42, 0x4f, 0xe7, 0x97, 0xdc, 0x9f, 0x3a, 0x54, 0x10};
[self application:application didRegisterForRemoteNotificationsWithDeviceToken:[NSData dataWithBytes:dt length:32]];
#endif
//角标清0
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
/*
// 测试本地通知
[self performSelector:@selector(testLocalNotifi) withObject:nil afterDelay:1.0];
*/
return YES;
}
- (void)testLocalNotifi
{
NSLog(@"测试本地通知啦!!!");
NSDate *fireDate = [[NSDate new] dateByAddingTimeInterval:5];
[BPush localNotification:fireDate alertBody:@"这是本地通知" badge:3 withFirstAction:@"打开" withSecondAction:nil userInfo:nil soundName:nil region:nil regionTriggersOnce:YES category:nil useBehaviorTextInput:YES];
}
// 此方法是 用户点击了通知,应用在前台 或者开启后台并且应用在后台 时调起
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
completionHandler(UIBackgroundFetchResultNewData);
// 打印到日志 textView 中
NSLog(@"********** iOS7.0之后 background **********");
// 应用在前台,不跳转页面,让用户选择。
if (application.applicationState == UIApplicationStateActive) {
NSLog(@"acitve ");
// UIAlertView *alertView =[[UIAlertView alloc]initWithTitle:@"收到一条消息" message:userInfo[@"aps"][@"alert"] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
// [alertView show];
}
//杀死状态下,直接跳转到跳转页面。
if (application.applicationState == UIApplicationStateInactive && !isBackGroundActivateApplication)
{
SkipViewController *skipCtr = [[SkipViewController alloc]init];
// 根视图是nav 用push 方式跳转
[_tabBarCtr.selectedViewController pushViewController:skipCtr animated:YES];
NSLog(@"applacation is unactive ===== %@",userInfo);
/*
// 根视图是普通的viewctr 用present跳转
[_tabBarCtr.selectedViewController presentViewController:skipCtr animated:YES completion:nil]; */
}
// 应用在后台。当后台设置aps字段里的 content-available 值为 1 并开启远程通知激活应用的选项
if (application.applicationState == UIApplicationStateBackground) {
NSLog(@"background is Activated Application ");
// 此处可以选择激活应用提前下载邮件图片等内容。
isBackGroundActivateApplication = YES;
// UIAlertView *alertView =[[UIAlertView alloc]initWithTitle:@"收到一条消息" message:userInfo[@"aps"][@"alert"] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
// [alertView show];
}
[self.viewController addLogString:[NSString stringWithFormat:@"Received Remote Notification :\n%@",userInfo]];
NSLog(@"%@",userInfo);
}
// 在 iOS8 系统中,还需要添加这个方法。通过新的 API 注册推送服务
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSLog(@"test:%@",deviceToken);
[BPush registerDeviceToken:deviceToken];
[BPush bindChannelWithCompleteHandler:^(id result, NSError *error) {
[self.viewController addLogString:[NSString stringWithFormat:@"Method: %@\n%@",BPushRequestMethodBind,result]];
// 需要在绑定成功后进行 settag listtag deletetag unbind 操作否则会失败
// 网络错误
if (error) {
return ;
}
if (result) {
// 确认绑定成功
if ([result[@"error_code"]intValue]!=0) {
return;
}
// 获取channel_id
NSString *myChannel_id = [BPush getChannelId];
NSLog(@"==%@",myChannel_id);
[BPush listTagsWithCompleteHandler:^(id result, NSError *error) {
if (result) {
NSLog(@"result ============== %@",result);
}
}];
[BPush setTag:@"Mytag" withCompleteHandler:^(id result, NSError *error) {
if (result) {
NSLog(@"设置tag成功");
}
}];
}
}];
// 打印到日志 textView 中
[self.viewController addLogString:[NSString stringWithFormat:@"Register use deviceToken : %@",deviceToken]];
}
// 当 DeviceToken 获取失败时,系统会回调此方法
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(@"DeviceToken 获取失败,原因:%@",error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
// App 收到推送的通知
[BPush handleNotification:userInfo];
NSLog(@"********** ios7.0之前 **********");
// 应用在前台 或者后台开启状态下,不跳转页面,让用户选择。
if (application.applicationState == UIApplicationStateActive || application.applicationState == UIApplicationStateBackground) {
NSLog(@"acitve or background");
UIAlertView *alertView =[[UIAlertView alloc]initWithTitle:@"收到一条消息" message:userInfo[@"aps"][@"alert"] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
[alertView show];
}
else//杀死状态下,直接跳转到跳转页面。
{
SkipViewController *skipCtr = [[SkipViewController alloc]init];
[_tabBarCtr.selectedViewController pushViewController:skipCtr animated:YES];
}
[self.viewController addLogString:[NSString stringWithFormat:@"Received Remote Notification :\n%@",userInfo]];
NSLog(@"%@",userInfo);
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSLog(@"接收本地通知啦!!!");
[BPush showLocalNotificationAtFront:notification identifierKey:nil];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
SkipViewController *skipCtr = [[SkipViewController alloc]init];
// 根视图是nav 用push 方式跳转
[_tabBarCtr.selectedViewController pushViewController:skipCtr animated:YES];
/*
// 根视图是普通的viewctr 用present跳转
[_tabBarCtr.selectedViewController presentViewController:skipCtr animated:YES completion:nil]; */
}
}
根据你个人需要自行修改增减代码
对了,别忘了填上你的 apikey
然后关于项目中推送配置 Background Modes、Push Notifications 开关什么的别忘记开
运行,获取到Channel_id,OK!
然后我发现,我成功运行是因为我是直接连手机运行的,非常成功,但是一旦我打包分发给别人测试的时候就报错
Code=3000 “未找到应用程序的“aps-environment”的授权字符串” WTF?!!!
然后经百度谷歌排查发现,推送是要有一个 XXX.entitlements 的文件的,而我没有╮(╯▽╰)╭
然后我又看了下 Build Srttings 里的 Code Signing Entitlements
.plist??? EXM??? Σ(・□・;) 那就要把它换成 .entitlements 文件才行啊!
重新编译、打包、运行测试,成功!
2018-11-13续:
百度推送成功率第及时性差,已经更换成极光推送了╮(╯▽╰)╭……
(后续 BUG 持续开发结束)