私有Pods封装个推SDK功能(解决方案)

一:运用场景

公司中同时有好几个APP在开发,而且每个APP都有使用到集成个推SDK来处理消息的功能,以前的做法是每个APP都去集成并在AppDelegate处理一些SDK的代码,包含个推基础配置、消息接收处理、远程信息处理、苹果通知注册等等;后来你会发现其实在这部分内容中只有配置跟消息接收时存在差异,毕竟接收消息用来处理不同的业务逻辑问题;今天要介绍的功能就是把相同或不变的内容封装起来,开放出差异给每个APP的AppDelegate进行处理;而对于这部分相同的封装运用私有Pods进行管理,所以封装后的个推使用起来很简单,哪怕你对个推都不了解也能在一分钟搞定个推集成功能;

实现这个封装运用下面几个知识点,私有Pods的搭建、AppDelegate方法的注入(采用插件XAspect 地址:https://github.com/xareelee/XAspect)

 

二:集成效果

1:首先了解一某个工程内的AppDelegate的代码,从下面的代码你是否已经找不到个推SDK那些代码及你消息注册等等;只在didFinishLaunchingWithOptions中增加一个配置,其它两个方法是用来处理消息的内容;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    //配置个推信息
    jiaGTConfigManager *gtConfig=[jiaGTConfigManager sharedInstance];
    gtConfig.jiaGTAppId=@"C83sm0U3xt5D5GUYqkfk53";
    gtConfig.jiaGTAppKey=@"13OydrjIuC8TZliF43hRS5";
    gtConfig.jiaGTAppSecret=@"gdgYQJSUNa5pIQB2icrCt1";
    
    ViewController *logInVc = [[ViewController alloc]init];
    self.window.rootViewController = logInVc;
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
}


/**
 *  @author wujunyang, 16-07-07 16:07:25
 *
 *  @brief  处理个推消息
 *
 *  @param notificationObject <#notificationObject description#>
 */
-(void)gtNotification:(NSObject *)notificationObject
{
    if (notificationObject) {
        NSNotification *curNotification=(NSNotification *)notificationObject;
        NSLog(@"%@",curNotification.userInfo[@"payload"]);
        NSLog(@"-----接收到个推通知------");
    }
}


/**
 *  @author wujunyang, 16-07-07 16:07:40
 *
 *  @brief  处理远程苹果通知
 *
 *  @param notificationObject <#notificationObject description#>
 */
-(void)receiveRemoteNotification:(NSObject *)notificationObject
{
    if (notificationObject) {
        NSNotification *curNotification=(NSNotification *)notificationObject;
        UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"您有一条新消息" message:[NSString stringWithFormat:@"%@,%@",curNotification.userInfo[@"payload"],curNotification.userInfo[@"message"]] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
        [alert show];
    }
}

 

2:工程中的AppDelegate继承于我们定义的父类jiaAppDelegate,关于jiaAppDelegate是什么,jiaGTConfigManager又是干什么;你可以接着往下看;

#import <UIKit/UIKit.h>
#import "jiaAppDelegate.h"
#import "jiaGTConfigManager.h"


@interface AppDelegate :jiaAppDelegate<UIAlertViewDelegate>

@end

 

3:引入Pod指令

link_with ['WjyTestClassDemo']

source 'https://github.com/CocoaPods/Specs.git'        #官方仓库地址
source ‘https://github.com/wujunyang/WjySpecs.git’        #私有仓库地址

platform :ios, "7.0"

pod "QiJIAGTSDK"

 

4:查看效果图

 

到这边如果你只是运用,那么就可以结束了;就算你不懂个推也已经搞定集成功能;

 

三:实现过程

为了实现上面这个简化版的集成功能,我们采用的私有Pods对个推进行管理,主要是把个推SDK跟我们编写的一些代码进行整合;关于如果搭建私有Pods不是本文的重点,如果说你对这方面也有感兴趣可以留言,我再写一个关于搭建私有Pods的文章,网络上也有很多这方面的内容,欢迎一起交流;当然XAspect在封装的过程中也起到很重要的作用,它的注入功能解决把原本应该在AppDelegate的代码解耦出来;

1:首先创建一个AppDelegate,主要作用是为了其它项目的AppDelegate可以以它为基类,而我的XAspect文件就可以只对我这个父类的AppDelegate进行注入,方便后期我扩展,比如后期我可能要实现关于友盟SDK、融云SDK的集成封装;

jiaAppDelegate.h的文件内容:

