总结 #
Tenjin iOS SDK 允许客户在他们的 iOS 应用程序中跟踪事件和安装。 要了解有关 Tenjin 和我们的产品的更多信息,请访问 https://www.tenjin.com.
- 请参照我们的Release Notes来查看历史版本.
- 关于 Unity 的说明请查看 https://github.com/tenjin/tenjin-unity-sdk.
- 如果有任何技术问题,请邮件至 support@tenjin.com, 我们有遍布全球的支持团队为你服务。
注释: #
- 如果使用 iOS SDK v1.12.17 及更高版本,则需要 Xcode 13。
- 对于 App 跟踪透明度, 请确保更新您的项目文件
.plist并添加Privacy- Tracking Usage Description(NSUserTrackingUsageDescription)以及要向用户显示的文本信息,该库仅适用于 iOS 14.0 以上版本。 - 对于 Apple Search Ads Attribution (苹果搜索广告归因) 支持, 请务必升级至 v1.12.6+ 并添加
AdServices.framework库,该库仅适用于 iOS 14.3 以上版本。
SDK 集成 #
Cocoapods #
如果你使用 pods 添加pod 'TenjinSDK' 到你的Podfile,然后运行pod install并跳至第 4 步。
Swift Package Manager #
如果您使用 SPM,请通过 Xcode 将 Tenjin 的SDK包添加到此库中,并跳至第 4 步。
- 下载最新版本的 SDK。
- 拖动
TenjinSDK.xcframework和TenjinSDK.h到 Link Binary With Libaries。 - 在 Build 设置中包含 linker flags
-ObjC
Objective-C项目的步骤 #
- 转到 AppDelegate 文件, 默认为
AppDelegate.m, 和#import "TenjinSDK.h"。 - 您可以在App页面获取
SDK_KEY。 请注意:每个应用的SDK_KEY都是唯一的,您可以为每个应用生成最多3个SDK_KEY。

- 在
didFinishLaunchingWithOptionsmethod 添加:
[TenjinSDK initialize:@" "];
[TenjinSDK connect];- 若要启用 Tenjin iOS SDK 的调试日志,请添加:
[TenjinSDK debugLogs];这是一个AppDelegate.m file:文件在集成中的样例:
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK initialize:@"<SDK_KEY>"];
[TenjinSDK connect];
//All your other stuff
...
}Swift项目的步骤 #
- Add Objective-C Bridging Header file for swift projects, If your project does not already have a bridging header, create one:
- 创建一个header文件
- File -> New -> File -> “Sources”
- 选择 “Header” File - > 点击Next
- header file的名字为“YourProjectName-Bridging-Header” - 在“Targets”下 ->选择app target ->点击Next
- In the header file – “YourProjectName-Bridging-Header.h”
- 增加以下内容,
#import "TenjinSDK.h" - 前往app target,在“Build Settings”下
- 转至“Swift Compiler - General”
- 转至“Objective-C Bridging Header” 并将header file - “YourProjectName-Bridging-Header.h” 拖到里面.
- 增加以下内容,
- 创建一个header文件
- 您可以在App页面获取
SDK_KEY。 请注意:每个应用的SDK_KEY都是唯一的,您可以为每个应用生成最多3个SDK_KEY。

