update: 更新和完善 GuruConsent 本地 iOS 库的文件和 podspec 配置
--story=1020278 --user=yufei.hu 【中台】【发行】【iOS】 将 GuruConsent 库升级到最新的版本, 将线上的 Pods 依赖改为 UPM 内部文件依赖 https://www.tapd.cn/33527076/s/1147977 Signed-off-by: huyufei <yufei.hu@castbox.fm>hotfix/v1.0.12.2
							parent
							
								
									5882d213c3
								
							
						
					
					
						commit
						d5c02418c7
					
				|  | @ -1,3 +0,0 @@ | |||
| fileFormatVersion: 2 | ||||
| guid: b88f29431cdd47f9bc1945ddd590c4df | ||||
| timeCreated: 1717035321 | ||||
|  | @ -1,3 +0,0 @@ | |||
| fileFormatVersion: 2 | ||||
| guid: c1d92ec4f77c4f179f05f8a7be17de86 | ||||
| timeCreated: 1717035338 | ||||
|  | @ -1,3 +0,0 @@ | |||
| fileFormatVersion: 2 | ||||
| guid: 4e5722a54ec94d72a304d981db2426f7 | ||||
| timeCreated: 1717035343 | ||||
										
											Binary file not shown.
										
									
								
							|  | @ -0,0 +1,3 @@ | |||
| fileFormatVersion: 2 | ||||
| guid: 78bd1ca99d374a1f9f31be5cbf38b03c | ||||
| timeCreated: 1717118600 | ||||
|  | @ -22,7 +22,7 @@ Pod::Spec.new do |s| | |||
|   s.swift_version = '5.0' | ||||
|   s.ios.deployment_target = '12.0' | ||||
| 
 | ||||
|   s.source_files  = "Sources/**/*.swift" | ||||
|   s.source_files  = "GuruConsent/Sources/**/*.swift" | ||||
| 
 | ||||
|   s.requires_arc = true | ||||
|    | ||||
|  | @ -34,7 +34,7 @@ Pod::Spec.new do |s| | |||
|    | ||||
|   s.subspec 'Privacy' do |ss| | ||||
|       ss.resource_bundles = { | ||||
|         s.name => 'Resources/PrivacyInfo.xcprivacy' | ||||
|         s.name => 'GuruConsent/Resources/PrivacyInfo.xcprivacy' | ||||
|       } | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -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. | ||||
|  | @ -0,0 +1,282 @@ | |||
| # GuruConsent-iOS  | ||||
| 
 | ||||
|   | ||||
| 
 | ||||
| ## 特性 | ||||
| 
 | ||||
| - [x] 支持系统ATT权限引导弹窗. | ||||
| - [x] 支持多国语言显示. | ||||
| - [x] 支持调试EEA地理设置等. | ||||
| - [x] 支持结果状态回调. | ||||
| 
 | ||||
| ## 准备 | ||||
| 
 | ||||
| 将应用 ID 添加到 Info.plist 中: | ||||
| 
 | ||||
| ``` | ||||
| <key>GADApplicationIdentifier</key> | ||||
| <string>YOUR-APP-ID</string> | ||||
| ``` | ||||
| 
 | ||||
| 将ATT跟踪权限添加到 Info.plist 中: | ||||
| 
 | ||||
| ``` | ||||
| <key>NSUserTrackingUsageDescription</key> | ||||
| <string>This identifier will be used to deliver personalized ads to you.</string> | ||||
| ``` | ||||
| 
 | ||||
| ## 安装 | ||||
| 
 | ||||
| GuruConsent 仅支持CocoaPods. | ||||
| 
 | ||||
| **CocoaPods - Podfile** | ||||
| 
 | ||||
| ```ruby | ||||
| source 'git@github.com:castbox/GuruSpecs.git' | ||||
| 
 | ||||
| pod 'GuruConsent' | ||||
| ``` | ||||
| 
 | ||||
| ## 使用 | ||||
| 
 | ||||
| 首先导入framework: | ||||
| 
 | ||||
| Swift: | ||||
| 
 | ||||
| ```swift | ||||
| import GuruConsent | ||||
| ``` | ||||
| 
 | ||||
| Objective-C: | ||||
| 
 | ||||
| ```objc | ||||
| #import <GuruConsent/GuruConsent-Swift.h> | ||||
| ``` | ||||
| 
 | ||||
| 下面是一些简单示例. 支持所有设备和模拟器: | ||||
| 
 | ||||
| ### 方式一: 自动 | ||||
| 
 | ||||
| 如果满足显示条件 自动显示弹窗 具有一定的延迟效果 但具体显示时机不定, 受网络影响. | ||||
| 
 | ||||
