Skip to content

接入新SDK

IMPORTANT

当我们需要在U8SDK中接入一个新渠道SDK时,我们心里应该牢记一点:接入过程和游戏工程没有半点关系。也就是说,游戏开发和SDK接入是完全解耦的。

所以,接入的时候,不要想着游戏中怎样怎样,严格按照下面的步骤进行接入,然后使用Demo母包进行测试即可。

所有的接入工程都放在一个统一的目录,默认是放在打包工具client/Plugins目录下。所有接入工程的命名格式必须固定,统一为U8SDK_***

创建新的SDK插件

更新: 为了方便接入新的SDK, 我们提供了渠道SDK创建辅助脚本, 以前手动创建接入工程的方式不再推荐

Plugins目录下的create_plugin.py就是我们提供的接入工程创建工具, 它以SDK接入工程U8SDK_Template做为模板生成新的接入工程

创建一个工程:U8SDK_AAA

cd Plugins
python create_plugin.py U8SDK_AAA

实现代码

NOTE:所有渠道SDK需要接入的方法,都大同小异。我们将其归为三大类: 1、初始化: 大部分渠道都有初始化方法 2、用户相关:包含[登录]、[切换帐号]、[登出]、[个人中心]、[提交玩家数据]、[退出确认框] 3、支付:仅仅包含一个充值的接口

1、引入SDK库和资源

一般渠道SDK,都会提供一些库文件和资源文件,接入的时候,需要将这些文件拷贝到该工程下面SDK目录下,同时,添加SDK目录中的framework和头文件到接入工程, 通常可以直接把整个SDK目录加到接入工程中, 但是要注意:
SDK目录下的静态库不能加入接入工程, 否则会导致最终编译渠道工程时连接失败

2、实现需要的方法

经过上面的脚本创建之后,会在Plugins目录下生成U8SDK_AAA插件工程目录, 我们用xcode打开该工程。可以看到,辅助脚本已经为我们生成好了U8SDK_AAA.hU8SDK_AAA.m文件

U8SDK_AAA.h文件如下:

objective-c
#import <Foundation/Foundation.h>
#import "U8Plugin.h"

#import "HXAppPlatformKitPro.h"

@interface U8SDK_AAA : U8Plugin<U8User, U8Pay>

@end

//1、继承U8Plugin接口,
//2、同时,实现U8User协议和U8Pay协议。
//3、在U8SDK_AAA.m文件中实现U8PluginProtocol中的接口,进行渠道SDK的初始化,和AppDelegate中的一些系统方法接口。
//4、在U8SDK_AAA.m文件中实现U8User和U8Pay中的接口。

//这三个需要实现的Protocol如下:

// U8Plugin 插件接口
@protocol U8PluginProtocol

-(instancetype) initWithParams:(NSDictionary*)params;

@optional

-(void) setupWithParams:(NSDictionary*)params;

// UIApplicationDelegate事件
- (void)didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
- (void)applicationWillResignActive:(UIApplication *)application;
- (void)applicationDidEnterBackground:(UIApplication *)application;
- (void)applicationWillEnterForeground:(UIApplication *)application;
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (void)applicationWillTerminate:(UIApplication *)application;

- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
- (void)didReceiveLocalNotification:(UILocalNotification*)notification;
- (void)didReceiveRemoteNotification:(NSDictionary*)userInfo;

- (void)openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation;

@end

//U8User 账号登录相关接口
@protocol U8User

- (void) login;				//SDK登录
- (void) logout;
- (void) switchAccount;

- (BOOL) hasAccountCenter;
@optional
- (void) showAccountCenter;

//- (BOOL) isLogined;
//- (NSString*) getSessionID;

@end

//U8Pay 应用内购接口
@protocol U8Pay

-(void) pay:(NSDictionary*) profuctInfo;

@optional
-(void) openIAP;

@optional
-(void) closeIAP;

@optional
-(void) finishTransactionId:(NSString*)transactionId;

@end

然后,我们在U8SDK_AAA.m中根据需要实现上面三个协议中的对应的接口,我们这里的内容还是iTools的实现,我们看一下:

objective-c

#import "U8SDK_AAA.h"
#import <AlipaySDK/AlipaySDK.h>

typedef enum
{
    StateDefault,
    StateIniting,
    StateInited,
    StateLogin,
    StateLogined
} SDKState;

@implementation U8SDK_AAA
{
    SDKState sdkState;
}

//////////////////////////////////////////////////////////////////////
#pragma mark - 处理 SDK 通知
//注册通知处理
- (void)registerNotification:(NSNotification *)notification
{
    NSLog(@"userId: %@", [notification.object objectForKey:@"userId"]);
    NSLog(@"userName: %@", [notification.object objectForKey:@"userName"]);
    NSLog(@"sessionId: %@", [notification.object objectForKey:@"sessionId"]);
}

