在國內(nèi)APP需要接入支付的話,支付寶支付和微信支付那肯定是必不可少的,在支付領(lǐng)域那二者肯定是同坐頭把交椅的,支付是沒得說,但是其他領(lǐng)域就不一定了,比如下面我們即將要講的推送,常用的或者市場份額大的當(dāng)然是極光推送,可在前期的調(diào)研和對比階段之后,產(chǎn)品和CTO沒有選擇常用的極光推送,而是選擇了小眾的阿里云移動推送,說句實(shí)話在公司沒說要用之前,我們移動端開發(fā)都不知道阿里竟然還有推送的產(chǎn)品,阿里的產(chǎn)品用得最多的友盟和支付寶支付,那么下面就來說說集成阿里云移動推送的過程。
我們的情況是已經(jīng)在項(xiàng)目中已經(jīng)手動集成了支付寶支付,現(xiàn)在需要再加上阿里云推送,當(dāng)然首先單獨(dú)寫了一個demo按阿里云的開發(fā)者文檔進(jìn)行cocopods形式的集成,一下子很快就測試成功了,我想這么簡單,那好啊!可是沒想到的是當(dāng)我把相同的配置方法加入的真正的項(xiàng)目中并進(jìn)行cocopods集成的時候,馬上紅色報錯就來了,如下圖:

這個報錯的關(guān)鍵字就是“UTDID”,那就要找和這個有關(guān)的了,Xcode項(xiàng)目里面全局搜索“UTDID”,支付寶支付的庫里面含有這個,但是我打開本地的支付寶庫卻是找不到,因?yàn)樗麄儼堰@個放在了framework里面,那竟然是這樣的話,這個時候我想到了那么移動推送里面的UTDID就不要接入不就可以了,這樣就不能使用cocopods集成了,刪掉cocopods集成的庫,然后改用手動集成,按阿里云的步驟進(jìn)行操作,可是的可是,還是不行哦,頭大!如下圖:

接著我咨詢了阿里云的售后服務(wù),如下圖:



反正反正這么一波操作,我還是沒有成功收到推送消息,真是崩潰。那么這個時候就要換個思路了,同時與售后的聊天過程中也知道了個事情,那就是移動推送還是使用cocopods集成,不用手動集成了,原先的想法是支付寶支付已經(jīng)成功了,支付寶支付功能是集成成功的了,那么既然移動推送只能用cocopods集成,而cocopods集成卻不能單獨(dú)剝離UTDID,那這么說就只能去把支付寶支付庫里面的UTDID給刪掉了,剝離的方法鏈接也上一個,阿里云-云產(chǎn)品SDK UTDID沖突解決方案

同樣阿里云也是推薦是支付寶支付使用剝離UTDID的支付寶SDK,然后保留阿里云平臺的UTDID包。
那么下面來詳細(xì)說明一下接入的過程:
1、打開移動推送的開發(fā)者文檔,iOS 移動推送SDK配置(點(diǎn)我打開)
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、運(yùn)行 pod update --no-repo-update命令,建議最好能連上外網(wǎng)的網(wǎng)絡(luò)下載,這樣就快很多;
4、下載完成之后,運(yùn)行項(xiàng)目肯定還是會報UTDID的沖突報錯,這個時候我們就下從支付寶開發(fā)文檔下載的兼容包去替換原先項(xiàng)目里面的包,如下圖:


5、替換完成后運(yùn)行還是會報錯,OBJC_CLASS$_CMMotionManager,如下圖:

備注:CMMotionManager 是 Core Motion 庫的核心類,負(fù)責(zé)獲取和處理手機(jī)的運(yùn)動信息。
項(xiàng)目中缺少CMMotionManager的庫,所以點(diǎn)擊添加相關(guān)庫。


6、還建議不要忘記在項(xiàng)目中拖入AliyunEmasServices-Info.plist文件,要不然推送是收不到的,打印窗里面也會有相關(guān)報錯打印。