| __建议在应用启动后 延后一些调用开始 请务必确保首次启动后已授权网络请求权限再调用__ | ||||
| 
 | ||||
| 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控制台会输出如下: | ||||
| 
 | ||||
| ``` | ||||
| <UMP SDK> 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地区):  | ||||
|  | ||||
| 
 | ||||
| 点击`Continue`按钮弹出ATT授权弹窗 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| ### EEA地区:  | ||||
|  | ||||
| 
 | ||||
| 未授权过ATT权限 点击同意等按钮弹出ATT授权弹窗 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| 
 | ||||
| ## 参考 | ||||
| 
 | ||||
| [官方文档](https://developers.google.com/admob/ump/ios/quick-start) | ||||
| 
 | ||||
| ## 协议 | ||||
| 
 | ||||
| GuruConsent 使用 MIT 协议. 有关更多信息,请参阅 [LICENSE](LICENSE) 文件. | ||||
|  | @ -0,0 +1,60 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| 	<key>NSPrivacyCollectedDataTypes</key> | ||||
| 	<array> | ||||
| 		<dict> | ||||
| 			<key>NSPrivacyCollectedDataType</key> | ||||
| 			<string>NSPrivacyCollectedDataTypeCoarseLocation</string> | ||||
| 			<key>NSPrivacyCollectedDataTypeLinked</key> | ||||
| 			<false/> | ||||
| 			<key>NSPrivacyCollectedDataTypeTracking</key> | ||||
| 			<false/> | ||||
| 			<key>NSPrivacyCollectedDataTypePurposes</key> | ||||
| 			<array> | ||||
| 				<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string> | ||||
| 			</array> | ||||
| 		</dict> | ||||
| 		<dict> | ||||
| 			<key>NSPrivacyCollectedDataType</key> | ||||
| 			<string>NSPrivacyCollectedDataTypePerformanceData</string> | ||||
| 			<key>NSPrivacyCollectedDataTypeLinked</key> | ||||
| 			<false/> | ||||
| 			<key>NSPrivacyCollectedDataTypeTracking</key> | ||||
| 			<false/> | ||||
| 			<key>NSPrivacyCollectedDataTypePurposes</key> | ||||
| 			<array> | ||||
| 				<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string> | ||||
| 			</array> | ||||
| 		</dict> | ||||
| 		<dict> | ||||
| 			<key>NSPrivacyCollectedDataType</key> | ||||
| 			<string>NSPrivacyCollectedDataTypeProductInteraction</string> | ||||
| 			<key>NSPrivacyCollectedDataTypeLinked</key> | ||||
| 			<false/> | ||||
| 			<key>NSPrivacyCollectedDataTypeTracking</key> | ||||
| 			<false/> | ||||
| 			<key>NSPrivacyCollectedDataTypePurposes</key> | ||||
| 			<array> | ||||
| 				<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string> | ||||
| 			</array> | ||||
| 		</dict> | ||||
| 	</array> | ||||
| 	<key>NSPrivacyAccessedAPITypes</key> | ||||
| 	<array> | ||||
| 		<dict> | ||||
| 			<key>NSPrivacyAccessedAPITypeReasons</key> | ||||
| 			<array> | ||||
| 				<string>CA92.1</string> | ||||
| 			</array> | ||||
| 			<key>NSPrivacyAccessedAPIType</key> | ||||
| 			<string>NSPrivacyAccessedAPICategoryUserDefaults</string> | ||||
| 		</dict> | ||||
| 	</array> | ||||
| 	<key>NSPrivacyTrackingDomains</key> | ||||
| 	<array/> | ||||
| 	<key>NSPrivacyTracking</key> | ||||
| 	<false/> | ||||
| </dict> | ||||
| </plist> | ||||
|  | @ -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:  | ||||
|  | @ -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<GDPRFormStatus, Error>) -> 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<GDPRStatus, Error>) -> 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<GDPRStatus, Error>) -> 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) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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:  | ||||
|  | @ -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<GDPRStatus, Error>) -> 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<GDPRStatus, Error>) -> 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<GDPRStatus, Error>) -> Void)) { | ||||
|         openForm(from: controller, with: completion) | ||||
|     } | ||||
| } | ||||
|  | @ -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:  | ||||
|  | @ -1 +0,0 @@ | |||
| /Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/LICENSE | ||||
|  | @ -1 +0,0 @@ | |||
| /Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/README.md | ||||
|  | @ -1 +0,0 @@ | |||
| /Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/Resources | ||||
|  | @ -1 +0,0 @@ | |||
| /Users/huyfuei/Workspace/Castbox/SDK/Native/GuruConsent-iOS/Sources | ||||
|  | @ -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 @@ | |||
| -  | ||||
| > 已知问题: 基于用户选择结果的 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* 插件实现自动依赖注入. | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue