之前写过一篇小米推送的文章,但是流程写的不详细,内容编辑也有问题,今天再次接入小米推送,趁热更新一下之前的文章,补充一下细节,供大佬们参考。
开始还是要吐槽一下小米开放平台的客服系统,尤其对于推送这种基础免费软件,没有人工客服,反馈问题都是靠邮件,难受的一笔。
集成过程分为以下几部分:
- 小米开放平台账号及权限申请,app注册
- 苹果推送证书申请
- 在小米推送后台配置推送证书
- 集成小米SDK
- 开发环境测试
- 模拟线上环境测试
小米开放平台账号及权限申请,app注册
进入小米开放平台,注册小米账号,并认证开发者权限。这部分工作一般是由开发支持部门完成。
苹果推送证书申请
这部分就以图片的形式说明了,网上这种教程很多,如果有不明白的地方,可以自行百度或者google
- 注册APPID
填写APPID描述和BundleID
![注册APPID]
勾选你需要的AppServices
,推送功能需要勾选Push Notifications
- 注册推送证书
打开mac钥匙串访问 -> 证书助理 -> 从证书颁发机构请求证书
填写相关信息,将证书存储到磁盘,备用
接下来进入苹果开发者中心,登陆并点击Account,进入个人中心,点击Certificates,Identifiers&Profiles
选项,进入证书,id,配置文件管理中心。
点击Certificates
,可以看到证书管理选项,如下图:
选择Certificates选项下的Development选项,点击右上角+号,选择Apple Push Notification service SSL (Sandbox)
,添加开发推送证书
选择之前创建的App ID
,
接下来就需要用到之前从钥匙串中颁发的证书,找到存储钥匙串证书的位置,选中添加,
最后,点击Continue,即可创建开发推送证书,然后下载创建好的证书,双击将其添加到要是串中,开发推送证书注册完毕。
生产推送证书的注册方式基本相同,只是在第一步选中的是Apple Push Notification service SSL (Sandbox & Production)
选项,如下图:
在小米推送后台配置推送证书
在上一步,注册了开发和生产的推送证书,下载并双击运行到了钥匙串中,所以这一步首先要将推送证书从钥匙串中导出。
共享证书文件需要通过导出.p12文件,导出证书姿势如下两种:
姿势一
姿势二
下面再演示一种错误姿势
,如果集成sdk之后,使用小米推送工具测试无法推送到APNs服务器,考虑一下是不是自己手欠,多选了一项。
证书导出完成之后,上传到对应app栏目下(这个就不贴图了)。
集成小米推送SDK
从官方文档中找到sdk下载链接,下载并将一个.a库和一个.h头文件引入项目中,记得点击copy items if need。
添加以下依赖库: UserNotifications.framework
(iOS10+), libresolv.dylib
, libxml2.dylib
, libz.dylib
,SystemConfiguration.framework
,MobileCoreServices.framework
,CFNetwork.framework
,CoreTelephony.framework
。
部分xcode版本需要在target的Capabilities
选项卡中打开Push Notifications
选项,具体如下图:
接下来,不要着急写码,还要先配置好参数, MiSDKAppID, MiSDKAppKey, MiSDKRun,前两者可以在小米开放平台注册的应用中拿到,后者是用来区分开发(debug)和生产(online)模式,这里直接建议使用User-Defined Setting参数来配置MiSDKRun的值,这样以后切换Debug和Release环境时就不用手动修改了。添加位置为工程中Info.plist文件,步骤如下图:
添加参数
添加User-Defined Setting变量
变量展示如下
时隔两天(写文章好累),开始上代码:
注册小米推送
/** 初始化小米推送 */
- (void)initMiPush
{
[MiPushSDK registerMiPush:self type:UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert connect:YES];
}
Appdelegate中实现注册推送成功/失败代理,方法如下:
/**
推送注册成功
*/
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
/** 注册成功绑定设备号 */
[MiPushSDK bindDeviceToken:deviceToken];
}
/**
推送注册失败
*/
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(@"小米推送注册失败");
}
实现小米sdk中异步回调代理(MiPushSDKDelegate),
/**
小米成功回调
*/
- (void)miPushRequestSuccWithSelector:(NSString *)selector data:(NSDictionary *)data
{
if ([selector isEqualToString:@"bindDeviceToken:"]) {
/** 如果服务端是通过regid推送,这个地方可以用全局变量或者其他方式记录一下,在某个时机上传到服务端 */
NSLog(@"regid = %@", data[@"regid"]);
}
}
- (void)miPushRequestErrWithSelector:(NSString *)selector error:(int)error data:(NSDictionary *)data
{
DLog(@"小米回调失败:%d",error);
}
收到小米推送到响应小米推送信息,这个过程分为三种场景
- 应用运行中,并处在前台
- 应用运行中,单处在后台
- 应用未启动
下面列出iOS9/iOS10两个版本下(因项目支持最低版本为iOS 9.0,所以没有测试iOS 9.0之前的版本,如有不同,可以告诉我下,我会做下补充),在系统收到推送和点击推送消息响应方法的区别:
下面分状态给出代码:
/**
iOS 9.0 应用处于前台,收到通知或点击通知消息,均执行该方法
*/
- ( void )application:( UIApplication *)application didReceiveRemoteNotification:( NSDictionary *)userInfo
{
//使用此方法后,所有消息会进行去重,然后通过miPushReceiveNotification:回调返回给App
[ MiPushSDK handleReceiveRemoteNotification :userInfo];
}
/**
iOS10 应用在前台收到通知
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[MiPushSDK handleReceiveRemoteNotification:userInfo];
}
if (@available(iOS 10.0, *)) {
/** 如果在前台想要显示通知栏消息,需要实现该Handler */
completionHandler(UNNotificationPresentationOptionBadge|
UNNotificationPresentationOptionSound|
UNNotificationPresentationOptionAlert);
} else {
// Fallback on earlier versions
}
}
当应用处于后台或者未启动状态,因iOS 9.0收到通知和点击通知调用方法相同,所以现在只需考虑iOS 10.0之后点击通知栏消息到响应消息过程。
由上面方法调用表可以看到,iOS 10.0之后,收到通知执行方法的顺序是方法4->方法1,如果当前app是冷启动,在执行下面方法时,window还未创建,所以在这里响应推送消息有可能无效,比如要push到指定页面,这里提供两种解决方法:
- 延时2s-3s,处理推送消息,但是这种方法有局限性,还是有可能无法响应消息.
- 在下面方法中记录该消息(NSUserDefaults或者其他方式),待window初始化之后,再响应该推送消息
/**
iOS 10,应用处于后台或者未启动,点击通知栏进入应用,会先执行该方法
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSDictionary * userInfo = response.notification.request.content.userInfo;
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[MiPushSDK handleReceiveRemoteNotification:userInfo];
/** 记录推送消息 */
}
completionHandler();
}
iOS 9.0/10.0 点击推送消息并且app冷启动状态都会走的方法
/**
iOS 9.0/10.0,应用冷启动,点击通知栏进入应用,会执行该方法,所以为了兼容iOS 9.0,这里也要记录推送消息
*/
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/** 注册小米推送 */
[self initMiPush];
/** app冷启动,记录(处理)小米推送消息 */
NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
[self dealMiPushMessage:userInfo];
return YES;
}
另外,如果应用处于前台,sdk内部会运行一个socket长连接到server端,来接收推送消息,这个方法中未做处理
/**
当app启动并运行在前台时,sdk内部会运行一个socket长连接到server端,来接收推送消息
@param data 消息格式跟APNs格式一样
*/
- ( void )miPushReceiveNotification:( NSDictionary *)data
{
NSLog(@"小米回调前台:%@",data);
}
至此,代码部分完结,有不明白的可以参看MipushDemodemo在文章两天内给出
,包括处理推送消息的方法,在Demo中都有体现。接下来是测试部分,有些同学集成sdk完毕之后,使用小米开放平台推送工具进行测试,有可能测试环境收不到推送,或者正式环境收不到推送,或者两者都收不到推送,如有该问题,可看一下以下部分,看看是否能解决问题。
iOS 推送环境分为两种:测试环境和正式环境
- 测试环境:即Dev模式,对应开发证书
- 正式环境:该环境可分为两种,appstore和Ad-hoc,两种推送的通道相同,所以正式环境的推送可以通过打Ad-hoc的包来测试。
使用Ad-hoc的开发证书无法直接运行项目在真机上,因为我项目里面使用了cocoapods,这个是否有解决方法?有知道的同学告诉我下,万分感谢!!!
所以正式环境和开发环境并不只是指修改targe中的debug和release编译模式,而是需要证书+编译模式两种齐备。测试环境对应Debug编译模式+dev打包证书,正式环境对应Release编译模式+Ad-hoc证书。
到这里小米推送的集成过程完毕,可通过小米开放平台的推送工具来进行测试。