//登录通知处理
- (void)loginNotification:(NSNotification *)notification
{
    NSLog(@"userId: %@", [notification.object objectForKey:@"userId"]);
    NSLog(@"userName: %@", [notification.object objectForKey:@"userName"]);
    NSLog(@"sessionId: %@", [notification.object objectForKey:@"sessionId"]);
    
    sdkState = StateLogined;
    
    NSDictionary* extension = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [notification.object objectForKey:@"userName"], @"username",
                                  [notification.object objectForKey:@"userId"], @"uid",
                                  [notification.object objectForKey:@"sessionId"], @"sessionid",
                                  nil];
    
    [self eventUserLoginExt:extension];
}

//关闭窗口通知处理
- (void)closeViewNotification:(NSNotification *)notification
{
    NSLog(@"SDK View Closed");
}

//注销通知处理
- (void)logoutNotification:(NSNotification *)notification
{
    NSLog(@"Logout");
    [self eventUserLogout:nil];
}

- (void)closePayViewNotification:(NSNotification *)notification
{
    NSLog(@"SDK PayView Closed");
    NSLog(@"userId: %@", [notification.object objectForKey:@"userId"]);
    NSLog(@"userName: %@", [notification.object objectForKey:@"userName"]);
    NSLog(@"sessionId: %@", [notification.object objectForKey:@"sessionId"]);
    NSLog(@"orderIdCom: %@", [notification.object objectForKey:@"orderIdCom"]);
}

//监听服务器有可更新App的通知处理
- (void)updateApp:(NSNotification *)notification
{
    NSLog(@"server has app update");
    NSLog(@"userId: %@", [notification.object objectForKey:@"userId"]);
    NSLog(@"userName: %@", [notification.object objectForKey:@"userName"]);
    NSLog(@"sessionId: %@", [notification.object objectForKey:@"sessionId"]);
}

//监听钱包支付不成功的通知处理
- (void)payFailed:(NSNotification *)notification
{
    NSLog(@"wallet pay failed");
    NSLog(@"orderIdCom: %@", [notification.object objectForKey:@"orderIdCom"]);
    NSLog(@"userId: %@", [notification.object objectForKey:@"userId"]);
    NSLog(@"userName: %@", [notification.object objectForKey:@"userName"]);
    NSLog(@"sessionId: %@", [notification.object objectForKey:@"sessionId"]);
}

//////////////////////////////////////////////////////////////////////

//这里进行SDK的初始化
-(instancetype)initWithParams:(NSDictionary *)params
{
    [U8SDK sharedInstance].defaultUser = self;			//这个是必须的
    [U8SDK sharedInstance].defaultPay  = self;			//这个是必须的
    
    sdkState = StateDefault;
    
    NSString* appid = [params objectForKey:@"appid"];	//这里的key和渠道SDK的配置文件中定义的key需要一致
    NSString* appkey = [params objectForKey:@"appkey"];
    
    //设置充值平台分配的appid和appkey
    [HXAppPlatformKitPro setAppId:[appid intValue] appKey:appkey];
    
    return self;
}

-(void) didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //设置支付宝回调所需的URL Scheme
    [HXAppPlatformKitPro setAlipayURLScheme:[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey]];
    //设置支持的旋转方向
    [HXAppPlatformKitPro setSupportOrientationPortrait:NO portraitUpsideDown:NO landscapeLeft:YES landscapeRight:YES];
    
    //监听注册通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(registerNotification:) name:HX_NOTIFICATION_REGISTER object:nil];

    //监听登录通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loginNotification:) name:HX_NOTIFICATION_LOGIN object:nil];
    
    //视图关闭通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeViewNotification:) name:HX_NOTIFICATION_CLOSEVIEW object:nil];
    
    //注销通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutNotification:) name:HX_NOTIFICATION_LOGOUT object:nil];
    
    //处理支付视图时关闭的附加通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closePayViewNotification:) name:HX_NOTIFICATION_CLOSE_PAYVIEW object:nil];
    
    //监听服务器有可更新App的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateApp:) name:HX_NOTIFICATION_UPDATE_APP object:nil];
    
    //监听钱包支付不成功的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(payFailed:) name:HX_NOTIFICATION_WALLET_PAY_FAILED object:nil];
}

-(void) openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    //跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给SDK
    if ([url.host isEqualToString:@"safepay"]) {
        [[AlipaySDK defaultService]
         processOrderWithPaymentResult:url
         standbyCallback:^(NSDictionary *resultDic) {
             NSLog(@"result = %@", resultDic);
             [HXAppPlatformKitPro alipayCallBack:resultDic];
         }];
    }
}

//实现SDK的登录
-(void) login
{
    [HXAppPlatformKitPro logout];
    [HXAppPlatformKitPro showLoginView];
}