#import <UIKit/UIKit.h>

@interface jiaAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

jiaAppDelegate.m的文件内容:

#import "jiaAppDelegate.h"

@interface jiaAppDelegate()

@end

@implementation jiaAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
}

- (void)applicationWillTerminate:(UIApplication *)application {
}

-(void)dealloc
{
}

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
}


-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
}
@end

是否发现其实jiaAppDelegate在这我什么也没有做,这样其实就足够了;因为这部分是比较基础的内容,所以我也用Pods进行管理,当然你也可以再创建一个viewController的基类,让你的工程所有的都以这为基类进行开发,有基类在手你后期一些扩展都比较好办;

 

2:接下来将要介绍关于集成个推模块的功能及相关代码,也是本文的重点;首先你可以上个推的gitHub去下载它最新的SDK及一个头文件GeTuiSdk.h;其实这两个文件也是你平时集成个推时引入到工程的内容;如下的目录是被我封装后的个推目录结构;除了那两个文件其它就是抽离出来的内容;

 

 

2.1 jiaAppDelegate+myGt类作用

因为封装的这个推SDK是依赖我们上面jiaAppDelegate;所以我们就可以对它进行扩展,创建这个Category是为了解决关于个推GeTuiSdkDelegate,因为XAspect 目前无法针对Delegate进行声明引用;

jiaAppDelegate+myGt.h的文件内容:

#import "jiaAppDelegate.h"
#import "GeTuiSdk.h"


@interface jiaAppDelegate (myGt)<GeTuiSdkDelegate>

@end

jiaAppDelegate+myGt.m的文件内容:

#import "jiaAppDelegate+myGt.h"

@implementation jiaAppDelegate (myGt)

@end

从上面的代码可以看出来只是引入的<GeTuiSdkDelegate>,这个Category什么都没有实现;

 

2.2 jiaGTConfigManager类作用

因为在个推会存在基础配置的内容,决定创建一个配置类进行管理,它是一个单例模式;

jiaGTConfigManager.h文件的内容

#import <Foundation/Foundation.h>

@interface jiaGTConfigManager : NSObject

+ (jiaGTConfigManager *)sharedInstance;

//个推配置
@property (strong, nonatomic) NSString *jiaGTAppId;
@property (strong, nonatomic) NSString *jiaGTAppKey;
@property (strong, nonatomic) NSString *jiaGTAppSecret;

@end

jiaGTConfigManager.m文件的内容

#import "jiaGTConfigManager.h"

@implementation jiaGTConfigManager

+ (jiaGTConfigManager *)sharedInstance
{
    static jiaGTConfigManager* instance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [jiaGTConfigManager new];
    });

    return instance;
}

@end

只是开放出三个属性用于获取到配置内容;

 

2.3 XAspect-GeTuiAppDelegate作用

正如前面说的个推集成的代码是工程当前的AppDelegate不用写,但并不代码一直不用写,只是被我们抽离在XAspect-GeTuiAppDelegate中,更加模块化;XAspect插件运用起来很比较简单,它比较一般注入的插件好处是可以多次对同一个文件相同的方法进行注入;

AspectPatch(-, BOOL, application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions)
{
    //个推初始化
    [self initLoadGeTui:launchOptions];
    
    //注册个推通知事件
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(geTuiMessageHandling:) name:jiaGeTuiNotification object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveRemoteMessageHandling:) name:jiaReceiveRemoteNotification object:nil];
    
    return XAMessageForward(application:application didFinishLaunchingWithOptions:launchOptions);
}

上面这段代码就是Aspect针对didFinishLaunchingWithOptions的注入,如果有多个文件它都会进行注入到此方法中;类似的写法就不再介绍,可以去官网进行了解;接收到个推消息跟远程消息运用本地通知的方式进行获取;

/** SDK收到透传消息回调 */
- (void)GeTuiSdkDidReceivePayload:(NSString *)payloadId andTaskId:(NSString *)taskId andMessageId:(NSString *)aMsgId andOffLine:(BOOL)offLine fromApplication:(NSString *)appId {
    
    [self handlePushMessage:nil notification:nil];
    // [4]: 收到个推消息
    NSData *payload = [GeTuiSdk retrivePayloadById:payloadId];
    NSString *payloadMsg = nil;
    if (payload) {
        payloadMsg = [[NSString alloc] initWithBytes:payload.bytes length:payload.length encoding:NSUTF8StringEncoding];
    }
    
    NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:aMsgId,@"aMsgId", [NSNumber numberWithBool:offLine],@"offLine",appId,@"appId",payloadMsg,@"payload",nil];
    //创建通知
    NSNotification *notification =[NSNotification notificationWithName:@"jiaGeTuiNotification" object:nil userInfo:dict];
    //通过通知中心发送通知
    [[NSNotificationCenter defaultCenter] postNotification:notification];
}

在获取到个推消息后我可以针对消息的内容先处理解析,因为本地通知的参数是一个字典,所以你可以存入你想开放的信息内容,然后再把它传给本地通知作处理,这样你在真正业务要使用的地方已经相当简便;远程通知也是类似;

而关于处理本地通知的方法让使用的当前工程AppDelegate去实现,方法gtNotification跟receiveRemoteNotification正是开头文章我们调用的方法;

//处理个推本地通知,判断是否存在gtNotification方法
- (void)geTuiMessageHandling:(NSNotification *)text{
    SEL gtNotificationSelector=@selector(gtNotification:);
    if([self respondsToSelector:gtNotificationSelector])
    {
        [self performSelector:gtNotificationSelector withObject:text];
    }
}


//处理苹果远程通知,判断是否存在receiveRemoteNotification方法
- (void)receiveRemoteMessageHandling:(NSNotification *)text{
    SEL receiveRemoteNotificationSelector=@selector(receiveRemoteNotification:);
    if([self respondsToSelector:receiveRemoteNotificationSelector])
    {
        [self performSelector:receiveRemoteNotificationSelector withObject:text];
    }
}

因为Aspect是要针对某个类进行注入,这个也是我们创建GeTuiAppDelegate基类的意义,这样我都可以只针对这个基类进行注入;你可以看到XAspect-GeTuiAppDelegate开头有这么两句,AtAspectOfClass就是指向类;

#define AtAspect GeTuiAppDelegate

#define AtAspectOfClass jiaAppDelegate

上面只是简单介绍一下XAspect-GeTuiAppDelegate的内容,下面是我会把它的完全代码贴出来;

 

四:引入私有Pod

当我们上面封装好的代码就可以进行使用Pod的打包,并推到我们的私有仓库,让别人使用了;虽然私有Pod不是本文的重点,但也把相关的创建命令提供出来,若有不明白可以留言其它文章更新;

1:当前podspec文件内容

Pod::Spec.new do |s|

  # ―――  Spec Metadata  ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  These will help people to find your library, and whilst it
  #  can feel like a chore to fill in it's definitely to your advantage. The
  #  summary should be tweet-length, and the description more in depth.
  #

  s.name         = "QiJIAGTSDK"
  s.version      = "1.4.4"
  s.summary      = "个推iOS SDK Cocoa Pods集成库"

  s.description  = <<-DESC
                   A longer description of getui-sdk-ios-cocoapods in Markdown format.

                   个推iOS SDK
                   DESC

  s.homepage     = "https://github.com/GetuiLaboratory/getui-sdk-ios-cocoapods"
  # s.screenshots  = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"


  # ―――  Spec License  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Licensing your code is important. See http://choosealicense.com for more info.
  #  CocoaPods will detect a license file if there is a named LICENSE*
  #  Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
  #

 # s.license      = "MIT (example)"
  s.license      = { :type => "MIT", :file => "LICENSE" }


  # ――― Author Metadata  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the authors of the library, with email addresses. Email addresses
  #  of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
  #  accepts just a name if you'd rather not provide an email address.
  #
  #  Specify a social_media_url where others can refer to, for example a twitter
  #  profile URL.
  #

  s.author             = { "个推" => "support@getui.com" }
  # Or just: s.author    = "个推实验室"
  # s.authors            = { "个推实验室" => "support@getui.com" }
  # s.social_media_url   = "http://twitter.com/个推实验室"

  # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If this Pod runs only on iOS or OS X, then specify the platform and
  #  the deployment target. You can optionally include the target after the platform.
  #

  # s.platform     = :ios
  s.platform     = :ios, "7.0"

  #  When using multiple platforms
  s.ios.deployment_target = "7.0"
  # s.osx.deployment_target = "10.7"
  # s.watchos.deployment_target = "2.0"


  # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the location from where the source should be retrieved.
  #  Supports git, hg, bzr, svn and HTTP.
  #

  s.source       = { :git => "https://github.com/wujunyang/jiaGTSDK.git", :tag => "1.4.4" }


  # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  CocoaPods is smart about how it includes source code. For source files
  #  giving a folder will include any swift, h, m, mm, c & cpp files.
  #  For header files it will include any header in the folder.
  #  Not including the public_header_files will make all headers public.
  #

  s.source_files  = "Pod/**/*.{h,m}"
  #s.exclude_files = "Classes/Exclude"

  # s.public_header_files = "Classes/**/*.h"


  # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  A list of resources included with the Pod. These are copied into the
  #  target bundle with a build phase script. Anything else will be cleaned.
  #  You can preserve files from being cleaned, please don't preserve
  #  non-essential files like tests, examples and documentation.
  #

  # s.resource  = "icon.png"
  # s.resources = "Resources/*.png"

  s.preserve_paths = "libGeTuiSdk-1.4.2.a"
  s.ios.vendored_library = "libGeTuiSdk-1.4.2.a"


  # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Link your library with frameworks, or libraries. Libraries do not include
  #  the lib prefix of their name.
  #

  #s.framework  = "UIKit"
  # s.frameworks = "SomeFramework", "AnotherFramework"
  s.frameworks = 'SystemConfiguration', 'CFNetwork','CoreTelephony','CoreLocation','AVFoundation','CoreBluetooth','Security','JavaScriptCore'
  s.ios.frameworks = 'SystemConfiguration', 'CFNetwork','CoreTelephony','CoreLocation','AVFoundation','CoreBluetooth','Security','JavaScriptCore'
  # s.library   = "sqlite3"
  s.ios.libraries = 'z','sqlite3.0'

  # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If your library depends on compiler flags you can set them in the xcconfig hash
  #  where they will only apply to your library. If you depend on other Podspecs
  #  you can include multiple dependencies to ensure it works.

  s.requires_arc = true

  # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
  s.dependency "jiaCore"
