iOS原生Xcode工程接入 TapTapSDK
作者:互联网
本次目标是 接入TapTapSDK 几个模块
1 账号登陆 - TDS 内建账户服务
2 事件上报
3 防沉迷 - 快速认证
环境介绍
Xcode 13.2 + 上一篇笔记中的creator3.5.1 导出游戏工程
TapSDK_iOS_v3.11.0
1 集成必要的静态库
根据TapSDK说明 需要如下静态库
还有其他文档中需要的系统库
最终Target General中预览如下 (其他无关库已打码)
2 根据要求修改info
主要是这些
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>taptap</string> <key>CFBundleURLSchemes</key> <array> <string>tt你的ClientID</string> </array> </dict> </array> <key>LSApplicationQueriesSchemes</key> <array> <string>tapiosdk</string> <string>tapsdk</string> </array> <key>NSCameraUsageDescription</key> <string>App 需要你的同意,才能访问相机 </string> <key>NSMicrophoneUsageDescription</key> <string>App 需要你的同意,才能访问麦克风 </string> <key>NSPhotoLibraryUsageDescription</key> <string>App 需要你的同意,才能访问相册 </string>
3 其余配置
- 在 Build Setting 中的 Other Link Flag 中添加 -ObjC
-
AntiAddictionService
防沉迷基础库,源码由 Swift 编写。 在 Build Setting 中的 Always Embed Swift Standard Libraried 设置为 YES,即始终引入 Swift 标准库,避免 App 启动时报错「无法找到 Swift 标准库之类」。如果项目中找不到,可以建立一个空 Swift 文件,Xcode 会自动建立桥接关系。 - 在 Build Setting 中的 Swift Compiler - Language/Swift Language Version 选择 Swift 5。
4 代码实现
我们为了方便2次开发和版本迭代。
将TapSDK相关功能接口集中在一个单例的类 TapSDKWrapper
TapSDKWrapper.h
// // TapSDKWrapper.h // creator351-mobile // // Created by yqAdmin on 2022/7/21. // #import <TapBootstrapSDK/TapBootstrapSDK.h> @interface TapSDKWrapper : NSObject{ } @property (nonatomic, strong) NSString *userId; @property (nonatomic, strong) NSString *username; @property (nonatomic, strong) NSString *avatar; @property bool *isLogin; + (instancetype)instance; - (void)initTapSDK; - (void)taptapLogin; - (bool)checkLoginStatus; - (void)taptapLogout; - (NSString *)getUserInfo; - (void)traceEvent:(NSString *)eventStr; @endView Code
TapSDKWrapper.m
// // TapSDKWrapper.m // creator351-mobile // // Created by yqAdmin on 2022/7/21. // #import <Foundation/Foundation.h> #import "TapSDKWrapper.h" #import <TapDB/TapDB.h> #import "JsbBridgeTest.h" //OC-JS层通讯接口 #import <AntiAddictionUI/AntiAddiction.h> #import <AntiAddictionService/AntiAddictionService.h> @implementation TapSDKWrapper #pragma mark - #pragma mark Singleton static TapSDKWrapper *mInstace = nil; + (instancetype)instance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ mInstace = [[super allocWithZone:NULL] init]; }); return mInstace; } # pragma mark - 初始化 - (void)initTapSDK { //初始化SDK NSString *client_ID = @"你的ClientID"; TapConfig *config = [TapConfig new]; config.clientId = client_ID; config.clientToken=@"你的Token"; config.region = TapSDKRegionTypeCN; config.serverURL = @"你的ServerURL"; [TapBootstrap initWithConfig:config]; TapDBConfig * dbConfig = [[TapDBConfig alloc]init]; dbConfig.enable = FALSE; dbConfig.channel=@"tapyap"; dbConfig.gameVersion=@"1.0"; dbConfig.advertiserIDCollectionEnabled=true; config.dbConfig = dbConfig; config.region = TapSDKRegionTypeCN; [TapBootstrap initWithConfig:config]; NSLog(@"taptap sdk init succ "); //初始化TapDB [TapDB onStartWithClientId:client_ID channel:@"taptap" version:nil isCN:YES]; //Tap防沉迷 AntiAddictionConfiguration *anti_config = AntiAddictionService.configuration; // 是否启用消费限制功能 anti_config.useSdkPaymentLimit = NO; // 是否启用时长限制功能 anti_config.useSdkOnlineTimeLimit = NO; // 是否显示切换账号按钮 anti_config.showSwitchAccount = NO; [AntiAddiction initGameIdentifier:client_ID antiAddictionConfig:anti_config antiAddictionCallbackDelegate:self completionHandler:^(BOOL success) { if (success) { // 初始化成功 NSLog(@"Tap 防沉迷初始化成功 ====== "); } }]; //开启动态 // [TapMoment setDelegate:self]; } //防沉迷 初始化 错误回调 - (void)antiAddictionCallbackWithCode:(AntiAddictionResultHandlerCode)code extra:(NSString *)extra { if(code == AntiAddictionResultHandlerLoginSuccess) { NSLog(@"Tap 防沉迷通过 ====== 登陆游戏"); [[JsbBridgeTest instance] OnTapLogin:([self getUserInfo])]; } else { NSLog(@"Tap 防沉迷返回 antiAddictionCallbackWithCode === code %ld ,extra %@",code, extra); } } #pragma mark - 登录相关 /** 登录 */ - (void)taptapLogin{ [TDSUser loginByTapTapWithPermissions:@[@"public_profile"] callback:^(TDSUser * _Nullable user, NSError * _Nullable error) { if (user) { // 开发者可以调用 user 的方法获取更多属性。 _userId = user.objectId; // 用户唯一标识 _username = user[@"nickname"]; // 昵称 _avatar = user[@"avatar"]; // 头像 NSLog(@"userId: %@, username: %@, avatar: %@", _userId, _username, _avatar); _isLogin = TRUE; //TapDB 设置用户 [TapDB setUser:_userId]; [TapDB setName:_username]; // [TapDB setLevel:5]; [TapDB setServer:@"taptap"]; //防沉迷 快速认证 BOOL useTapLogin = YES; NSString *userIdentifier = _userId; [AntiAddiction startUpUseTapLogin:useTapLogin userIdentifier:userIdentifier]; } else { NSLog(@"%@", error); _isLogin = FALSE; [[JsbBridgeTest instance] OnTapLogin:(NULL)]; } }]; } //拉取user信息 - (NSString *)getUserInfo{ NSString *jsonStr = [NSString stringWithFormat:@"{\"openid\":\"%@\",\"name\":\"%@\",\"avatar\":\"%@\"}", _userId,_username, _avatar]; NSLog(@"json is %@", jsonStr); return jsonStr; } /** 判定登陆状态 */ - (bool)checkLoginStatus { TDSUser *currentUser = [TDSUser currentUser]; if (currentUser == nil) { // 未登录 NSLog(@"登陆状态:未登陆"); return FALSE; } else { // 已登录 if (currentUser) { // 开发者可以调用 user 的方法获取更多属性。 _userId = currentUser.objectId; // 用户唯一标识 _username = currentUser[@"nickname"]; // 昵称 _avatar = currentUser[@"avatar"]; // 头像 NSLog(@"userId: %@, username: %@, avatar: %@", _userId, _username, _avatar); _isLogin = TRUE; } NSLog(@"登陆状态:已登陆"); return TRUE; } } /** 登出 */ - (void)taptapLogout{ [TDSUser logOut]; } #pragma mark TapDB事件上报 //Json解析 - (NSDictionary *)jsonParse:(NSString *)eventStr{ NSError *error = nil; id jsonObj = [NSJSONSerialization JSONObjectWithData:[eventStr dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:&error]; if (error) { NSLog(@"JSON: %@\n parse error : %@",eventStr,error); // return jsonObj; } return [jsonObj isKindOfClass:NSDictionary.class]? jsonObj :nil; } - (void)traceEvent:(NSString *)eventStr{ NSDictionary *eventDic = [self jsonParse:eventStr]; NSDictionary* dic = @{eventDic[@"eventKey"]:eventDic[@"eventValue"]}; [TapDB trackEvent:eventDic[@"eventName"] properties:dic]; } @endView Code
在AppDelegate中 加入Taptap WebUI的支持
#pragma mark taptap打开web登陆 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return [TapBootstrap handleOpenURL:url]; } - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { return [TapBootstrap handleOpenURL:url]; }
5 对SDK接口的调用
AppDelegate启动后 加入TapSDK初始化
#pragma mark - #pragma mark Application lifecycle - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[SDKWrapper shared] application:application didFinishLaunchingWithOptions:launchOptions]; appDelegateBridge = [[AppDelegateBridge alloc] init]; // Add the view controller's view to the window and display. CGRect bounds = [[UIScreen mainScreen] bounds]; self.window = [[UIWindow alloc] initWithFrame:bounds]; // Should create view controller first, cc::Application will use it. _viewController = [[ViewController alloc] init]; _viewController.view = [[View alloc] initWithFrame:bounds]; _viewController.view.contentScaleFactor = UIScreen.mainScreen.scale; _viewController.view.multipleTouchEnabled = true; [self.window setRootViewController:_viewController]; [self.window makeKeyAndVisible]; //试图调用 viewDidLoad [_viewController viewInit]; // TapSDK 初始化 [[TapSDKWrapper instance] initTapSDK]; //GroMore SDK初始化 [[ABUAdWrapper instance] initSDK]; //jsb绑定 初始化 会调用init [JsbBridgeTest instance]; [appDelegateBridge application:application didFinishLaunchingWithOptions:launchOptions]; return YES; }View Code
另外实现 JS - OC 的通信类 JsbBridgerTest 根据业务情况调用Tap登陆 (见另一篇笔记 creator3.5打包 JS-OC 互通实现)
//js - oc - js taptap 登陆 [m addScriptEventListener:@"TapLogin" listener:^void(NSString* arg){ NSLog(@"JsbBridge TapLogin ==========="); [[TapSDKWrapper instance] taptapLogin]; }];
登陆过程中 按照防沉迷接入要求。首次登陆调用防沉迷验证接口。验证通过后再执行登陆流程
//防沉迷 快速认证 BOOL useTapLogin = YES; NSString *userIdentifier = _userId; [AntiAddiction startUpUseTapLogin:useTapLogin userIdentifier:userIdentifier];
//防沉迷 初始化 错误回调 - (void)antiAddictionCallbackWithCode:(AntiAddictionResultHandlerCode)code extra:(NSString *)extra { if(code == AntiAddictionResultHandlerLoginSuccess) { NSLog(@"Tap 防沉迷通过 ====== 登陆游戏"); [[JsbBridgeTest instance] OnTapLogin:([self getUserInfo])]; } else { NSLog(@"Tap 防沉迷返回 antiAddictionCallbackWithCode === code %ld ,extra %@",code, extra); } }
根据游戏业务 在一定时机由js调用 Tap事件上报接口 trace
对应Tap后台 数据分析中的 自定义事件
- (void)traceEvent:(NSString *)eventStr{ NSDictionary *eventDic = [self jsonParse:eventStr]; NSDictionary* dic = @{eventDic[@"eventKey"]:eventDic[@"eventValue"]}; [TapDB trackEvent:eventDic[@"eventName"] properties:dic]; }
6 踩坑
1)打包出目标iOS 14.0的版本后。 真机iOS14.2 启动崩溃。发现报错
dyld: Library not loaded: /System/Library/Frameworks/AdServices.framework Referenced from:。。。。。 Reason: image not found 解决方案 :这里只需要在TARGETS—>Build Phases —> Link Binary With Libraries里边,UserNoifications.framework 后面的status改成Optional标签:TapSDKWrapper,TapTapSDK,防沉迷,Xcode,iOS,NSString,NSLog,config,void 来源: https://www.cnblogs.com/xiloweiEVE/p/16535343.html