- 在您的code data-no-translation="" data-no-auto-translation="">didFinishLaunchingWithOptions中添加:
TenjinSDK.getInstance(" ")
TenjinSDK.connect()如果您使用的是Swift 5, 用getInstance() 方法而不是init(). 请参阅sample Swift app
- 若要启用 Tenjin iOS SDK 的调试日志,请添加:
TenjinSDK.debugLogs();下面是一个示例,说明在Swift项目中,您的 AppDelegate.swift如何集成:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
TenjinSDK.getInstance("<SDK_KEY>")
TenjinSDK.connect()
return true
}注意: 请确保每次应用启动中执行此代码didFinishLaunchingWithOptions,而不仅仅是在App首次打开时执行。
通过初始化处理来自其他服务的深度链接。若您使用其他服务生成延迟深度链接,您可以将这些深度链接传递给Tenjin,以便利用Tenjin深度链接功能处理归因逻辑。
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK init:@"<SDK_KEY>"];
//get your deep link from your other 3rd party service
NSURL *url = [NSURL withString: @"your_deep_link"];
//if you have a deep link that's generated from a third party service then pass it to tenjin to handle the Attribution of deep links holistically
if(url) {
[TenjinSDK connectWithDeferredDeeplink:url];
}
else{
[TenjinSDK connect];
}
//All your other stuff
//...
}You can verify if the integration is working through our Live Test Device Data Tool. Add your advertising_id 或 IDFA/GAID to the list of test devices. You can find this under Support -\> Test Devices. Go to the Live Event Tool page and send the test events from your app. You should see live events come in:
使用 ATTrackingManager 初始化 Tenjin #
从 iOS 14 开始,你可以选择初始话并显示 ATTrackingManager权限提示,让用户选择允许或不允许追踪。
如果用户选择不允许追踪,IDFA的值将会是0,如果用户选择同意追踪, connect() 方法就会发送 IDFA 到我们的服务器。
即便不使用ATTrackingManager,你也可以调用 Tenjin connect()。如果您不打算获取用户的IDFA或发给Tenjin,可以选择不启用ATT。
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK init:@"<SDK_KEY>"];
if (@available(iOS 14, *)) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
[TenjinSDK connect];
}];
} else {
[TenjinSDK connect];
}
}显示ATT权限请求弹窗 #
为遵守Apple的ATT指南,你需要为ATT权限请求弹窗提供说明,并在你的应用中实现该权限请求。
注意:在您的游戏中投放广告之前,您必须执行权限请求。
设定用户跟踪描述 #
Apple 需要开发者描述 ATT 提示的用途。您需要在 Xcode 项目的Info.plist文件中使用 NSUserTrackingUsageDescription设置描述。您必须提供一条消息,告知用户您为何请求使用设备跟踪数据的权限:
- 在您的 Xcode 项目导航器中,打开
Info.plist文件。 - 单击属性列表编辑器中任意键旁边的添加按钮 (+) 以创建新的属性键。
- 输入键名
NSUserTrackingUsageDescription. - 选择字符串 String 值类型。
- 在值字段中输入应用跟踪透明度消息。一些例子包括:
- “我们将使用您的数据来提供更好的个性化广告体验。”
- “我们会尝试根据您使用的应用程序、您使用的设备以及您所在的国家/地区展示您最感兴趣的应用程序和产品的广告。”
- “我们会尝试根据您使用的应用为您最感兴趣的应用和产品展示广告。”
注意:Apple 提供了特定的应用商店指南,为所有面向最终用户的隐私相关功能定义了可接受的使用和消息传递。Tenjin 不提供法律意见。因此,此页面上的信息不能替代您寻求自己的法律顾问来确定您的业务和流程的法律要求以及如何解决这些要求。
SKAdNetwork与Conversion value转化值 #
作为SKAdNetwork的一部分,我们为 updatePostbackConversionValue(_:) 创建的封装方案,可以注册等效的 SKAdNetwork 方案并同时发送 conversion values 到我们的服务器。
updatePostbackConversionValue(\_:) 6位值来对应应用内事件,不能二进制形式输入,而应为 0-63 的整数。我们的服务器将拒绝任何无效值。
对于支持 SKAdNetwork 4.0 的 iOS 16.1 之后的版本,现可通过发送coarseValue (String 字符串格式,可能的变体为 "low","medium" 或者 "high")以及lockWindow(Boolean 布尔值)作为更新版回传方法的参数
updatePostbackConversionValue(_ conversionValue: Integer, coarseValue: String)
updatePostbackConversionValue(_ conversionValue: Integer, coarseValue: String, lockWindow: Bool)
- 对于 iOS 版本为 16.1+,即支持 SKAdNetwork 4.0,您可以根据需要多次调用此方法,并可以使转换值低于或高于上一个值。
- 对于 iOS 版本低于 16.1,即所支持的 SKAdnetWork 版本低于 4.0,您仍可以调用此方法,我们的 SDK 将自动检测 iOS 版本并仅更新
conversionValue转换值。
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK initialize:@"<SDK_KEY>"];
[TenjinSDK connect];
//
// This will call [SKAdNetwork updatePostbackConversionValue: <Integer between 0 and 63>]
// and also send Conversion value to our servers.
//
// You will need to use a value between 0-63.
//
[TenjinSDK updatePostbackConversionValue:<Integer between 0 and 63>];
// For iOS 16.1+ (SKAN 4.0)
[TenjinSDK updatePostbackConversionValue:<Integer between 0 and 63> coarseValue:@"medium"];
[TenjinSDK updatePostbackConversionValue:<Integer between 0 and 63> coarseValue:@"medium" lockWindow:true];
}
@endSKAdNetwork 和 iOS 15+ 广告主回调 #
需要将 Tenjin 指定为 SKAdNetwork 回调接收方,请进行以下操作:
- 在 Xcode 的项目导航器中选择
Info.plist。 - 单击"属性/Property"列表编辑器中某个键旁边的添加按钮 (+),然后按回车键。
- 输入名称
NSAdvertisingAttributionReportEndpoint. - 从"类型/Type"列的弹出菜单中选择"String"。
- 输入
https://tenjin-skan.com
以上操作是为适配 Apple 的指引,具体详情可参:这里.
GDPR #
作为GDPR合规的一部分,使用Tenjin的SDK,你可以选择设备/用户的同意(opt-in)或拒绝(opt-out),或者选择针对哪些具体的设备相关参数进行同意或拒绝。
调用OptOut()时,将不会向Tenjin发送任何API请求,也不会处理任何事件。
选择opt-in/opt-out:
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK initialize:@"<SDK_KEY>"];
if ([self checkOptInValue]) {
[TenjinSDK optIn];
}
else {
[TenjinSDK optOut];
}
[TenjinSDK connect];
//All your other stuff
//..
}
-(BOOL) checkOptInValue
{
// check opt-in value
// return YES; // if user opted-in
return NO;
}要对特定的设备相关参数进行同意(opt-in)或拒绝(opt-out),你可以使用OptInParams()或OptOutParams()。
OptInParams() 只会发送你指定的设备相关参数。
OptOutParams() 会发送除你指定之外的所有设备相关参数。
- 请注意,我们至少需要以下参数来正确地对设备进行追踪监测:
developer_device_id
如果你使用 Google ads 投放,则还需要添加: advertising_id, developer_device_id, platform, os_version,app_version, locale, device_model, 和build_id.
如果只想使用OptInParams()获取设备相关的特定参数,在下面的样例中, 我们只发送这些设备相关的参数: ip_address, advertising_id, developer_device_id,和limit_ad_tracking
[TenjinSDK initialize:@"<SDK_KEY>"];
NSArray *optInParams = @[@"ip_address", @"advertising_id", @"developer_device_id", @"limit_ad_tracking"];
[TenjinSDK optInParams:optInParams];
[TenjinSDK connect];如果要使用OptOutParams()发送除特定设备相关参数以外的所有参数,如下样例中,我们会发送除了 locale, timezone, 和 build_id之外的所有相关的参数。
[TenjinSDK initialize:@"<SDK_KEY>"];
NSArray *optOutParams = @[@"country", @"timezone", @"language"];
[TenjinSDK optOutParams:optOutParams];
[TenjinSDK connect];Opt in/out using CMP #
您可以使用CMP (目的 1)的条款,实现自动选择opt in/out功能,并返回布尔值(boolean)。该功能基于用户设备中已存储的信息,无需额外交互。
optInOutUsingCMP()
[TenjinSDK initialize:@"<SDK_KEY>"];
optInOut = [TenjinSDK optInOutUsingCMP]; 设备层级数据 #
| 参数 | 说明 |
|---|---|
| ip_address | IP 地址 |
| advertising_id | 设备的广告标识符 |
| developer_device_id | ID for Vendor |
| limit_ad_tracking | 设备是否限制广告追踪 |
| platform | platform |
| os_version | 操作系统版本 |
| device | 设备名称 |
| device_model | 设备型号 |
| device_model_name | 设备型号 |
| device_cpu | 设备CPU |
| os_version_release | 操作系统版本 |
| build_id | 包名 |
| locale | 设备区域设置 |
| country | 设备国家设置 |
| timezone | timezone |
购买事件 #
在购买验证完成后,传入(SKPaymentTransaction *) transaction和(NSData *) receipt对象,然后将SKPaymentTransactionStatePurchased传递给Tenjin,用于标记该已购买的交易:
//Get the NSData receipt
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
//Pass the transaction and the receiptData to Tenjin
[TenjinSDK transaction: transaction andReceipt: receiptData];StoreKit 2 IAP #
StoreKit 2 是一款仅在Swift框架下使用的 API。对于使用StoreKit 2的应用,您可以提取JWS(JSON Web 签名)表示形式和交易详情:
import StoreKit
func handlePurchase(_ result: VerificationResult<Transaction>) async {
switch result {
case .verified(let transaction):
// Get the JWS representation (SK2 receipt)
let jwsRepresentation = transaction.jwsRepresentation
// Extract transaction details
let productId = transaction.productID
let transactionId = String(transaction.id)
let price = transaction.price ?? Decimal(0)
let currencyCode = transaction.currency?.identifier ?? "USD"
// Send to Tenjin
TenjinSDK.transaction(
withProductName: productId,
andCurrencyCode: currencyCode,
andQuantity: transaction.purchasedQuantity,
andUnitPrice: NSDecimalNumber(decimal: price),
andTransactionId: transactionId,
andBase64Receipt: jwsRepresentation
)
await transaction.finish()
case .unverified(_, _):
// Handle unverified transaction
break
}
}(灵活的应用商店佣金设置)您可以在Tenjin面板上选择0%、15%或30%的应用商店收入佣金。操作步骤如下:
- 前往CONFIGURE –> Apps
- 单击您想要更改的应用程序
- 在“App Store Commission”部分下单击“Edit”
- 在0%、15%或30%中选择您想要的应用商店佣金比例。
- 选择开始日期和结束日期(或者,如果您不需要结束日期,可以将结束日期留空)
- 点击“Save”保存(注意:佣金设置只会应用于变更日期之后的数据,历史数据不会受影响。因此请将开始日期设置为修改当天及之后的日期)。
订阅服务 #
重要:如果你有订阅类IAP,则需要在Tenjin dashboard中添加应用的public key。你可以在iTunes Connect Console中获取iOS的App-Specific Shared Secret:进入你的应用 > App Information > App-Specific Shared Secret。
请注意,你需要在每个订阅期间内发送相应的订阅交易(例如,如果是按月订阅,你需要每月向我们发送1笔交易)。
在下面的示例时间轴中,交易事件仅应在“首次收费 First Charge”和“续订 Renewal”事件中发送。在试用期间,请勿将交易事件发送给 Tenjin。Tenjin 不会对重复交易进行数据删除。
有关订阅的更多信息,请参阅: Apple documentation on Working with Subscriptions
自定义事件 #
重要提示:请不要在 CONNECT/INITIALIZATION 事件之前发送自定义事件.
必须先进行初始化,然后再发送自定义事件。
重要:自定义事件名称请限制在80个字符以内。自定义事件的数量不得超过500个。
使用 Tenjin SDK 传递自定义事件:
sendEventWithName: (NSString *)eventName和
你可以使用自定义事件来向 Tenjin 传递不同获客渠道的用户成本,样例如下:
//send a particular event for when someone swipes on a part of your app
[TenjinSDK sendEventWithName:@"swipe_right"];自定义事件也可以传递NString eventValue。 Tenjin 将eventValue作为同一个eventName的总和。 eventValue必须为整数,如果不是整数,Tenjin 将不发送事件。
//send a particular event for when someone swipes and an event value on a part of your app
[TenjinSDK sendEventWithName:@"swipe_right" andEventValue:@"1"];S2S 服务端集成 #
Tenjin提供s2s服务端集成。这允许你直接从自己的服务器向Tenjin服务器发送安装和安装后事件,无需集成SDK。
应用子版本及 A/B 测试(需要DataVault) #
如果你想进行 A/B 测试并查看差异报告,我们可以使用appendAppSubversion方法将数字值附加到你的应用程序版本中。例如,如果你的应用程序版本 1.0.1设置了appendAppSubversion: @8888,就可以上报 App version 为1.0.1.8888的数据。
这些数据将在 DataVault 中,你可以通对应的过 subversion 值来查看报告。
[TenjinSDK initialize:@" "];
[TenjinSDK appendAppSubversion:@8888];
[TenjinSDK connect];广告展示层级收益集成 #
Tenjin目前支持与以下聚合平台展示数据的集成:
- AppLovin
- Unity LevelPlay
- HyperBid
- AdMob
- TopOn
- CAS
- TradPlus
此功能将允许您获取每一个广告展示的明细数据,该功能可用于广告投放渠道基于广告收益的优化策略,以及更精确的用户层级收益计算等。具体文档请参考这里。
动态运营LiveOps #
Tenjin 支持在 SDK 层面获取用户的来源信息,包括买量渠道及广告计划等。如有需要,请联系您的客户经理。 这将允许广告主实时收集和分析这些用户级归因数据。以下是使用 Tenjin LiveOps 动态运营的实用案例:
- 如果您有自己的数据分析工具,S2S回调将允许您将归因数据与设备级别的游戏内数据联系起来,也就是将推广数据与应用内事件数据相联系。
- 根据用户的来源显示不同的应用程序内容。例如,用户A是自然量用户,而用户B是Facebook买量用户。由于用户B可能更喜欢您的应用程序,因此您可能希望在用户安装应用程序之后为用户B显示游戏内的特别优惠,这时就可以使用自定义回传。如果您想讨论更多具体的用例,请联系Tenjin成功经理。
LiveOps相关文档请参考这里。
用户ID #
您发送事件时可以设置自定义的用户ID。
setCustomerUserId(userId: "user_id") getCustomerUserId()
[TenjinSDK initialize:@"<SDK_KEY>"];
[TenjinSDK setCustomerUserId:@"user_id"];
userId = [TenjinSDK getCustomerUserId]; 分析ID Analytics Installation ID #
您可以在设备的本地储备中获取分析ID(Analytics Installation ID),该ID是随机生成的。 getAnalyticsInstallationId()
[TenjinSDK initialize:@" "];
analyticsId = [TenjinSDK getAnalyticsInstallationId]; 用户画像–LiveOps指标 #
Tenjin Android SDK会自动跟踪用户参与度指标,帮助你了解玩家行为和生命周期价值。这些指标会自动收集,并且可以通过代码获取。
自动收集 #
Tenjin SDK目前会自动收集:
- 会话指标:会话次数,时长,首次、末次会话日期
- 应用内购买 (IAP):交易次数、按货币统计的收入、已购买的产品ID
- 广告收入 (ILRD):来自支持的广告渠道的展示层级广告收入。
获取用户画像数据 #
获取完整用户资料对象 #
返回一个包含所有指标的TJNUserProfileData对象:
TJNUserProfileData *profile = [TenjinSDK getUserProfile];
// Session metrics
NSInteger sessionCount = profile.sessionCount;
long long totalTime = profile.totalSessionTime;
long long avgLength = profile.averageSessionLength;
long long lastSession = profile.lastSessionLength;
long long currentSession = profile.currentSessionDuration;
NSDate *firstSession = profile.firstSessionDate;
NSDate *lastSession = profile.lastSessionDate;
// IAP metrics
NSInteger iapCount = profile.iapTransactionCount;
NSDictionary *revenueByCurrency = profile.iapRevenueByCurrency;
NSArray *productIDs = profile.purchasedProductIDsArray;
// ILRD metrics
double totalAdRevenue = profile.totalILRDRevenueUSD;
NSDictionary *revenueByNetwork = profile.ilrdRevenueByNetwork;Available Properties:
| Property | 类型 | 说明 |
|---|---|---|
sessionCount | NSInteger | 会话总次数 |
totalSessionTime | long long | 总时长(毫秒) |
averageSessionLength | long long | 平均会话时长(毫秒) |
lastSessionLength | long long | 末次会话时长(毫秒) |
currentSessionDuration | long long | 当前活跃会话时长(毫秒) |
firstSessionDate | NSDate? | 首次会话日期 |
lastSessionDate | NSDate? | 上次完成的会话日期 |
iapTransactionCount | NSInteger | 总内购次数 |
iapRevenueByCurrency | NSDictionary<NSString*, NSNumber*> | 用货币代码获取内购收入 |
purchasedProductIDsArray | NSArray<NSString*> | 产品ID |
totalILRDRevenueUSD | double | 美元汇总的广告收入 |
ilrdRevenueByNetwork | NSDictionary<NSString*, NSNumber*> | 来自广告渠道的广告收入 |
以键值对(Dictionary)形式返回用户数据。 #
返回一个包含所有指标的Dictionary,便于进行序列化或展示:
NSDictionary *profileDict = [TenjinSDK getUserProfileAsDictionary];
// Example usage
NSNumber *sessionCount = profileDict[@"session_count"];
NSString *firstSession = profileDict[@"first_session_date"];
NSDictionary *iapRevenue = profileDict[@"iap_revenue_by_currency"];
NSArray *productIds = profileDict[@"purchased_product_ids"];Dictionary Keys:
| Key | 类型 | 说明 |
|---|---|---|
session_count | NSNumber | 会话次数 |
total_session_time | NSNumber | 总时长(毫秒) |
average_session_length | NSNumber | 平均会话时长(毫秒) |
last_session_length | NSNumber | 末次会话时长(毫秒) |
iap_transaction_count | NSNumber | 总内购次数 |
total_ilrd_revenue_usd | NSNumber | 美元汇总的广告收入 |
Dictionary Keys (Conditional – only if available):
| Key | 类型 | 说明 |
|---|---|---|
first_session_date | NSString | ISO8601格式的日期 |
last_session_date | NSString | ISO8601格式的日期 |
current_session_length | NSNumber | 活跃会话时长(毫秒) |
iap_revenue_by_currency | NSDictionary | 货币 → 收入的映射关系 |
purchased_product_ids | NSArray | Sorted array of product IDs |
ilrd_revenue_by_network | NSDictionary | 渠道 → 收入的映射关系 |
重置用户资料 #
清除所有用户资料数据(适用于测试或用户登出等场景):
[TenjinSDK resetUserProfile];会话配置 #
自定义会话超时时间(默认30分钟):
TJNUserProfileManager.sessionTimeoutInterval = 600; // 10 minutes辅助方法 #
获取指定货币的收入:
double usdRevenue = [profile getIAPRevenueForCurrency:@"USD"];获得某个广告渠道的展示层级广告收入
double appLovinRevenue = [profile getILRDRevenueForNetwork:TJNAdNetworkAppLovin];重试/缓存事件 #
当请求失败或用户没有网络连接时,您可以启用/禁用重试和缓存所有事件。 这些事件将在新事件添加到队列并且用户恢复连接后发送。
setCacheEventSetting(true)
[TenjinSDK setCacheEventSetting:true];Google DMA 参数 #
若您已集成CMP的模式,Google DMA参数将由Tenjin SDK自动采集,且无需额外操作。若您希望取代CMP,或者构建自己的用户协议机制,您可以使用以下方法:
setGoogleDMAParametersWithAdPersonalization(bool, bool)
[[TeninSDK sharedInstance] setGoogleDMAParametersWithAdPersonalization:adPersonalization adUserData:adUserData]; 您可以选择加入或退出谷歌 DMA 参数的收集,从而管理谷歌DMA参数的收集。默认情况下会加入,但您可以使用 optInGoogleDMA 或 optOutGoogleDMA 方法轻松更改您的偏好,从而完全控制您的数据隐私设置:
[TeninSDK optInGoogleDMA];
[TeninSDK optOutGoogleDMA]; 