end

其实这个文件是拿个推那个进行简单修改,而个推的SDK被我们用自个的git进行管理起来;主要是因为它是静态的framework文件,所以在私有pod引入静态的framework文件一直失败,所以才想出这个办法;

 

2:私有Pod检验跟合并推仓库的指令

pod lib lint QiJIAGTSDK.podspec --use-libraries --verbose --allow-warnings --sources='https://github.com/CocoaPods/Specs.git,https://github.com/wujunyang/WjySpecs.git'


pod repo push WjySpecs QiJIAGTSDK.podspec --use-libraries --verbose --allow-warnings --sources='https://github.com/CocoaPods/Specs.git,https://github.com/wujunyang/WjySpecs.git'

主要是包含静态所以指令中--use-libraries,而sources则是关于仓库的地址,一个是公共一个是我们自个私有;

当你封装好推到私有仓库后,对于后面新项目你只要告诉它Pod引入命令,并配置跟处理消息就可以了;完全不用开发者了解关于个推的内容;

 

五:XAspect-GeTuiAppDelegate文件内容:

//
//  XAspect-LogAppDelegate.m
//  MobileProject 抽离原本应在AppDelegate的内容(个推)
//
//  Created by wujunyang on 16/6/22.
//  Copyright © 2016年 wujunyang. All rights reserved.
//

#import "jiaAppDelegate.h"
#import "GeTuiSdk.h"
#import "XAspect.h"
#import "jiaGTConfigManager.h"

NSString * const jiaGeTuiNotification = @"jiaGeTuiNotification";
NSString * const jiaReceiveRemoteNotification = @"jiaReceiveRemoteNotification";


#define AtAspect GeTuiAppDelegate

#define AtAspectOfClass jiaAppDelegate
@classPatchField(jiaAppDelegate)

@synthesizeNucleusPatch(Default, -, BOOL, application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions);
@synthesizeNucleusPatch(Default, -, void, application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken);
@synthesizeNucleusPatch(Default, -, void, application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error);
@synthesizeNucleusPatch(Default, -, void, application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings);
@synthesizeNucleusPatch(Default, -, void, application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler);
@synthesizeNucleusPatch(Default,-,void, dealloc);


AspectPatch(-, BOOL, application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions)
{
    //个推初始化
    [self initLoadGeTui:launchOptions];
    
    //注册个推通知事件
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(geTuiMessageHandling:) name:jiaGeTuiNotification object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveRemoteMessageHandling:) name:jiaReceiveRemoteNotification object:nil];
    
    return XAMessageForward(application:application didFinishLaunchingWithOptions:launchOptions);
}

