千千游戏SDK是一个专门提供给合作方接入的自有游戏SDK,主要包含用户账号系统与游戏支付业务。 具体代码业务参考我方提供的SDK示例代码。
一、SDK导入与配置
1. 导入SDK
上图为SDK提供的示例代码文件夹基础结构,将SDK文件夹整个拖入到Xcode工程中即可,添加选项如下图所示:
如果为Unity项目需按照以下导入配置:
导入后需要添加SDK内的bundle文件到主工程内:
2. 配置项目最小支持版本
SDK最小支持版本为iOS 12.0,但由于业务需求以及部分依赖限制推荐统一将最小支持版本设置为iOS13
3. 配置info.plist
- 配置隐私权限API描述
NSPhotoLibraryAddUsageDescription:游戏需要相处权限,用于保存账号信息
NSUserTrackingUsageDescription:游戏需要获取IDFA权限,用于定位游戏异常信息
- 配置
LSApplicationQueriesSchemes,具体以接入SDK版本为准,可参考提供的Demo
4. 配置 Build Settings
-
添加链路器命令行参数:
-ObjC -
配置动态框架(如抖音促活SDK:
UnionOpenPlatformDataLink.framework),具体设置参考SDK补充说明,若未正确配置则在真机运行时将会崩溃并提示无法加载对应的动态框架。如下图:
二、SDK API说明
SDK文件说明参考上图,其中接口类:
MQWPlatform为SDK核心接口类,SDK接口结过采取广播方式接收,具体各通知名称如下:
MQWInitResultNotification: SDK初始化/激活结果通知MQWLoginFinishedNotification:SDK登录成功通知MQWLogoutFinishedNotification:SDK登出完成通知MQWRegisterFinishedNotification:SDK注册完成通知MQWThirdShareNotification:SDK分享通知(该通知仅适用接入微信等三方SDK的版本)IAPFinishedNotification:支付成功通知(已废弃,请自行验证服务端)IAPFailedNotification: 支付失败通知
PS:对于马甲包接入时由于需要进行代码混淆处理,上述文件名与类名可能存在变化具体以实际提供SDK文件为准。
1. 监听SDK相关接口结果
/// 添加SDK各接口相关结果通知,其中1-4为必须接入
- (void)addNotis {
/// 1. 监听SDK初始化接口通知
[self noti:MQWInitResultNotification sel:@selector(initFinished:)];
/// 2. 监听登录成功通知
[self noti:MQWLoginFinishedNotification sel:@selector(login:)];
/// 3. 监听注册成功通知
[self noti:MQWRegisterFinishedNotification sel:@selector(regist:)];
/// 4. 监听登出通知
[self noti:MQWLogoutFinishedNotification sel:@selector(logout:)];
/// 5. 监听第三方分享通知(该方法仅针对接入微信、Tap、等第三方SDK版本有效)
[self noti:MQWThirdShareNotification sel:@selector(shareResult:)];
}
2. 初始化SDK(激活接口)
//激活API
/// @param appId:sdk提供的产品id
/// @param code: 支付货币ISO编码(已废弃,传nil即可)
+ (void)activePlatformWithAppId:(NSString *)appId currencyISO:(nullable NSString *)code;
调用示例:
#import "ViewController.h"
#import <MiquwanSDK/MiquwanSDK.h>
/// 推荐在系统启动方法中调用该方法,如下:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 1. 调用初始化接口前需要先添加接口结果通知
[self addNotis];
// 2. 调用激活接口
[MQWPlatform activePlatformWithAppId:@"sdk-appid" currencyISO:nil];
return YES;
}
//接受SDK激活结果
- (void)initFinished:(NSNotification *)noti {
NSError *error = noti.object;
if (error) {
NSLog(@"激活失败:%@", error);
}else {
NSLog(@"SDK平台已经激活,可调用其他接口了");
/// 初始化成功后调用自动登录,由于各游戏业务与逻辑不同,登录接口可自行延后调用
[MQWPlatform loginPlatformNeedAutoLogin:true];
}
}
3. 登录/注册
SDK没有实际意义的登录或注册接口,当下方接口needAutoLogin=false时将展示登录/注册UI
/// 登录接口
/// @param needAutoLogin 是否需要自动登录
+ (void)loginPlatformNeedAutoLogin:(BOOL)needAutoLogin;
调用示例:
// 1. 调用登录接口,若首次登录不想自动登录needAutoLogin选择NO即可
if (firstLogin) {
[MQWPlatform loginPlatformNeedAutoLogin:YES];
}else {
[MQWPlatform loginPlatformNeedAutoLogin:NO];
}
// 注册成功结果处理
- (void)regist:(NSNotification *)noti {
NSLog(@"这是一个新账号,如果无需记录,可直接将注册通知接受方法指向login:方法")
[self login:noti];
}
// 登录成功结果处理
- (void)login:(NSNotification *)noti {
NSDictionary *result = noti.object;
NSString *uid = result[@"userId"];
NSString *token = result[@"token"];
NSString *account = result[@"userAccount"];
//。。。。进入游戏
}
4. 登出
/// 退出平台
+ (void)logoutPlatform;
调用示例:
[MQWPlatform logoutPlatform];
// 登出成功结果处理
- (void)logout:(NSNotification *)noti {
//取消自动登录
[MQWPlatform loginPlatformNeedAutoLogin:NO];
}
5. 上传游戏角色
------------------- MQWRole.h ---------------------
/// 1. 创建角色接口
/// 创建角色模型
/// @param serverId 所在服务器ID
/// @param serverName 服务器名称
/// @param gameRoleName 角色名
/// @param gameRoleID 角色id
/// @param gameRoleLevel 角色等级
/// @param vipLevel vip等级
/// @param source 角色上报时机
+ (MQWRole *)createRoleWithServerId:(NSString *)serverId
serverName:(NSString *)serverName
gameRoleName:(NSString *)gameRoleName
gameRoleID:(NSString *)gameRoleID
gameRoleLevel:(NSNumber *)gameRoleLevel
vipLevel:(NSNumber *)vipLevel
source:(NSString *)source;
------------------- MQWPlatform.h ---------------------
/// 2.上传角色接口
+ (void)uploadRole:(MQWRole *)role
handler:(void (^)(BOOL, NSError * _Nullable))handler
其中 角色上报时机(source) 字段对应字符串说明如下:
createrole:创建新角色时调用levelup:玩家升级角色时调用enterServer:选择服务器进入时调用
调用示例:
// 1. 封装角色信息
MQWRole *role = [MQWRole createRoleWithServerId:@"IOS001"
serverName:@"命运方舟" gameRoleName:@"枪火"
gameRoleID:@"100000001" gameRoleLevel:@100
vipLevel:@16 source:@"enterServer"];
// 2. 上传角色信息
[MQWPlatform uploadRole:role handler:^(BOOL flag, NSError * error) {
if (error) {
NSLog(@"上传失败:\n%@", error.localizedDescription);
}else {
NSLog(@"上传成功");
}
}];
6. 支付
关于支付测试需要先向我方游戏对接人员提供自己的SDK测试账号,让其配置测试权限才能进行支付测试
------------------- MQWOrder.h ---------------------
/// 1. 创建游戏订单信息
/// @param goodsId 苹果内购产品ID字符串
/// @param goodName 内购产品名称
/// @param oredrId 游戏内订单id
/// @param count 充值对应游戏货币(金币,元宝。。)数量
/// @param money 充值金额(单位元)
/// @param callBackInfo 游戏自定义会传参数(长度限制250个字符)
+ (MQWOrder *)createOrderWithGoodsID:(NSString *)goodsId
goodsName:(NSString *)goodName
cpOrderID:(NSString *)oredrId
count:(NSNumber *)count
money:(NSNumber *)money
callBackInfo:(NSString *)callBackInfo;
------------------- MQWPlatform.h ---------------------
/// 2. 支付接口
/// @param order 订单信息
/// @param role 角色信息
+ (void)purchaseOrder:(nonnull MQWOrder *)order role:(nullable MQWRole *)role
调用示例:
// 1. 封装订单信息
MQWOrder *order = [MQWOrder createOrderWithGoodsID:@"com.productid.6"
goodsName:@"每日首充" cpOrderID:@"game-order-id0001"
count:@60 money:@6 callBackInfo:@"游戏回传信息"];
// 当海外版本SDK时需要额外设置货币ISO编码
order.currency = @"CNY";
// 2. 下单角色信息
MQWRole *role = [MQWRole createRoleWithServerId:@"IOS001"
serverName:@"命运方舟" gameRoleName:@"枪火"
gameRoleID:@"100000001" gameRoleLevel:@100
vipLevel:@16 source:@""];
// 3. 调用支付接口
[MQWPlatform purchaseOrder:order role:role];
7. 联系客服
/// 联系客服
+ (void)contactUS
调用示例:
[MQWPlatform contactUS];
8. 处理IAE/URL启动事件
关于IAE请先参考官方文档
项目配置请查看千千SDK游戏自有IAE深链配置
/// 1. 判定URL启动APP事件是否需要被拦截
/// @param url 启动App对应URL
/// @return YES:SDK已经处理本次操作,无需后续处理
+ (BOOL)handleLaunchURL:(NSURL *)url;
/// 2. 判定App Store活动启动事件(IAE)
/// @param userActivity app激活实例
/// @return YES:SDK已经处理本次操作,无需继续处理
+ (BOOL)handleLaunchUniversalLink:(NSUserActivity *)userActivity;
调用示例:
-
App代理文件中的 IAE系统入口方法
-(BOOL) application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * _Nullable)) restorationHandler { // 判定深链事件 if ([MQWPlatform handleLaunchUniversalLink:userActivity]) { // SDK拦截本次事件,例如微信分享事件 return true; }; // 非SDK内部深链需要自行处理 if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { NSURL *url = userActivity.webpageURL; [self handleURL:url]; } return YES; } -
App代理文件中的 URL启动方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { // 判定URL启动事件 if ([MQWPlatform handleLaunchURL:url]) { // SDK拦截本次事件,例如微信登录事件 return true; } // 非SDK内URL启动链接需自行处理 [self handleURL:url]; return true; } -
处理启动URL(非系统方法)
该处以千千SDK标准规则判定,如果使用自有深链或者第三方深链请结合实际情况判定IAE活动规则。
IAE深链规则:
https://[Xcode配置的深链域名]/sdk/[SDK-AppID]/.../[EventId]示例链接:
https://my.domain.com/sdk/1102/.../0000001- (void)handleURL:(NSURL *)url { NSURL *flagURL = [url URLByDeletingLastPathComponent]; NSString *eventId = url.lastPathComponent; if ([flagURL.absoluteString hasPrefix:@"https://my.domain.com/sdk/1102"] && eventId.length > 0) { //为千千SDK提供的IAE链接,登录后需要展示游戏对应活动界面 //保存活动ID(eventId)后用于用户登录后操作展示相应活动 [self recordLaunchEventId:eventId]; }else { //其他处理 } }
9. 分享
该接口仅对接入微信/TapTap等三方平台SDK版本有效
/// 分享链接
+ (void)share:(NSString *)title desc:(nullable NSString *)desc link:(NSString *)link;
/// 分享图片
+ (void)share:(nullable UIImage *)image;
调用示例:
// 1. 分享一个链接
[MQWPlatform share:@"SDK分享测试"
desc:@"这个搜索有点坑"
link:@"https://juejin.cn/post/7393194401575944231"];
// 2. 分享一张图片
[MQWPlatform share:[UIImage imageNamed:@"AppIcon"]]
// 3. 接收分享结果
- (void)shareResult:(NSNotification *)noti {
NSLog(@"由于各SDK分享逻辑不同,未必有结果反馈,因此一旦收到此通知就应发放奖品");
}
10. 推送
项目配置请参考:
1.上报设备令牌
/// 处理设备令牌注册
/// @param deviceToken 设备令牌数据
+ (void)handleDeviceToken:(NSData *)deviceToken;
调用示例:
App代理文件中的 推送通知注册回调
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[MQWPlatform handleDeviceToken:deviceToken];
}
2.处理静默推送
/// 处理静默推送
/// @param userInfo 推送内容
/// @param completionHandler 完成回调
+ (void)handleSilentNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
调用示例:
App代理文件中的 远程推送通知处理回调
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[MQWPlatform handleSilentNotification:userInfo fetchCompletionHandler:completionHandler];
}
11. iOS游戏中心(Game Center)
1.该功能为可选项,请根据实际需求选择接入.
2.由于项目不同,上报排行榜/成就用到的ID也不同,实际ID以我方对接人员提供为准。
Game Center功能为苹果提供的游戏社交平台,用户通过Apple ID登录后可使用好友联机、成就系统、全球排行榜等功能。
关于Game Center具体介绍请查看官方文档
项目配置请查看SDK补充说明-Xcode游戏中心配置
1.排行榜分数上报
/// Game Center排行榜分数上报
/// @param score 上报的分数
/// @param boardID 苹果后台创建的排行榜ID
/// @param handler 结果回调
+ (void)gameCenterReportScore:(int64_t)score
forLeaderboardID:(nullable NSString *)boardID
handler:(void(^)(NSError*__nullable error))handler;
调用示例:
/// Game Center排行榜分数上报
/// 排行榜类型:由开发者自定义,例如比较常见的积分排行、等级排行、充值排行等
/// 排行榜分数:这里使用自定义的等级排行榜,15代表玩家在等级排行榜上的等级为15级
/// 排行榜ID: 由开发者在苹果后台创建时输入
- (void)uploadGameCenterScore {
[MQWPlatform gameCenterReportScore:15 forLeaderboardID:@"1001" handler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"uploadScore-ERRO:\n%@",error.localizedDescription);
return;
}else {
NSLog(@"上报成功");
}
}];
}
2.成就上报
/// Game Center成就上报
/// @param progress 上报的成就进度
/// @param achievementID 苹果后台创建的成就ID
/// @param handler 结果回调
+ (void)gameCenterReportAchievement:(int64_t)progress
forAchievementID:(NSString *)achievementID
handler:(void(^)(NSError*__nullable error))handler;
调用示例:
/// Game Center成就上报
/// 成就类型:由开发者自定义,例如达成100级等级成就、打怪100只获得的成就等
/// 成就分数:分值范围0-100,代表达成该成就的进度百分比,传100代表玩家解锁该成就
/// 成就ID: 由开发者在苹果后台创建时输入
- (void)reportGameCenterAchivement {
[MQWPlatform gameCenterReportAchievement:80 forAchievementID:@"1002" handler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"reportAchError-ERRO:\n%@",error.localizedDescription);
return;
}else {
NSLog(@"上报成功");
}
}];
}
3.发送排行榜(分数)挑战
/// Game Center发送排行(分数)挑战
/// @param score 挑战的分数值
/// @param identifier 苹果后台创建的排行榜ID
/// @param handler 结果回调
+ (void)gameCenterSendScoreChallengeWithScore:(int64_t)score
forLeaderboardID:(NSString *)identifier
handler:(void(^)(NSError * _Nullable error))handler;
调用示例:
/// Game Center发送排行榜(分数)挑战
///排行榜分数:需要挑战的分数值
///排行榜ID:需要挑战的排行榜,由开发者在苹果后台创建时输入
- (void)sendGameCenterScoreChallenge {
[MQWPlatform gameCenterSendScoreChallengeWithScore:666 forLeaderboardID:@"1001" handler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"sendChallengeError-ERRO:\n%@",error.localizedDescription);
return;
}
NSLog(@"挑战发送成功");
}];
}
4.发送成就挑战
/// Game Center发送成就挑战
/// @param identifier 苹果后台创建的成就ID
/// @param handler 结果回调
+ (void)gameCenterSendAchievementChallengeForAchievementID:(NSString *)identifier
handler:(void(^)(NSError * _Nullable error))handler;
调用示例:
/// Game Center发送成就挑战
/// 成就ID:需要挑的成就,由开发者在苹果后台创建时输入
- (void)sendGameCenterAchivementChallenge {
[MQWPlatform gameCenterSendAchievementChallengeForAchievementID:@"1002" handler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"sendChallengeError-ERRO:\n%@",error.localizedDescription);
return;
}
NSLog(@"挑战发送成功");
}];
}