記錄一次集成阿里移動推送和支付寶同時存在的過程(最詳細(xì)集成阿里云移動推送)

在國內(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)行操作,可是的可是,還是不行哦,頭大!如下圖:

阿里移動推送下載的SDK

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


售后聊天
售后聊天
售后聊天

剝離UTDID:https://help.aliyun.com/document_detail/59152.html?spm=5176.smartservice_service_chat.0.0.2a97709avL99Wx

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

剝離UTDID

同樣阿里云也是推薦是支付寶支付使用剝離UTDID的支付寶SDK,然后保留阿里云平臺的UTDID包。

那么下面來詳細(xì)說明一下接入的過程:
1、打開移動推送的開發(fā)者文檔,iOS 移動推送SDK配置(點(diǎn)我打開)

2、pod方式,如下圖:


pod方式

Podfile文件就是這樣子:


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)目里面的包,如下圖:

下載兼容版本支付寶SDK

兼容版支付寶SDK

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

CMMotionManager報錯

備注:CMMotionManager 是 Core Motion 庫的核心類,負(fù)責(zé)獲取和處理手機(jī)的運(yùn)動信息。

項(xiàng)目中缺少CMMotionManager的庫,所以點(diǎn)擊添加相關(guān)庫。

添加CMMotionManager庫
添加CMMotionManager庫

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


添加阿里云plist文件

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地址

移動推送demo

到此為止,阿里云移動推送已經(jīng)完成集成,可以正式接收相關(guān)通知。

如果以上的方法幫助到你了,歡迎分享,更歡迎簡書底部贊賞,也可以直接打開支付寶進(jìn)行打賞支持作者創(chuàng)作,感謝感謝!

支付寶賬號:zouhuaping123@qq.com

歡迎和我交流,QQ和微信:834537795(小蜜蜂)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容