7、在AppDelegate.m里面寫入阿里云移動推送相關(guān)代碼,如下:
#import "AppDelegate.h"
//阿里推送
#import <CloudPushSDK/CloudPushSDK.h>
// iOS 10 notification
#import <UserNotifications/UserNotifications.h>
static NSString *const testAppKey = @“填入阿里云移動推送APPKey;
static NSString *const testAppSecret = @"填入阿里云移動推送AppSecret";
@interface AppDelegate ()<UNUserNotificationCenterDelegate>
@end
@implementation AppDelegate{
// iOS 10通知中心
UNUserNotificationCenter *_notificationCenter;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//這里一定要強(qiáng)引用self.baseVc為屬性,要不然后面會不執(zhí)行代理方法
self.baseTabBarVc = [[XMFBaseUseingTabarController alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
//設(shè)置window的背景顏色,防止有些present控制器的時候背景黑屏
self.window.backgroundColor = KWhiteColor;
self.window.rootViewController = self.baseTabBarVc;
[self.window makeKeyAndVisible];
// APNs注冊,獲取deviceToken并上報
[self registerAPNS:application];
// 初始化SDK
[self initCloudPush];
// 監(jiān)聽推送通道打開動作
[self listenerOnChannelOpened];
// 監(jiān)聽推送消息到達(dá)
[self registerMessageReceive];
// 點(diǎn)擊通知將App從關(guān)閉狀態(tài)啟動時,將通知打開回執(zhí)上報
// [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];
// 創(chuàng)建category,并注冊到通知中心
[self createCustomNotificationCategory];
_notificationCenter.delegate = self;
// 請求推送權(quán)限
[_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
}
}
/**
* 主動獲取設(shè)備通知是否授權(quán)(iOS 10+)
*/
- (void)getNotificationSettingStatus {
[_notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
NSLog(@"User authed.");
} else {
NSLog(@"User denied.");
}
}];
}
/*
* APNs注冊成功回調(diào),將返回的deviceToken上傳到CloudPush服務(wù)器
*/
- (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注冊失敗回調(diào)
*/
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"didFailToRegisterForRemoteNotificationsWithError %@", error);
}
/**
* 創(chuàng)建并注冊通知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];
// 創(chuàng)建id為`test_category`的category,并注冊兩個action到category
// UNNotificationCategoryOptionCustomDismissAction表明可以觸發(fā)通知的dismiss回調(diào)
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;
// 標(biāo)題
NSString *title = content.title;
// 副標(biāo)題
NSString *subtitle = content.subtitle;
// 內(nèi)容
NSString *body = content.body;
// 角標(biāo)
int badge = [content.badge intValue];
// 取得通知自定義字段內(nèi)容,例:獲取key為"Extras"的內(nèi)容
NSString *extras = [userInfo valueForKey:@"Extras"];
// 通知角標(biāo)數(shù)清0
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
// 同步角標(biāo)數(shù)到服務(wù)端
// [self syncBadgeNum:0];
// 通知打開回執(zhí)上報
[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通知,并上報通知打開回執(zhí)
[self handleiOS10Notification:notification];
// 通知不彈出
completionHandler(UNNotificationPresentationOptionNone);
// 通知彈出,且?guī)в新曇?、?nèi)容和角標(biāo)
//completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
/**
* 觸發(fā)通知動作時回調(diào),比如點(diǎn)擊、刪除通知和點(diǎn)擊自定義action(iOS 10+)
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSString *userAction = response.actionIdentifier;
// 點(diǎn)擊通知打開
if ([userAction isEqualToString:UNNotificationDefaultActionIdentifier]) {
NSLog(@"User opened the notification.");
// 處理iOS 10通知,并上報通知打開回執(zhí)
[self handleiOS10Notification:response.notification];
}
// 通知dismiss,category創(chuàng)建時傳入UNNotificationCategoryOptionCustomDismissAction才可以觸發(fā)
if ([userAction isEqualToString:UNNotificationDismissActionIdentifier]) {
[CloudPushSDK sendDeleteNotificationAck:response.notification.request.content.userInfo];
}
NSString *customAction1 = @"action1";
NSString *customAction2 = @"action2";
// 點(diǎn)擊用戶自定義Action1
if ([userAction isEqualToString:customAction1]) {
NSLog(@"User custom action1.");
}
// 點(diǎn)擊用戶自定義Action2
if ([userAction isEqualToString:customAction2]) {
NSLog(@"User custom action2.");
}
completionHandler();
}
#pragma mark SDK Init
- (void)initCloudPush {
// 正式上線建議關(guān)閉
[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處于啟動狀態(tài)時,通知打開回調(diào)
*/
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo {
NSLog(@"Receive one notification.");
// 取得APNS通知內(nèi)容
NSDictionary *aps = [userInfo valueForKey:@"aps"];
// 內(nèi)容
NSString *content = [aps valueForKey:@"alert"];
// badge數(shù)量
NSInteger badge = [[aps valueForKey:@"badge"] integerValue];
// 播放聲音
NSString *sound = [aps valueForKey:@"sound"];
// 取得通知自定義字段內(nèi)容,例:獲取key為"Extras"的內(nèi)容
NSString *Extras = [userInfo valueForKey:@"Extras"]; //服務(wù)端中Extras字段,key是自己定義的
NSLog(@"content = [%@], badge = [%ld], sound = [%@], Extras = [%@]", content, (long)badge, sound, Extras);
// iOS badge 清0
application.applicationIconBadgeNumber = 0;
// 同步通知角標(biāo)數(shù)到服務(wù)端
// [self syncBadgeNum:0];
// 通知打開回執(zhí)上報
// [CloudPushSDK handleReceiveRemoteNotification:userInfo];(Deprecated from v1.8.1)
[CloudPushSDK sendNotificationAck:userInfo];
}
#pragma mark Channel Opened
/**
* 注冊推送通道打開監(jiān)聽
*/
- (void)listenerOnChannelOpened {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onChannelOpened:)
name:@"CCPDidChannelConnectedSuccess"
object:nil];
}
/**
* 推送通道打開回調(diào)
*
* @param notification
*/
- (void)onChannelOpened:(NSNotification *)notification {
// [MBProgressHUD showSuccess:@"消息通道建立成功" toView:kAppWindow];
DLog(@"消息通道建立成功");
}
#pragma mark Receive Message
/**
* @brief 注冊推送消息到來監(jiān)聽
*/
- (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);
}
/* 同步通知角標(biāo)數(shù)到服務(wù)端 */
- (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
以上代碼是根據(jù)阿里云的github上的demo進(jìn)行的相關(guān)配置,demo地址

到此為止,阿里云移動推送已經(jīng)完成集成,可以正式接收相關(guān)通知。
如果以上的方法幫助到你了,歡迎分享,更歡迎簡書底部贊賞,也可以直接打開支付寶進(jìn)行打賞支持作者創(chuàng)作,感謝感謝!
支付寶賬號:zouhuaping123@qq.com
歡迎和我交流,QQ和微信:834537795(小蜜蜂)