私有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             = { "个推" => "[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(@"\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
时间: 2024-08-10 02:09:58

私有Pods封装个推SDK功能(解决方案)的相关文章

使用【百度云推送】第三方SDK实现推送功能详解

之前介绍过如何使用shareSDK实现新浪微博分享功能,今天介绍如何使用百度云推送SDK实现Android手机后台推送功能. 运行效果如下 第一步,如果使用百度的SDK,当然要先成为百度的开发者啦,这个就不详述了.成为开发者之后,我们要建立一个应用,如下图所示 第二步,创建好应用之后,我们点击开方者服务管理,进入工程管理页面,然后点击左侧云推送,进入云推送功能页面,具体如下图 进入云推送详细页面之后,我们点击推送设置,设置好我们的应用的包名,然后点击快速实例,将系统给我们产生的示例代码下载下来

使用【百度云推送】第三方SDK实现推送功能具体解释

之前介绍过怎样使用shareSDK实现新浪微博分享功能,今天介绍怎样使用百度云推送SDK实现Android手机后台推送功能. 执行效果例如以下 第一步,假设使用百度的SDK,当然要先成为百度的开发人员啦,这个就不详述了.成为开发人员之后,我们要建立一个应用,例如以下图所看到的 第二步,创建好应用之后,我们点击开方者服务管理,进入project管理页面,然后点击左側云推送,进入云推送功能页面,详细例如以下图 进入云推送具体页面之后,我们点击推送设置,设置好我们的应用的包名,然后点击高速实例,将系统

如何通过个推SDK实现IM功能

服务上线4年多以来,个推已经服务了逾19万app开发者,35万app,助推了无数著名合作伙伴应用精细化运营.但是,大多数开发者都不了解,用个推的推送SDK还可以实现IM功能.作为曾经做过IM通讯app的个推团队,满足大部分开发者对于IM的使用需求一定不是问题.目前通过个推SDK实现IM功能的合作伙伴也已经有了一定的规模. 一. 应用场景:已经接入个推SDK的应用中需要实现IM功能,分为客户端A与客户端B.客户端A与B之间相互发送消息,开启单独的聊天模式或者有多个客户端之间使用群聊模式,内容可以是

Android消息推送完美解决方案全析

推送功能在手机应用开发中越来越重要,已经成为手机开发的必须.在Android应用开发中,由于众所周知的原因,Android消息推送我们不得不大费周折.本文就是用来和大家共同探讨一种Android消息推送的完美解决方案. 一.消息推送基础 消息推送,就是在互联网上通过定期传送用户需要的信息来减少信息过载的一项新技术.推送技术通过自动传送信息给用户,来减少用于网络上搜索的时间.它根据用户的兴趣来搜索.过滤信息,并将其定期推给用户,帮助用户高效率地发掘有价值的信息 当我们开发需要和服务器交互的移动应用

Android实现推送方式解决方案【转载地址:http://www.cnblogs.com/hanyonglu/archive/2012/03/04/2378971.html】

本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息.这种推送功能是好的一面,但是也会经常看到很多推送过来的垃圾信息,这就让我们感到厌烦了,关于这个我们就不能多说什么了,毕竟很多商家要做广告.本文就是来探讨下Android中实现推送功能的一些解决方案,也希望能够起到抛砖引玉的作用.^_^ 1.推送方式基础知识:  在移动互联网时代以前的手机,如果有事情

Android实现推送方式解决方案

Android实现推送方式解决方案 本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息.这种推送功能是好的一面,但是也会经常看到很多推送过来的垃圾信息,这就让我们感到厌烦了,关于这个我们就不能多说什么了,毕竟很多商家要做广告.本文就是来探讨下Android中实现推送功能的一些解决方案,也希望能够起到抛砖引玉的作用.^_^ 1.推送方式基础知识: 在移

【转】Android实现推送方式解决方案

本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息.这种推送功能是好的一面,但是也会经常看到很多推送过来的垃圾信息,这就让我们感到厌烦了,关于这个我们就不能多说什么了,毕竟很多商家要做广告.本文就是来探讨下Android中实现推送功能的一些解决方案,也希望能够起到抛砖引玉的作用.^_^ 1.推送方式基础知识:  在移动互联网时代以前的手机,如果有事情

Android集成友盟推送功能

友盟是中国最大的移动开发者服务平台,为移动开发者提供免费的应用统计分析.社交分享.消息推送.自动更新.在线参数.移动推广效果分析.微社区等app开发和运营解决方案. 如何快速集成友盟推送功能: 1. 注册友盟账号 友盟开发者账号的注册地址:http://www.umeng.com/users/sign_up 2. 创建推送应用 首先进入友盟消息推送的应用中心,创建一个应用,链接地址为:http://message.umeng.com/appList. 应用创建完成后,点击应用名称进入应用详情页面

Android实现推送方式解决方案(转)

本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息.这种推送功能是好的一面,但是也会经常看到很多推送过来的垃圾信息,这就让我们感到厌烦了,关于这个我们就不能多说什么了,毕竟很多商家要做广告.本文就是来探讨下Android中实现推送功能的一些解决方案,也希望能够起到抛砖引玉的作用.^_^ 1.推送方式基础知识:  在移动互联网时代以前的手机,如果有事情