/** 远程通知注册成功委托 */
AspectPatch(-, void, application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken)
{
    NSString *myToken = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    myToken = [myToken stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    [GeTuiSdk registerDeviceToken:myToken];
    
    NSLog(@"\n>>>[DeviceToken值]:%@\n\n", myToken);
    
    return XAMessageForward(application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken);
}

/** 远程通知注册失败委托 */
AspectPatch(-, void, application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error){
    
    [GeTuiSdk registerDeviceToken:@""];
    
    NSLog(@"\n>>>[DeviceToken失败]:%@\n\n", error.description);
    
    return XAMessageForward(application:application didFailToRegisterForRemoteNotificationsWithError:error);
}


#pragma mark - 用户通知(推送)回调 _IOS 8.0以上使用

/** 已登记用户通知 */
AspectPatch(-, void, application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings)
{
    // 注册远程通知(推送)
    [application registerForRemoteNotifications];
    
    return XAMessageForward(application:application didRegisterUserNotificationSettings:notificationSettings);
}


AspectPatch(-, void,application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler)
{
    
    //处理applicationIconBadgeNumber-1
    [self handlePushMessage:userInfo notification:nil];
    
    //除了个推还要处理走苹果的信息放在body里面
    if (userInfo) {
        NSString *payloadMsg = [userInfo objectForKey:@"payload"];
        NSString *message=[[[userInfo objectForKey:@"aps"]objectForKey:@"alert"]objectForKey:@"body"];
        
        NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:payloadMsg,@"payload",message,@"message",nil];
        //创建通知
        NSNotification *notification =[NSNotification notificationWithName:@"jiaReceiveRemoteNotification" object:nil userInfo:dict];
        //通过通知中心发送通知
        [[NSNotificationCenter defaultCenter] postNotification:notification];
    }
    // 处理APN
    //NSLog(@"\n>>>[Receive RemoteNotification - Background Fetch]:%@\n\n", userInfo);
    completionHandler(UIBackgroundFetchResultNewData);
    return XAMessageForward(application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler);
}

AspectPatch(-, void, dealloc)
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:jiaGeTuiNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:jiaReceiveRemoteNotification object:nil];
    XAMessageForwardDirectly(dealloc);
}


#pragma mark - GeTuiSdkDelegate

/** SDK启动成功返回cid */
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId {
    // [4-EXT-1]: 个推SDK已注册,返回clientId
    NSLog(@"\n>>>[个推Cid]:%@\n\n", clientId);
}

/** SDK遇到错误回调 */
- (void)GeTuiSdkDidOccurError:(NSError *)error {
    // [EXT]:个推错误报告,集成步骤发生的任何错误都在这里通知,如果集成后,无法正常收到消息,查看这里的通知。
    NSLog(@"\n>>>[GexinSdk error]:%@\n\n", [error localizedDescription]);
}



/** SDK收到sendMessage消息回调 */
- (void)GeTuiSdkDidSendMessage:(NSString *)messageId result:(int)result {
    // [4-EXT]:发送上行消息结果反馈
    NSString *msg = [NSString stringWithFormat:@"sendmessage=%@,result=%d", messageId, result];
    NSLog(@"\n>>>[GexinSdk DidSendMessage]:%@\n\n", msg);
}

/** SDK运行状态通知 */
- (void)GeTuiSDkDidNotifySdkState:(SdkStatus)aStatus {
    // [EXT]:通知SDK运行状态
    NSLog(@"\n>>>[GexinSdk SdkState]:%u\n\n", aStatus);
}

/** SDK设置推送模式回调 */
- (void)GeTuiSdkDidSetPushMode:(BOOL)isModeOff error:(NSError *)error {
    if (error) {
        NSLog(@"\n>>>[GexinSdk SetModeOff Error]:%@\n\n", [error localizedDescription]);
        return;
    }
    
    NSLog(@"\n>>>[GexinSdk SetModeOff]:%@\n\n", isModeOff ? @"开启" : @"关闭");
}