//实现SDK的登出
-(void) logout
{
    [HXAppPlatformKitPro logout];
}

//实现SDK的切换账号
-(void) switchAccount
{
    [HXAppPlatformKitPro logout];
    [HXAppPlatformKitPro showLoginView];
}

//SDK是否要求游戏中提供[个人中心]按钮,点击可以进入SDK的个人中心界面
-(BOOL) hasAccountCenter
{
    return YES;
}

//显示SDK的个人中心界面
-(void) showAccountCenter
{
    [HXAppPlatformKitPro showPlatformView];
}

//实现渠道SDK的支付方法,打开渠道SDK的支付界面
-(void) pay:(NSDictionary*)productInfo
{
    int price = [[productInfo valueForKey:@"price"] intValue];
    NSString* productName = [productInfo valueForKey:@"productName"];
    NSString* orderId = [productInfo valueForKey:@"orderID"];

    //NSString* extension = [productInfo valueForKey:@"extension"];
    //NSString* serverName = [productInfo valueForKey:@"serverName"];
    //int buyNum = [[productInfo valueForKey:@"buyNum"] intValue];
    
    [HXAppPlatformKitPro payProductWithProductName:productName Amount:price OrderIdCom:orderId];
}

@end

触发U8SDK事件

NOTE:接入工程中,在初始化成功;登录成功;登出成功;支付成功;等时刻,都需要往抽象层抛出对应的事件,以便抽象层中能够分发这些事件,这样游戏接入工程监听这些事件,就能做对应的逻辑处理。

对应的事件触发方法在U8Plugin中,因为上面U8SDK_AAA直接继承了U8Plugin,所以在U8SDK_AAA.m中,可以直接调用。我们看看这些事件:

objective-c
#import "U8SDK.h"

@interface U8Plugin : NSObject<U8PluginProtocol>

-(UIView*) view;										//获取当前的UIView
-(UIViewController*) viewController;					//获取当前的UIViewController


-(void) eventPlatformInit:(NSDictionary*) params;		//初始化成功的时候,调用
-(void) eventUserLogin:(NSDictionary*) params;			//直接使用eventUserLoginExt即可
-(void) eventUserLoginExt:(id) extension;				//登录成功的时候,调用
-(void) eventUserLogout:(NSDictionary*) params;			//登出成功的时候,调用
-(void) eventPayPaid:(NSDictionary*) params;			//支付成功的时候,调用

比如上面在SDK通知的登录成功的回调方法loginNotification中,我们触发了eventUserLoginExt事件,同时将登录验证需要的参数,放在了一个Dictionary中,这些参数在去U8Server做二次登录认证的时候,会转换成json放到extension字段中。

所以,这里的名称是什么,U8Server那边也按照对应的key,按照json格式进行解析即可。

@end

配置编译参数

NOTE: 我们在每个渠道SDK的根目录下,都有一个xcode_process.py文件,用来配置当前渠道SDK的编译参数信息,同时也定义了一个自定义脚本的处理接口,用来实现特殊操作。

py
文件内容如下:

# -*- coding: utf-8 -*-

mods = {
    "group": "U8SDK_AAA",
    "files": [
        "libU8SDK_AAA.a",
    ],
    "folders": [
        "SDK"
    ],
    "frameworks": [
        "MobileCoreServices.framework",
        "AdSupport.framework",
        "UIKit.framework"
    ],
    "libs": [
        "libsqlite3.dylib"
    ]
}

def post_process(self, project, infoPlist, sdkparams):

    self.addBundleURLType(CFBundleTypeRole="Editor", CFBundleURLSchemes=[self.getBundleId()])
    
    infoPlist['UIViewControllerBasedStatusBarAppearance'] = False

1、mods:配置添加到xcode工程中的库和文件等。
	group:添加到工程中的group
	files:添加到工程中的文件
	folders:添加到工程中的文件夹,SDK下面是当前渠道SDK提供的各种库文件和资源文件
	frameworks:添加到工程中的系统的frameworks,注意:这里添加的都是当前渠道SDK需要依赖的系统的framework
	libs:添加到工程中的系统的lib文件,注意:这里添加的都是当前渠道SDk需要依赖的系统的lib

2、post_process:当前渠道SDK的自定义脚本
	self:当前类空间,可以用self调用XcodeProcess类中所有方法。这个类在buildscript/xcode_gen.py文件中
	project:当前工程对象
	infoPlist:info.plist对象,是一个字典结构
	sdkparams:当前渠道SDK的配置参数,是一个字典结构

插件代码编写完毕之后, 我们可以在Plugins目录下,执行./build_plugin.sh U8SDK_AAA 完成该插件的编译, 编译成功之后,会在模块根目录下生成一个名为libU8SDK_AAA.a的静态库文件。

版权所有© 2021-2030 上海丞诺网络科技有限公司