源码

首页 » 归档 » 源码 » 私有Pods封装个推SDK功能(解决方案)-ios学习从入门到精通尽在姬长信

私有Pods封装个推SDK功能(解决方案)-ios学习从入门到精通尽在姬长信

分享最热门的ios资讯

padlock-lock-chain-key-39624-medium.jpeg

一:运用场景


一:运用场景

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

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

屏幕快照 2016-07-07 下午16.24.43 下午.png

上面图为整体一个项目实例,相信也是很多项目目前采用Pod插件管理的方式;

二:集成效果

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 
 */
-(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 
 */
-(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 #import "jiaAppDelegate.h"
#import "jiaGTConfigManager.h"


@interface AppDelegate :jiaAppDelegate@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:检察效果图

屏幕快照 2016-07-07 下午16.39.51 下午.png

上面随便用个推推送一条消息,可以准确获得;到这边如果你只是运用,那么就可以结束了;就算你不懂个推也已经搞定集成功能;


三:实现过程

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

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

jiaAppDelegate.h的文件内容:

#import @interface jiaAppDelegate : UIResponder @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;其实这两个文件也是你平时集成个推时引入到工程的内容;如下的目录是被我封装后的个推目录结构;除了那两个文件其它就是抽离出来的内容;

屏幕快照 2016-07-07 下午16.57.46 下午.png

2.1 jiaAppDelegate+myGt类作用

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

jiaAppDelegate+myGt.h的文件内容:

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


@interface jiaAppDelegate (myGt)@end

jiaAppDelegate+myGt.m的文件内容:

#import "jiaAppDelegate+myGt.h"

@implementation jiaAppDelegate (myGt)

@end

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


2.2 jiaGTConfigManager类作用

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

jiaGTConfigManager.h文件的内容

#import @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  = < "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             = { "个推" => "[email protected]" }
  # Or just: s.author    = "个推实验室"
  # s.authors            = { "个推实验室" => "[email protected]" }
  # 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(@"
>>>[DeviceToken值]:%@

", myToken);
    
    return XAMessageForward(application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken);
}

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

", 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(@"
>>>[Receive RemoteNotification - Background Fetch]:%@

", 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(@"
>>>[个推Cid]:%@

", clientId);
}

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

", [error localizedDescription]);
}



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

", msg);
}

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

", aStatus);
}

/** SDK设置推送模式回调 */
- (void)GeTuiSdkDidSetPushMode:(BOOL)isModeOff error:(NSError *)error {
    if (error) {
        NSLog(@"
>>>[GexinSdk SetModeOff Error]:%@

", [error localizedDescription]);
        return;
    }
    
    NSLog(@"
>>>[GexinSdk SetModeOff]:%@

", 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(@"
>>>[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


如果还有什么不明白可以留言,顺便介绍一下自个一个开源的iOS快速搭建项目源代码,地址https://github.com/wujunyang/MobileProject

已经集成一些常用的功能,希望可以一起完善起来,当然如果对你有资助也可以点下星哈;


用意志战胜身体的惰性!

(0)

本文由 姬長信 创作,文章地址:https://blog.isoyu.com/archives/739.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:7 月 17, 2016 at 11:59 下午

关键词:

热评文章

发表回复

[必填]

我是人?

提交后请等待三秒以免造成未提交成功和重复