在国内APP需要接入支付的话,支付宝支付和微信支付那肯定是必不可少的,在支付领域那二者肯定是同坐头把交椅的,支付是没得说,但是其他领域就不一定了,比如下面我们即将要讲的推送,常用的或者市场份额大的当然是极光推送,可在前期的调研和对比阶段之后,产品和CTO没有选择常用的极光推送,而是选择了小众的阿里云移动推送,说句实话在公司没说要用之前,我们移动端开发都不知道阿里竟然还有推送的产品,阿里的产品用得最多的友盟和支付宝支付,那么下面就来说说集成阿里云移动推送的过程。
我们的情况是已经在项目中已经手动集成了支付宝支付,现在需要再加上阿里云推送,当然首先单独写了一个demo按阿里云的开发者文档进行cocopods形式的集成,一下子很快就测试成功了,我想这么简单,那好啊!可是没想到的是当我把相同的配置方法加入的真正的项目中并进行cocopods集成的时候,马上红色报错就来了,如下图:
这个报错的关键字就是“UTDID”,那就要找和这个有关的了,Xcode项目里面全局搜索“UTDID”,支付宝支付的库里面含有这个,但是我打开本地的支付宝库却是找不到,因为他们把这个放在了framework里面,那竟然是这样的话,这个时候我想到了那么移动推送里面的UTDID就不要接入不就可以了,这样就不能使用cocopods集成了,删掉cocopods集成的库,然后改用手动集成,按阿里云的步骤进行操作,可是的可是,还是不行哦,头大!如下图:
接着我咨询了阿里云的售后服务,如下图:
剥离UTDID:https://help.aliyun.com/document_detail/59152.html?spm=5176.smartservice_service_chat.0.0.2a97709avL99Wx
反正反正这么一波操作,我还是没有成功收到推送消息,真是崩溃。那么这个时候就要换个思路了,同时与售后的聊天过程中也知道了个事情,那就是移动推送还是使用cocopods集成,不用手动集成了,原先的想法是支付宝支付已经成功了,支付宝支付功能是集成成功的了,那么既然移动推送只能用cocopods集成,而cocopods集成却不能单独剥离UTDID,那这么说就只能去把支付宝支付库里面的UTDID给删掉了,剥离的方法链接也上一个,阿里云-云产品SDK UTDID冲突解决方案
同样阿里云也是推荐是支付宝支付使用剥离UTDID的支付宝SDK,然后保留阿里云平台的UTDID包。
那么下面来详细说明一下接入的过程:
1、打开移动推送的开发者文档,iOS 移动推送SDK配置(点我打开)
2、pod方式,如下图:
Podfile文件就是这样子:
source 'https://github.com/CocoaPods/Specs.git'#阿里云1
source 'https://github.com/aliyun/aliyun-specs.git'#阿里云2
pod 'AlicloudPush', '~> 1.9.9.5'#阿里云3
3、运行 pod update --no-repo-update命令,建议最好能连上外网的网络下载,这样就快很多;
4、下载完成之后,运行项目肯定还是会报UTDID的冲突报错,这个时候我们就下从支付宝开发文档下载的兼容包去替换原先项目里面的包,如下图:
5、替换完成后运行还是会报错,OBJC_CLASS$_CMMotionManager,如下图:
备注:CMMotionManager 是 Core Motion 库的核心类,负责获取和处理手机的运动信息。
项目中缺少CMMotionManager的库,所以点击添加相关库。
6、还建议不要忘记在项目中拖入AliyunEmasServices-Info.plist文件,要不然推送是收不到的,打印窗里面也会有相关报错打印。
7、在AppDelegate.m里面写入阿里云移动推送相关代码,如下:
#import "AppDelegate.h"
//阿里推送
#import
// iOS 10 notification
#import
static NSString *const testAppKey = @“填入阿里云移动推送APPKey;
static NSString *const testAppSecret = @"填入阿里云移动推送AppSecret";
@interface AppDelegate ()
@end
@implementation AppDelegate{
// iOS 10通知中心
UNUserNotificationCenter *_notificationCenter;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//这里一定要强引用self.baseVc为属性,要不然后面会不执行代理方法
self.baseTabBarVc = [[XMFBaseUseingTabarController alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
//设置window的背景颜色,防止有些present控制器的时候背景黑屏
self.window.backgroundColor = KWhiteColor;
self.window.rootViewController = self.baseTabBarVc;
[self.window makeKeyAndVisible];
// APNs注册,获取deviceToken并上报
[self registerAPNS:application];
// 初始化SDK
[self initCloudPush];
// 监听推送通道打开动作
[self listenerOnChannelOpened];
// 监听推送消息到达
[self registerMessageReceive];
// 点击通知将App从关闭状态启动时,将通知打开回执上报
// [CloudPushSDK handleLaunching:launchOptions];(Deprecated from v1.8.1)
[CloudPushSDK sendNotificationAck:launchOptions];
return YES;
}
#pragma mark - ——————— 阿里推送 ————————
#pragma mark APNs Register
/**
* 向APNs注册,获取deviceToken用于推送
*
* @param application
*/
- (void)registerAPNS:(UIApplication *)application {
float systemVersionNum = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersionNum >= 10.0) {
// iOS 10 notifications
_notificationCenter = [UNUserNotificationCenter currentNotificationCenter];
// 创建category,并注册到通知中心
[self createCustomNotificationCategory];
_notificationCenter.delegate = self;
// 请求推送权限
[_notificationCenter requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// granted
NSLog(@"User authored notification.");
// 向APNs注册,获取deviceToken
dispatch_async(dispatch_get_main_queue(), ^{
[application registerForRemoteNotifications];
});
} else {
// not granted
NSLog(@"User denied notification.");
}
}];
} else if (systemVersionNum >= 8.0) {
// iOS 8 Notifications
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
[application registerUserNotificationSettings:
[UIUserNotificationSettings settingsForTypes:
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
categories:nil]];
[application registerForRemoteNotifications];
#pragma clang diagnostic pop
} else {
// iOS < 8 Notifications
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
#pragma clang diagnostic pop
}
}
/**
* 主动获取设备通知是否授权(iOS 10+)
*/
- (void)getNotificationSettingStatus {
[_notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
NSLog(@"User authed.");
} else {
NSLog(@"User denied.");
}
}];
}
/*
* APNs注册成功回调,将返回的deviceToken上传到CloudPush服务器
*/
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"Upload deviceToken to CloudPush server.");
[CloudPushSDK registerDevice:deviceToken withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
NSLog(@"Register deviceToken success, deviceToken: %@", [CloudPushSDK getApnsDeviceToken]);
} else {
NSLog(@"Register deviceToken failed, error: %@", res.error);
}
}];
}
/*
* APNs注册失败回调
*/
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"didFailToRegisterForRemoteNotificationsWithError %@", error);
}
/**
* 创建并注册通知category(iOS 10+)
*/
- (void)createCustomNotificationCategory {
// 自定义`action1`和`action2`
UNNotificationAction *action1 = [UNNotificationAction actionWithIdentifier:@"action1" title:@"test1" options: UNNotificationActionOptionNone];
UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"action2" title:@"test2" options: UNNotificationActionOptionNone];
// 创建id为`test_category`的category,并注册两个action到category
// UNNotificationCategoryOptionCustomDismissAction表明可以触发通知的dismiss回调
UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:@"test_category" actions:@[action1, action2] intentIdentifiers:@[] options:
UNNotificationCategoryOptionCustomDismissAction];
// 注册category到通知中心
[_notificationCenter setNotificationCategories:[NSSet setWithObjects:category, nil]];
}
/**
* 处理iOS 10通知(iOS 10+)
*/
- (void)handleiOS10Notification:(UNNotification *)notification {
UNNotificationRequest *request = notification.request;
UNNotificationContent *content = request.content;
NSDictionary *userInfo = content.userInfo;
// 通知时间
NSDate *noticeDate = notification.date;
// 标题
NSString *title = content.title;
// 副标题
NSString *subtitle = content.subtitle;
// 内容
NSString *body = content.body;
// 角标
int badge = [content.badge intValue];
// 取得通知自定义字段内容,例:获取key为"Extras"的内容
NSString *extras = [userInfo valueForKey:@"Extras"];
// 通知角标数清0
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
// 同步角标数到服务端
// [self syncBadgeNum:0];
// 通知打开回执上报
[CloudPushSDK sendNotificationAck:userInfo];
NSLog(@"Notification, date: %@, title: %@, subtitle: %@, body: %@, badge: %d, extras: %@.", noticeDate, title, subtitle, body, badge, extras);
}
/**
* App处于前台时收到通知(iOS 10+)
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSLog(@"Receive a notification in foregound.");
// 处理iOS 10通知,并上报通知打开回执
[self handleiOS10Notification:notification];
// 通知不弹出
completionHandler(UNNotificationPresentationOptionNone);
// 通知弹出,且带有声音、内容和角标
//completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
/**
* 触发通知动作时回调,比如点击、删除通知和点击自定义action(iOS 10+)
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSString *userAction = response.actionIdentifier;
// 点击通知打开
if ([userAction isEqualToString:UNNotificationDefaultActionIdentifier]) {
NSLog(@"User opened the notification.");
// 处理iOS 10通知,并上报通知打开回执
[self handleiOS10Notification:response.notification];
}
// 通知dismiss,category创建时传入UNNotificationCategoryOptionCustomDismissAction才可以触发
if ([userAction isEqualToString:UNNotificationDismissActionIdentifier]) {
[CloudPushSDK sendDeleteNotificationAck:response.notification.request.content.userInfo];
}
NSString *customAction1 = @"action1";
NSString *customAction2 = @"action2";
// 点击用户自定义Action1
if ([userAction isEqualToString:customAction1]) {
NSLog(@"User custom action1.");
}
// 点击用户自定义Action2
if ([userAction isEqualToString:customAction2]) {
NSLog(@"User custom action2.");
}
completionHandler();
}
#pragma mark SDK Init
- (void)initCloudPush {
// 正式上线建议关闭
[CloudPushSDK turnOnDebug];
// SDK初始化,手动输出appKey和appSecret
// [CloudPushSDK asyncInit:testAppKey appSecret:testAppSecret callback:^(CloudPushCallbackResult *res) {
// if (res.success) {
// NSLog(@"Push SDK init success, deviceId: %@.", [CloudPushSDK getDeviceId]);
// } else {
// NSLog(@"Push SDK init failed, error: %@", res.error);
// }
// }];
// SDK初始化,无需输入配置信息
// 请从控制台下载AliyunEmasServices-Info.plist配置文件,并正确拖入工程
[CloudPushSDK autoInit:^(CloudPushCallbackResult *res) {
if (res.success) {
NSLog(@"Push SDK init success, deviceId: %@.", [CloudPushSDK getDeviceId]);
} else {
NSLog(@"Push SDK init failed, error: %@", res.error);
}
}];
}
#pragma mark Notification Open
/*
* App处于启动状态时,通知打开回调
*/
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo {
NSLog(@"Receive one notification.");
// 取得APNS通知内容
NSDictionary *aps = [userInfo valueForKey:@"aps"];
// 内容
NSString *content = [aps valueForKey:@"alert"];
// badge数量
NSInteger badge = [[aps valueForKey:@"badge"] integerValue];
// 播放声音
NSString *sound = [aps valueForKey:@"sound"];
// 取得通知自定义字段内容,例:获取key为"Extras"的内容
NSString *Extras = [userInfo valueForKey:@"Extras"]; //服务端中Extras字段,key是自己定义的
NSLog(@"content = [%@], badge = [%ld], sound = [%@], Extras = [%@]", content, (long)badge, sound, Extras);
// iOS badge 清0
application.applicationIconBadgeNumber = 0;
// 同步通知角标数到服务端
// [self syncBadgeNum:0];
// 通知打开回执上报
// [CloudPushSDK handleReceiveRemoteNotification:userInfo];(Deprecated from v1.8.1)
[CloudPushSDK sendNotificationAck:userInfo];
}
#pragma mark Channel Opened
/**
* 注册推送通道打开监听
*/
- (void)listenerOnChannelOpened {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onChannelOpened:)
name:@"CCPDidChannelConnectedSuccess"
object:nil];
}
/**
* 推送通道打开回调
*
* @param notification
*/
- (void)onChannelOpened:(NSNotification *)notification {
// [MBProgressHUD showSuccess:@"消息通道建立成功" toView:kAppWindow];
DLog(@"消息通道建立成功");
}
#pragma mark Receive Message
/**
* @brief 注册推送消息到来监听
*/
- (void)registerMessageReceive {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onMessageReceived:)
name:@"CCPDidReceiveMessageNotification"
object:nil];
}
/**
* 处理到来推送消息
*
* @param notification
*/
- (void)onMessageReceived:(NSNotification *)notification {
NSLog(@"Receive one message!");
CCPSysMessage *message = [notification object];
NSString *title = [[NSString alloc] initWithData:message.title encoding:NSUTF8StringEncoding];
NSString *body = [[NSString alloc] initWithData:message.body encoding:NSUTF8StringEncoding];
NSLog(@"Receive message title: %@, content: %@.", title, body);
}
/* 同步通知角标数到服务端 */
- (void)syncBadgeNum:(NSUInteger)badgeNum {
[CloudPushSDK syncBadgeNum:badgeNum withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
NSLog(@"Sync badge num: [%lu] success.", (unsigned long)badgeNum);
} else {
NSLog(@"Sync badge num: [%lu] failed, error: %@", (unsigned long)badgeNum, res.error);
}
}];
}
#pragma mark 禁止横屏
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskPortrait;
}
- (void)applicationWillResignActive:(UIApplication *)application {}
- (void)applicationDidEnterBackground:(UIApplication *)application {}
- (void)applicationWillEnterForeground:(UIApplication *)application {}
- (void)applicationDidBecomeActive:(UIApplication *)application {}
- (void)applicationWillTerminate:(UIApplication *)application {
}
@end
以上代码是根据阿里云的github上的demo进行的相关配置,demo地址
到此为止,阿里云移动推送已经完成集成,可以正式接收相关通知。
如果以上的方法帮助到你了,欢迎分享,更欢迎底部赞赏,也可以直接打开支付宝进行打赏支持作者创作,感谢感谢!
支付宝账号:[email protected]
欢迎和我交流,QQ和微信:834537795(小蜜蜂)