// 处理推送消息
- (void)handlePushMessage:(NSDictionary *)dict notification:(UILocalNotification *)localNotification {
    if ([UIApplication sharedApplication].applicationIconBadgeNumber != 0) {
        if (localNotification) {
            [[UIApplication sharedApplication] cancelLocalNotification:localNotification];
        }
        [UIApplication sharedApplication].applicationIconBadgeNumber -= 1;
    }
    else {
        [[UIApplication sharedApplication] cancelAllLocalNotifications];
        [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
    }
}



/** SDK收到透传消息回调 */
- (void)GeTuiSdkDidReceivePayload:(NSString *)payloadId andTaskId:(NSString *)taskId andMessageId:(NSString *)aMsgId andOffLine:(BOOL)offLine fromApplication:(NSString *)appId {
    
    [self handlePushMessage:nil notification:nil];
    // [4]: 收到个推消息
    NSData *payload = [GeTuiSdk retrivePayloadById:payloadId];
    NSString *payloadMsg = nil;
    if (payload) {
        payloadMsg = [[NSString alloc] initWithBytes:payload.bytes length:payload.length encoding:NSUTF8StringEncoding];
    }
    
    NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:aMsgId,@"aMsgId", [NSNumber numberWithBool:offLine],@"offLine",appId,@"appId",payloadMsg,@"payload",nil];
    //创建通知
    NSNotification *notification =[NSNotification notificationWithName:@"jiaGeTuiNotification" object:nil userInfo:dict];
    //通过通知中心发送通知
    [[NSNotificationCenter defaultCenter] postNotification:notification];
}


#pragma mark 自定义关于个推的内容

-(void)initLoadGeTui:(NSDictionary *)launchOptions
{
    // 通过 appId、 appKey 、appSecret 启动SDK,注:该方法需要在主线程中调用
    [GeTuiSdk startSdkWithAppId:[jiaGTConfigManager sharedInstance].jiaGTAppId appKey:[jiaGTConfigManager sharedInstance].jiaGTAppKey appSecret:[jiaGTConfigManager sharedInstance].jiaGTAppSecret delegate:self];
    
    // 注册APNS
    [self registerUserNotification];
    
    // 处理远程通知启动APP
    [self receiveNotificationByLaunchingOptions:launchOptions];
    
    //个推SDK支持当APP进入后台后,个推是否运行。NO是不允许(为了让个APP进入后端时就直接走苹果推送)
    [GeTuiSdk runBackgroundEnable:NO];
}



#pragma mark - 用户通知(推送) _自定义方法

/** 注册用户通知 */
- (void)registerUserNotification {
    
    /*
     注册通知(推送)
     申请App需要接受来自服务商提供推送消息
     */
    
    // 判读系统版本是否是“iOS 8.0”以上
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ||
        [UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
        
        // 定义用户通知类型(Remote.远程 - Badge.标记 Alert.提示 Sound.声音)
        UIUserNotificationType types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
        
        // 定义用户通知设置
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        
        // 注册用户通知 - 根据用户通知设置
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else { // iOS8.0 以前远程推送设置方式
        // 定义远程通知类型(Remote.远程 - Badge.标记 Alert.提示 Sound.声音)
        UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
        
        // 注册远程通知 -根据远程通知类型
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
    }
}

/** 自定义:APP被“推送”启动时处理推送消息处理(APP 未启动--》启动)*/
- (void)receiveNotificationByLaunchingOptions:(NSDictionary *)launchOptions {
    if (!launchOptions)
        return;
    
    /*
     通过“远程推送”启动APP
     UIApplicationLaunchOptionsRemoteNotificationKey 远程推送Key
     */
    NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if (userInfo) {
        NSLog(@"\n>>>[Launching RemoteNotification]:%@", userInfo);
    }
}



//处理个推本地通知,判断是否存在gtNotification方法
- (void)geTuiMessageHandling:(NSNotification *)text{
    SEL gtNotificationSelector=@selector(gtNotification:);
    if([self respondsToSelector:gtNotificationSelector])
    {
        [self performSelector:gtNotificationSelector withObject:text];
    }
}


//处理苹果远程通知,判断是否存在receiveRemoteNotification方法
- (void)receiveRemoteMessageHandling:(NSNotification *)text{
    SEL receiveRemoteNotificationSelector=@selector(receiveRemoteNotification:);
    if([self respondsToSelector:receiveRemoteNotificationSelector])
    {
        [self performSelector:receiveRemoteNotificationSelector withObject:text];
    }
}

@end
#undef AtAspectOfClass
#undef AtAspect

 

最近有个妹子弄的一个关于扩大眼界跟内含的订阅号,每天都会更新一些深度内容,在这里如果你感兴趣也可以关注一下(嘿对美女跟知识感兴趣),当然可以关注后输入:github 会有我的微信号,如果有问题你也可以在那找到我;当然不感兴趣无视此信息;

posted @ 2016-07-07 18:02  踏浪帅  阅读(2981)  评论(1编辑  收藏  举报