關於個推的理解

一、後臺不能收到通知

首先要強調的一點是,假如程序退出前臺之後不能收到通知是什麼原因,剛開始的時候一直找一直找,問個推客服,都沒解決,後面仔細看了有關APNS和個推的文檔,根據個推文檔的非本問題有關文檔,我發現:




因爲推送證書並不是我做的 所以我猜想是不是在蘋果官網導出的推送證書不正確,所以我自己去根據個推的教程導了一遍,果然,成功了。可見,這些文檔非常重要,要一步一步做。在此 僅附上少量截圖與鏈接,不一一概述。






附錄:創建Apple應用並創建APNS推送證書

注:上述只是其中幾個截圖,並不是連貫在一起的。

二、Clientid和devicetoken綁定

關於個推必須確認Clientid和devicetoken綁定是否正確”,綁定不正確,也有可能後臺收不到通知,解決辦法:1、可以先在手機上刪除App,然後重新運行。2、找個推客服。當然第一點基於一定要 推送證書正確。

三、APNS推送的流程

看了很多關於蘋果推送的文檔,然後纔對整個流程有個稍微清晰的理解。直接借用官方的圖片,再加上自己的一些理解。




按照我的理解,是這樣的。在3-3中,1、通過代碼讓手機先與蘋果的APNS取得連接(蘋果規定,推送服務必須由蘋果APNS來對客戶進行推送,所以,任何第三方都需先把推送發給蘋果的APNS!!),2、從APNS獲取本機的deviceToken(若是運用到第三方,例如:極光推送,百度雲推送,個推。應該會由第三方來完成3-3),3、將本機的deviceToken與Client App(客戶端應用程序)進行綁定,4、把deviceToken發給服務器(第三方)。

當需要服務器對App進行推送時,3-1,服務器會先發送信息給APNS,APNS再根據deviceToken發給對應的電腦或者手機端,再發至對應的App。

至此,整個推送的粗略流程完成。

四、使用定位功能

在使用個推中,由於個推的配置是在AppDelegate中完成,所以不可避免的代碼終究要跳入我們的Controller。在使用定位的功能中,切記 加上代理要設爲自己,猜想可能是因爲:跳入Controller的時候 此時定位代理未設置 所以並不會執行定位代理。我做的時候 就半天沒跳代理,弄的獲取不了本機位置。貼上例子:
- (void)GexinSdkDidReceivePayload:(NSString *)payloadId fromApplication:(NSString *)appId
{
    // [4]: 收到個推消息
    
    NSData *payload = [_gexinPusher retrivePayloadById:payloadId];
    NSString *payloadMsg = nil;
    if (payload) {
        payloadMsg = [[NSString alloc] initWithBytes:payload.bytes
                                              length:payload.length
                                            encoding:NSUTF8StringEncoding];
    }
//    NSString *record = [NSString stringWithFormat:@"%d, %@, %@", ++_lastPayloadIndex, [NSDate date], payloadMsg];
    NSString *record = [NSString stringWithFormat:@"%@",payloadMsg];
    if (record != nil) {
        ImmediLocaInfo *PositInfo = [[ImmediLocaInfo alloc] init];
            if ([PositInfo.type isEqualToString:@"05"]) {
                [_kqViewController lijidingwei:record];
            }else if ([PositInfo.type isEqualToString:@"03"]){
                [_kqViewController dingshidingwei:record];
        }
    }
}
-(void)lijidingwei:(NSString *)aMsg{
    //============立即定位===============//
    _immediLocaInfo = [[ImmediLocaInfo alloc] init];
    if (_userLocation == nil) {
        _userLocation = [[BMKLocationService alloc] init];
    }
    _userLocation.delegate = self;
    [ImmediLocaInfo sharedInstance].pType = 20;
    NSLog(@"%@",_userLocation.delegate);
    [_userLocation startUserLocationService];
}

如代碼所示 假如需要跳至不同的方法,然後在不同的方法裏面又需跳至同一方法(例如本例中定位 都需跳入didUpdataUserLocation)。此時就需定個標誌[ImmediLocaInfosharedInstance].pType = 20。必須用單例。因爲跳入方法後 還需要繼續跳回AppDelegate,此時若不設置單例,跳回去的時候,全局變量則會消失,不能判斷

PS:記得遵守代理 百度地圖定位代理爲 BMKLocationServiceDelegate 。蘋果自帶定位代理爲 CLLocationManagerDelegate ,CLLocationManager *locManager。

    locManager = [[CLLocationManager alloc]init];
    //設置代理
    locManager.delegate = self;
    //設置位置經度
    locManager.desiredAccuracy = kCLLocationAccuracyBest;
    //設置距離過濾器爲100米,表示每移動100米更新一次位置
    locManager.distanceFilter = 100;
    //開始定位服務
    [locManager startUpdatingLocation];

//協議中的方法,作用是每當位置發生更新時會調用的委託方法
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
    //結構體,存儲位置座標
    CLLocationCoordinate2D loc = [newLocation coordinate];
    double longitude = loc.longitude;
    double latitude = loc.latitude;
    fx = [NSString stringWithFormat:@"%g",longitude];
    fy = [NSString stringWithFormat:@"%g",latitude];
    [locManager stopUpdatingLocation];
}

五、個推代碼理解

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
    NSLog(@"deviceToken: %@", deviceToken);
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
	_deviceToken = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"deviceToken:%@", _deviceToken);
    
    
    // [3]:向個推服務器註冊deviceToken
    if (_gexinPusher) {
        [_gexinPusher registerDeviceToken:_deviceToken];
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
    // [3-EXT]:如果APNS註冊失敗,通知個推服務器
    if (_gexinPusher) {
        [_gexinPusher registerDeviceToken:@""];
    }
    
	NSLog(@"didFailToRegisterForRemoteNotificationsWithError:%@", [error localizedDescription]);
}

#pragma mark - GexinSdkDelegate

- (void)GexinSdkDidRegisterClient:(NSString *)clientId

{

    [ImmediLocaInfosharedInstance].CID = clientId;

    // [4-EXT-1]: 個推SDK已註冊

    _sdkStatus =SdkStatusStarted;

    //    [self stopSdk];

}

此時會收到 clientId ,[3]:向個推服務器註冊deviceToken,成功綁定後 通知代理,返回 clientId 。

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // [EXT] 切後臺關閉SDK,讓SDK第一時間斷線,讓個推先用APN推送
    [self stopSdk];
}
一旦推出前臺,讓個推直接斷線,然後服務器會發送推送消息給APNS,再由APNS來推送至手機端App。

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // [EXT] 重新上線
    [self startSdkWith:_appID appKey:_appKey appSecret:_appSecret];
}

後臺收到通知後,點進程序,個推重新上線,開始執行代碼。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userinfo
{    
    // [4-EXT]:處理APN
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    [UIApplication sharedApplication].applicationIconBadgeNumber = 1;
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
    [self startSdkWith:_appID appKey:_appKey appSecret:_appSecret];
    NSString *payloadMsg = [userinfo objectForKey:@"payload"];
    NSString *record = [NSString stringWithFormat:@"[APN]%@, %@", [NSDate date], payloadMsg];
}

此代碼爲不想通過個推的重新上線後來處理推送消息,而是通過APNS處理消息。


- (void)GexinSdkDidOccurError:(NSError *)error
{
    // [EXT]:個推錯誤報告,集成步驟發生的任何錯誤都在這裏通知,如果集成後,無法正常收到消息,查看這裏的通知。
//    [_viewController logMsg:[NSString stringWithFormat:@">>>[GexinSdk error]:%@", [error localizedDescription]]];
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章