From d5c02418c7c7bddf3ea74bcc426e355253291b21 Mon Sep 17 00:00:00 2001 From: huyufei Date: Fri, 31 May 2024 12:59:52 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E6=9B=B4=E6=96=B0=E5=92=8C=E5=AE=8C?= =?UTF-8?q?=E5=96=84=20GuruConsent=20=E6=9C=AC=E5=9C=B0=20iOS=20=E5=BA=93?= =?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6=E5=92=8C=20podspec=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --story=1020278 --user=yufei.hu 【中台】【发行】【iOS】 将 GuruConsent 库升级到最新的版本, 将线上的 Pods 依赖改为 UPM 内部文件依赖 https://www.tapd.cn/33527076/s/1147977 Signed-off-by: huyufei --- Runtime/GuruConsent/Bridge.meta | 3 - Runtime/GuruConsent/Bridge/Plugins.meta | 3 - Runtime/GuruConsent/Bridge/Plugins/iOS.meta | 3 - .../Plugins/Android/GuruConsent-1.0.0.aar | Bin 12980 -> 15787 bytes .../GuruConsent/Plugins/iOS/GuruConsent.meta | 3 + .../Plugins/iOS/GuruConsent.podspec | 4 +- .../Plugins/iOS/GuruConsent/LICENSE | 21 ++ .../iOS/{ => GuruConsent}/LICENSE.meta | 0 .../Plugins/iOS/GuruConsent/README.md | 282 ++++++++++++++++++ .../iOS/{ => GuruConsent}/README.md.meta | 0 .../iOS/{ => GuruConsent}/Resources.meta | 0 .../Resources/PrivacyInfo.xcprivacy | 60 ++++ .../Resources/PrivacyInfo.xcprivacy.meta | 85 ++++++ .../iOS/{ => GuruConsent}/Sources.meta | 0 .../Sources/GuruConsent.GDPR.swift | 121 ++++++++ .../Sources/GuruConsent.GDPR.swift.meta | 49 +++ .../iOS/GuruConsent/Sources/GuruConsent.swift | 204 +++++++++++++ .../Sources/GuruConsent.swift.meta | 49 +++ Runtime/GuruConsent/Plugins/iOS/LICENSE | 1 - Runtime/GuruConsent/Plugins/iOS/README.md | 1 - Runtime/GuruConsent/Plugins/iOS/Resources | 1 - Runtime/GuruConsent/Plugins/iOS/Sources | 1 - .../{Bridge => }/Plugins/iOS/U3DConsent.mm | 0 .../Plugins/iOS/U3DConsent.mm.meta | 0 Runtime/GuruConsent/README.md | 17 +- .../Runtime/Script/Consent/GuruConsent.cs | 4 +- 26 files changed, 890 insertions(+), 22 deletions(-) delete mode 100644 Runtime/GuruConsent/Bridge.meta delete mode 100644 Runtime/GuruConsent/Bridge/Plugins.meta delete mode 100644 Runtime/GuruConsent/Bridge/Plugins/iOS.meta create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent.meta create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent/LICENSE rename Runtime/GuruConsent/Plugins/iOS/{ => GuruConsent}/LICENSE.meta (100%) create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent/README.md rename Runtime/GuruConsent/Plugins/iOS/{ => GuruConsent}/README.md.meta (100%) rename Runtime/GuruConsent/Plugins/iOS/{ => GuruConsent}/Resources.meta (100%) create mode 100755 Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy.meta rename Runtime/GuruConsent/Plugins/iOS/{ => GuruConsent}/Sources.meta (100%) create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift.meta create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift create mode 100644 Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift.meta delete mode 120000 Runtime/GuruConsent/Plugins/iOS/LICENSE delete mode 120000 Runtime/GuruConsent/Plugins/iOS/README.md delete mode 120000 Runtime/GuruConsent/Plugins/iOS/Resources delete mode 120000 Runtime/GuruConsent/Plugins/iOS/Sources rename Runtime/GuruConsent/{Bridge => }/Plugins/iOS/U3DConsent.mm (100%) rename Runtime/GuruConsent/{Bridge => }/Plugins/iOS/U3DConsent.mm.meta (100%) diff --git a/Runtime/GuruConsent/Bridge.meta b/Runtime/GuruConsent/Bridge.meta deleted file mode 100644 index bc56537..0000000 --- a/Runtime/GuruConsent/Bridge.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b88f29431cdd47f9bc1945ddd590c4df -timeCreated: 1717035321 \ No newline at end of file diff --git a/Runtime/GuruConsent/Bridge/Plugins.meta b/Runtime/GuruConsent/Bridge/Plugins.meta deleted file mode 100644 index 0ab4f91..0000000 --- a/Runtime/GuruConsent/Bridge/Plugins.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: c1d92ec4f77c4f179f05f8a7be17de86 -timeCreated: 1717035338 \ No newline at end of file diff --git a/Runtime/GuruConsent/Bridge/Plugins/iOS.meta b/Runtime/GuruConsent/Bridge/Plugins/iOS.meta deleted file mode 100644 index 11b1c1c..0000000 --- a/Runtime/GuruConsent/Bridge/Plugins/iOS.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 4e5722a54ec94d72a304d981db2426f7 -timeCreated: 1717035343 \ No newline at end of file diff --git a/Runtime/GuruConsent/Plugins/Android/GuruConsent-1.0.0.aar b/Runtime/GuruConsent/Plugins/Android/GuruConsent-1.0.0.aar index d24ab95f64770f378361d56c4da95043df5f5d7a..d78c3c07b4c827ed8353c300fbde5bdabd2a9b77 100644 GIT binary patch delta 15322 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 'Resources/PrivacyInfo.xcprivacy' + s.name => 'GuruConsent/Resources/PrivacyInfo.xcprivacy' } end end diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/LICENSE b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/LICENSE new file mode 100644 index 0000000..a40c2c1 --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 CastBox Dev Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Runtime/GuruConsent/Plugins/iOS/LICENSE.meta b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/LICENSE.meta similarity index 100% rename from Runtime/GuruConsent/Plugins/iOS/LICENSE.meta rename to Runtime/GuruConsent/Plugins/iOS/GuruConsent/LICENSE.meta diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/README.md b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/README.md new file mode 100644 index 0000000..ec9e6d6 --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/README.md @@ -0,0 +1,282 @@ +# GuruConsent-iOS + +![Swift](https://img.shields.io/badge/Swift-5.0-orange.svg)  + +## 特性 + +- [x] 支持系统ATT权限引导弹窗. +- [x] 支持多国语言显示. +- [x] 支持调试EEA地理设置等. +- [x] 支持结果状态回调. + +## 准备 + +将应用 ID 添加到 Info.plist 中: + +``` +GADApplicationIdentifier +YOUR-APP-ID +``` + +将ATT跟踪权限添加到 Info.plist 中: + +``` +NSUserTrackingUsageDescription +This identifier will be used to deliver personalized ads to you. +``` + +## 安装 + +GuruConsent 仅支持CocoaPods. + +**CocoaPods - Podfile** + +```ruby +source 'git@github.com:castbox/GuruSpecs.git' + +pod 'GuruConsent' +``` + +## 使用 + +首先导入framework: + +Swift: + +```swift +import GuruConsent +``` + +Objective-C: + +```objc +#import +``` + +下面是一些简单示例. 支持所有设备和模拟器: + +### 方式一: 自动 + +如果满足显示条件 自动显示弹窗 具有一定的延迟效果 但具体显示时机不定, 受网络影响. + +__建议在应用启动后 延后一些调用开始 请务必确保首次启动后已授权网络请求权限再调用__ + +Swift: + +```swift +// 开始请求 +GuruConsent.start(from: controller) { result in + switch result { + case .success(let status): + if #available(iOS 14, *) { + print("ATT 结果: \(ATTrackingManager.trackingAuthorizationStatus)") + } + print("GDPR 结果: \(status)") + + case .failure(let error): + print("失败: \(error)") + } +} +``` + +Objective-C: + +```objc +// 开始请求 +[GuruConsent startFrom:self success:^(enum GuruConsentGDPRStatus status) { + + if (@available(iOS 14, *)) { + NSLog(@"ATT 结果: %lu", (unsigned long)ATTrackingManager.trackingAuthorizationStatus); + } + + switch (status) { + case GuruConsentGDPRStatusUnknown: + + break; + + case GuruConsentGDPRStatusRequired: + + break; + + case GuruConsentGDPRStatusNotRequired: + + break; + + case GuruConsentGDPRStatusObtained: + + break; + + default: + break; + } + NSLog(@"GDPR 结果: %ld", (long)status); + +} failure:^(NSError * _Nonnull error) { + NSLog(@"失败: %@", error); +}]; +``` + + +### 方式二: 手动 + +先调用准备, 准备完成后在合适的时机手动调用弹窗显示. + +__建议在应用启动后 延后一些调用准备 请务必确保首次启动后已授权网络请求权限再调用__ + +Swift: + +```swift +// 准备 +GuruConsent.prepare { result in + switch result { + case .success(let status): + print("GDPR 结果: \(status)") + + case .failure(let error): + print("失败: \(error)") + } +} + + +// 显示 请确保status为.required 否则无法显示 +GuruConsent.present(from: self) { result in + switch result { + case .success(let status): + if #available(iOS 14, *) { + print("ATT 结果: \(ATTrackingManager.trackingAuthorizationStatus)") + } + print("GDPR 结果: \(status)") + + case .failure(let error): + print("失败: \(error)") + } +} +``` + +Objective-C: + +```objc +// 准备 +[GuruConsent prepareWithSuccess:^(enum GuruConsentGDPRStatus status) { + + switch (status) { + case GuruConsentGDPRStatusUnknown: + + break; + + case GuruConsentGDPRStatusRequired: + + break; + + case GuruConsentGDPRStatusNotRequired: + + break; + + case GuruConsentGDPRStatusObtained: + + break; + + default: + break; + } + NSLog(@"GDPR 结果: %ld", (long)status); + +} failure:^(NSError * _Nonnull error) { + NSLog(@"失败: %@", error); +}]; + + +// 显示 请确保status为.required 否则无法显示 +[GuruConsent presentFrom:self success:^(enum GuruConsentGDPRStatus status) { + + if (@available(iOS 14, *)) { + NSLog(@"ATT 结果: %lu", (unsigned long)ATTrackingManager.trackingAuthorizationStatus); + } + + switch (status) { + case GuruConsentGDPRStatusUnknown: + + break; + + case GuruConsentGDPRStatusRequired: + + break; + + case GuruConsentGDPRStatusNotRequired: + + break; + + case GuruConsentGDPRStatusObtained: + + break; + + default: + break; + } + NSLog(@"GDPR 结果: %ld", (long)status); + +} failure:^(NSError * _Nonnull error) { + NSLog(@"%@", error); +}]; +``` + + +### 调试设置 + +`testDeviceIdentifiers`获取方式: 当传入空置, 运行调用`GuruConsent.start(from:)` Xcode控制台会输出如下: + +``` + To enable debug mode for this device, set: UMPDebugSettings.testDeviceIdentifiers = @[ @"8C5E8576-5090-4C41-8FC4-A5A80FF77D9E" ]; +``` +将控制台的`8C5E8576-5090-4C41-8FC4-A5A80FF77D9E` 复制粘贴到代码中, 再次运行即可进行调试. + +Swift: + +```swift +// 设置调试配置 +let debug = GuruConsent.DebugSettings() +debug.testDeviceIdentifiers = ["8C5E8576-5090-4C41-8FC4-A5A80FF77D9E"] +debug.geography = .EEA +GuruConsent.debug = debug +``` + +Objective-C: + +```objc +// 设置调试配置 +GuruConsentDebugSettings *debug = [[GuruConsentDebugSettings alloc] init]; +debug.testDeviceIdentifiers = @[@"8C5E8576-5090-4C41-8FC4-A5A80FF77D9E"]; +debug.geography = GuruConsentDebugSettingsGeographyEEA; +GuruConsent.debug = debug; +``` + +重置状态 + +```swift +GuruConsent.reset() +``` + +## 运行 + +### 未授权过ATT权限 (非EEA地区): +![IMG_4886](https://user-images.githubusercontent.com/13112992/201629493-3b95e3e8-ca02-41b6-9a64-1acd11ea4261.PNG) + +点击`Continue`按钮弹出ATT授权弹窗 + +![IMG_4887](https://user-images.githubusercontent.com/13112992/201629676-3ca39406-513a-46ec-b79e-60df4fd7cc88.PNG) + +### EEA地区: +![IMG_4888](https://user-images.githubusercontent.com/13112992/201629612-b736c439-54fe-4c59-97ee-71a6a449f23a.PNG) + +未授权过ATT权限 点击同意等按钮弹出ATT授权弹窗 + +![Simulator Screen Shot - iPhone 14 Pro - 2022-11-14 at 16 40 48](https://user-images.githubusercontent.com/13112992/201629990-ec3776b2-6bd0-4c3e-aba4-48f093216e11.png) + + +## 参考 + +[官方文档](https://developers.google.com/admob/ump/ios/quick-start) + +## 协议 + +GuruConsent 使用 MIT 协议. 有关更多信息,请参阅 [LICENSE](LICENSE) 文件. diff --git a/Runtime/GuruConsent/Plugins/iOS/README.md.meta b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/README.md.meta similarity index 100% rename from Runtime/GuruConsent/Plugins/iOS/README.md.meta rename to Runtime/GuruConsent/Plugins/iOS/GuruConsent/README.md.meta diff --git a/Runtime/GuruConsent/Plugins/iOS/Resources.meta b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources.meta similarity index 100% rename from Runtime/GuruConsent/Plugins/iOS/Resources.meta rename to Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources.meta diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy new file mode 100755 index 0000000..a20ab95 --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,60 @@ + + + + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeCoarseLocation + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypePerformanceData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeProductInteraction + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + + + NSPrivacyTrackingDomains + + NSPrivacyTracking + + + diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy.meta b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy.meta new file mode 100644 index 0000000..3399c07 --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Resources/PrivacyInfo.xcprivacy.meta @@ -0,0 +1,85 @@ +fileFormatVersion: 2 +guid: 71f33675e1c99450686a549ba5f04505 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/GuruConsent/Plugins/iOS/Sources.meta b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources.meta similarity index 100% rename from Runtime/GuruConsent/Plugins/iOS/Sources.meta rename to Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources.meta diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift new file mode 100644 index 0000000..2e0028f --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift @@ -0,0 +1,121 @@ +// +// GuruConsent.GDPR.swift +// GuruConsent +// +// Created by 李响 on 2022/11/11. +// + +import UIKit +import UserMessagingPlatform + +public extension GuruConsent { + + /// 当前状态 + @objc + public static var status: GDPRStatus { + return .init( + rawValue: UMPConsentInformation.sharedInstance.consentStatus.rawValue + ) ?? .unknown + } + + /// 是否可以请求广告 (status为.obtained或.notRequired) + @objc + public static var canRequestAds: Bool { + return UMPConsentInformation.sharedInstance.canRequestAds + } + + /// 隐私选项状态 + /// 初始状态为.unknown 如果status为.notRequired 该状态也是.notRequired + /// status为.obtained(弹窗同意后) 会变成.required, 代表可以让用户修改之前同意的隐私选项 + /// 调用`func openPrivacyOptions(from: with:)`方法可以再次打开弹窗 + /// 弹窗第二次打开后 用户可以重新勾选隐私选项并同意, 操作完成后状态会变为.unknown + @objc + public static var privacyOptionsRequirementStatus: GDPRPrivacyOptionsRequirementStatus { + return .init( + rawValue: UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus.rawValue + ) ?? .unknown + } + + private static var form: UMPConsentForm? + + internal static func request(with completion: @escaping ((Swift.Result) -> Void)) { + let parameters = UMPRequestParameters() + // 设置未满同意年龄的标签。此处false表示用户达到年龄 + parameters.tagForUnderAgeOfConsent = tagForUnderAgeOfConsent + // 设置调试设置 + if let debug = GuruConsent.debug { + let debugSettings = UMPDebugSettings() + debugSettings.testDeviceIdentifiers = debug.testDeviceIdentifiers + debugSettings.geography = .init(rawValue: debug.geography.rawValue) ?? .disabled + parameters.debugSettings = debugSettings + } + + // 请求最新同意信息 + UMPConsentInformation.sharedInstance.requestConsentInfoUpdate( + with: parameters, + completionHandler: { error in + if let error = error { + // 请求同意信息失败 + completion(.failure(error)) + + } else { + let status = UMPConsentInformation.sharedInstance.formStatus + completion(.success(.init(rawValue: status.rawValue) ?? .unknown)) + } + } + ) + } + + static func loadForm(with completion: @escaping ((Swift.Result) -> Void)) { + // 加载表单 + UMPConsentForm.load { form, error in + if let error = error { + // 表单加载失败 + completion(.failure(error)) + + } else { + self.form = form + let status = UMPConsentInformation.sharedInstance.consentStatus + completion(.success(.init(rawValue: status.rawValue) ?? .unknown)) + } + } + } + + static func openForm(from controller: UIViewController, with completion: @escaping ((Swift.Result) -> Void)) { + guard let form = form else { + completion(.failure(NSError(domain: "Form Empty.", code: -1))) + return + } + // 打开弹窗 + form.present( + from: controller, + completionHandler: { error in + if let error = error { + // 弹窗失败 + completion(.failure(error)) + + } else { + // 是否已同意 + completion(.success(status)) + } + } + ) + } + + /// 重置 + @objc + public static func reset() { + UMPConsentInformation.sharedInstance.reset() + } + + /// 打开隐私选项弹窗 (privacyOptionsRequirementStatus必须为.required) + /// - Parameters: + /// - controller: 视图控制器 + /// - completion: 完成回调 + @objc + public static func openPrivacyOptions(from controller: UIViewController, with completion: @escaping ((Error?) -> Void)) { + UMPConsentForm.presentPrivacyOptionsForm(from: controller) { error in + completion(error) + } + } +} diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift.meta b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift.meta new file mode 100644 index 0000000..48688a8 --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.GDPR.swift.meta @@ -0,0 +1,49 @@ +fileFormatVersion: 2 +guid: 604558f3813844f3eaa13f84fde7e522 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 0 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift new file mode 100644 index 0000000..f294437 --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift @@ -0,0 +1,204 @@ +// +// GuruConsent.swift +// GuruConsent +// +// Created by 李响 on 2022/11/11. +// + +import UIKit + +@objc +public class GuruConsent: NSObject { + + /// CDPR状态 + @objc(GuruConsentGDPRStatus) + public enum GDPRStatus: Int { + case unknown ///< Unknown consent status. + case required ///< User consent required but not yet obtained. + case notRequired ///< Consent not required. + case obtained ///< User consent obtained, personalized vs non-personalized undefined. + } + + /// CDPR表单状态 + internal enum GDPRFormStatus: Int { + case unknown + case available + case unavailable + } + + /// GDPR隐私选项所需状态 + @objc(GuruConsentGDPRPrivacyOptionsRequirementStatus) + public enum GDPRPrivacyOptionsRequirementStatus: Int { + case unknown ///< Requirement unknown. + case required ///< A way must be provided for the user to modify their privacy options. + case notRequired ///< User does not need to modify their privacy options. Either consent is not required, or the consent type does not require modification. + } + + /// 调试设置 + @objc(GuruConsentDebugSettings) + public class DebugSettings: NSObject { + + @objc(GuruConsentDebugSettingsGeography) + public enum Geography: Int { + case disabled + case EEA + case notEEA + } + + /// 测试设备ID + @objc + public var testDeviceIdentifiers: [String] + /// 地理位置 + @objc + public var geography: Geography + + @objc + public override init() { + testDeviceIdentifiers = [] + geography = .disabled + } + } + + /// 调试设置 + @objc + public static var debug: DebugSettings? + + /// 设置未满同意年龄的标签 默认为false 表示用户达到年龄 + @objc + public static var tagForUnderAgeOfConsent: Bool = false + + /// 是否已同意 (status为.obtained) + @objc + public static var isObtained: Bool { + return status == .obtained + } + + /// 开始 OC + /// ATT未授权过(非EEA地区) 会弹出ATT引导弹窗 在点击继续按钮时弹出ATT权限弹窗 + /// ATT未授权过(EEA地区) 会弹出GDPR弹窗 在点击同意时弹出ATT权限弹窗 + /// - Parameters: + /// - controller: 视图控制器 + /// - completion: 完成回调 + @objc + public static func start(from controller: UIViewController, success: @escaping ((GDPRStatus) -> Void), failure: @escaping (Error) -> Void) { + start(from: controller) { result in + switch result { + case .success(let value): + success(value) + + case .failure(let error): + failure(error) + } + } + } + + /// 开始 Swift + /// ATT未授权过(非EEA地区) 会弹出ATT引导弹窗 在点击继续按钮时弹出ATT权限弹窗 + /// ATT未授权过(EEA地区) 会弹出GDPR弹窗 在点击同意时弹出ATT权限弹窗 + /// - Parameters: + /// - controller: 视图控制器 + /// - completion: 完成回调 + public static func start(from controller: UIViewController, with completion: @escaping ((Swift.Result) -> Void)) { + request { result in + switch result { + case .success(let value): + if value == .available { + // 加载表单 + loadForm { result in + switch result { + case .success(let value): + switch value { + case .required: + // 打开表单 + openForm(from: controller, with: completion) + + default: + completion(.success(value)) + } + + case .failure(let error): + // 表单加载失败 + completion(.failure(error)) + } + } + + } else { + // 无表单需要加载 + completion(.success(.notRequired)) + } + + case .failure(let error): + // 请求同意信息失败 + completion(.failure(error)) + } + } + } + + /// ---------------------------------------- + + @objc + public static func prepare(success: @escaping ((GDPRStatus) -> Void), failure: @escaping (Error) -> Void) { + prepare { result in + switch result { + case .success(let value): + success(value) + + case .failure(let error): + failure(error) + } + } + } + + @objc + public static func present(from controller: UIViewController, success: @escaping ((GDPRStatus) -> Void), failure: @escaping (Error) -> Void) { + present(from: controller) { result in + switch result { + case .success(let value): + success(value) + + case .failure(let error): + failure(error) + } + } + } + + /// 预加载 (需在加载成功后 手动调用打开表单) + /// - Parameter completion: 完成回调 + public static func prepare(with completion: @escaping ((Swift.Result) -> Void)) { + request { result in + switch result { + case .success(let value): + if value == .available { + // 加载表单 + loadForm { result in + switch result { + case .success(let value): + // 表单加载成功 + completion(.success(value)) + + case .failure(let error): + // 表单加载失败 + completion(.failure(error)) + } + } + + } else { + // 无表单需要加载 + completion(.success(.notRequired)) + } + + case .failure(let error): + // 请求同意信息失败 + completion(.failure(error)) + } + } + } + + /// 打开表单 请确保status为.required 否则无效 + /// - Parameters: + /// - controller: 视图控制器 + /// - completion: 完成回调 + public static func present(from controller: UIViewController, with completion: @escaping ((Swift.Result) -> Void)) { + openForm(from: controller, with: completion) + } +} diff --git a/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift.meta b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift.meta new file mode 100644 index 0000000..2c848da --- /dev/null +++ b/Runtime/GuruConsent/Plugins/iOS/GuruConsent/Sources/GuruConsent.swift.meta @@ -0,0 +1,49 @@ +fileFormatVersion: 2 +guid: 0b11b5b1fa30a432eaf1b02602717dc9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 0 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/GuruConsent/Plugins/iOS/LICENSE b/Runtime/GuruConsent/Plugins/iOS/LICENSE deleted file mode 120000 index b012b3a..0000000 --- a/Runtime/GuruConsent/Plugins/iOS/LICENSE +++ /dev/null @@ -1 +0,0 @@ -/Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/LICENSE \ No newline at end of file diff --git a/Runtime/GuruConsent/Plugins/iOS/README.md b/Runtime/GuruConsent/Plugins/iOS/README.md deleted file mode 120000 index a167ee3..0000000 --- a/Runtime/GuruConsent/Plugins/iOS/README.md +++ /dev/null @@ -1 +0,0 @@ -/Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/README.md \ No newline at end of file diff --git a/Runtime/GuruConsent/Plugins/iOS/Resources b/Runtime/GuruConsent/Plugins/iOS/Resources deleted file mode 120000 index 9464a8b..0000000 --- a/Runtime/GuruConsent/Plugins/iOS/Resources +++ /dev/null @@ -1 +0,0 @@ -/Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/Resources \ No newline at end of file diff --git a/Runtime/GuruConsent/Plugins/iOS/Sources b/Runtime/GuruConsent/Plugins/iOS/Sources deleted file mode 120000 index ea570b1..0000000 --- a/Runtime/GuruConsent/Plugins/iOS/Sources +++ /dev/null @@ -1 +0,0 @@ -/Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/Sources \ No newline at end of file diff --git a/Runtime/GuruConsent/Bridge/Plugins/iOS/U3DConsent.mm b/Runtime/GuruConsent/Plugins/iOS/U3DConsent.mm similarity index 100% rename from Runtime/GuruConsent/Bridge/Plugins/iOS/U3DConsent.mm rename to Runtime/GuruConsent/Plugins/iOS/U3DConsent.mm diff --git a/Runtime/GuruConsent/Bridge/Plugins/iOS/U3DConsent.mm.meta b/Runtime/GuruConsent/Plugins/iOS/U3DConsent.mm.meta similarity index 100% rename from Runtime/GuruConsent/Bridge/Plugins/iOS/U3DConsent.mm.meta rename to Runtime/GuruConsent/Plugins/iOS/U3DConsent.mm.meta diff --git a/Runtime/GuruConsent/README.md b/Runtime/GuruConsent/README.md index 151741a..ccf0730 100644 --- a/Runtime/GuruConsent/README.md +++ b/Runtime/GuruConsent/README.md @@ -1,16 +1,23 @@ # Guru Unity Consent -## Version 1.0.8 +## 1.0.9 +* 更新 iOS 库版为本地 Pod 库, 直接引用源码 `1.4.6` +> 78dfe631fc97da53023577a7fcebb71400c3c873 +* Anroid 库同步 github 仓库最新版本 `1.0.0` +> f8355aecfb36132c252d216331ad6d8f2c4b6363 + +## 1.0.8 * 更新 GuruConsent 的 iOS 库版本至 `1.4.6` * 更新 iOS 库添加 Privacy Policy 的配置项 * 更新 iOS 依赖的 cocospods 库地址 -## Version 1.0.7 + +## 1.0.7 * 更新 Consent 针对 Json 参数的回调和解析逻辑. -## Version 1.0.6 +## 1.0.6 * 更新了Google DMA 合规策略, 请查询详细的 [Google Ads Consent Mode DMA合规 技术需求文档](https://docs.google.com/document/d/1p7ad-W6XnqPjMgFkvoVf1Yylsogm_PykD9_nauInVoI/edit#heading=h.42lwhi7yczmk) * 已集成了中台的 `dma_gg` 点位 * 云控可控变量 `dma_map_rule`, `dma_country_check` 两个参数来改变 TFC 策略以及开启地区检测 @@ -18,12 +25,12 @@ - ![](Docs/tcf_map.png) > 已知问题: 基于用户选择结果的 Purpose 在 iOS 上会产生乱码, 因此针对返回空串或非 "0","1" 的结果处理为非EEA地区的用户, 即不上报 DMA 数据 -## Version 1.0.3 +## 1.0.3 * 更新了SDKCallback对象的名称和逻辑, 同SDK本体进行区分 -## Version 1.0.2 +## 1.0.2 - 注意本插件库依赖 `LitJson` 用于解析Json格式数据. 请确保项目内引入此库. - 使用了 *EDM* 插件实现自动依赖注入. diff --git a/Runtime/GuruConsent/Runtime/Script/Consent/GuruConsent.cs b/Runtime/GuruConsent/Runtime/Script/Consent/GuruConsent.cs index a5e5a19..4c9ae94 100644 --- a/Runtime/GuruConsent/Runtime/Script/Consent/GuruConsent.cs +++ b/Runtime/GuruConsent/Runtime/Script/Consent/GuruConsent.cs @@ -14,7 +14,7 @@ namespace Guru public class GuruConsent { // Guru Consent Version - public static string Version = "1.0.8"; + public static string Version = "1.0.9"; public static string Tag = "[GuruConsent]"; #region 公用接口 @@ -56,7 +56,7 @@ namespace Guru string deviceId = "", int debugGeography = -1, string dmaMapRule = "", bool enableCountryCheck = false) { - Debug.Log($"{Tag} --- GuruConsent::StartConsent - deviceId:[{deviceId}] debugGeography:[{debugGeography}] dmaMapRule:[{dmaMapRule}] enableCountryCheck:[{enableCountryCheck}]"); + Debug.Log($"{Tag} --- GuruConsent::StartConsent [{Version}] - deviceId:[{deviceId}] debugGeography:[{debugGeography}] dmaMapRule:[{dmaMapRule}] enableCountryCheck:[{enableCountryCheck}]"); _dmaMapRule = dmaMapRule; _enableCountryCheck = enableCountryCheck;