From aecba9b75e83d5c03fdcde9a10f3a63374322349 Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Mon, 15 Apr 2024 15:29:35 -0700 Subject: [PATCH 1/9] Added DT Exchange Privacy API usage --- .../android/build.gradle | 24 ++-- .../DTExchangePrivacyApi.g.kt | 119 ++++++++++++++++++ .../GmaMediationDTExchangePlugin.kt | 25 +++- .../GmaMediationDtexchangePluginTest.kt | 76 ++++++++--- .../ios/Classes/DTExchangePrivacyApi.g.swift | 100 +++++++++++++++ .../lib/dtexchange_privacy_api.g.dart | 96 ++++++++++++++ .../lib/gma_mediation_dtexchange.dart | 18 ++- .../pigeons/dtexchange_privacy_api.dart | 36 ++++++ .../gma_mediation_dtexchange/pubspec.yaml | 1 + 9 files changed, 464 insertions(+), 31 deletions(-) create mode 100644 packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt create mode 100644 packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift create mode 100644 packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart create mode 100644 packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart diff --git a/packages/mediation/gma_mediation_dtexchange/android/build.gradle b/packages/mediation/gma_mediation_dtexchange/android/build.gradle index 908f4aa32..bc5e08aa3 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/build.gradle +++ b/packages/mediation/gma_mediation_dtexchange/android/build.gradle @@ -50,20 +50,30 @@ android { } dependencies { - implementation 'com.google.ads.mediation:fyber:8.2.6.1' - testImplementation 'org.jetbrains.kotlin:kotlin-test' - testImplementation 'org.mockito:mockito-core:5.0.0' + implementation 'com.google.ads.mediation:fyber:8.2.7.0' + testImplementation 'junit:junit:4.13.2' + testImplementation 'androidx.test:core:1.5.0' + testImplementation 'androidx.test:core-ktx:1.5.0' + testImplementation 'androidx.test.ext:junit:1.1.5' + testImplementation 'org.jetbrains.kotlin:kotlin-stdlib:1.8.20' + testImplementation 'org.mockito:mockito-core:5.5.0' + testImplementation 'org.mockito.kotlin:mockito-kotlin:5.1.0' + testImplementation 'org.robolectric:robolectric:4.10.3' } testOptions { unitTests.all { - useJUnitPlatform() + useJUnit() testLogging { - events "passed", "skipped", "failed", "standardOut", "standardError" - outputs.upToDateWhen {false} - showStandardStreams = true + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen {false} + showStandardStreams = true } } + unitTests { + includeAndroidResources = true + unitTests.returnDefaultValues = true + } } } diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt new file mode 100644 index 000000000..5d14701f0 --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt @@ -0,0 +1,119 @@ +// Autogenerated from Pigeon (v18.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer + +private fun wrapResult(result: Any?): List { + return listOf(result) +} + +private fun wrapError(exception: Throwable): List { + if (exception is FlutterError) { + return listOf( + exception.code, + exception.message, + exception.details + ) + } else { + return listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface DTExchangePrivacyApi { + fun setGDPRConsent(gdprConsent: Boolean) + fun setGDPRConsentString(gdprConsentString: String) + fun setUSPrivacyString(usPrivacyString: String) + + companion object { + /** The codec used by DTExchangePrivacyApi. */ + val codec: MessageCodec by lazy { + StandardMessageCodec() + } + /** Sets up an instance of `DTExchangePrivacyApi` to handle messages through the `binaryMessenger`. */ + @Suppress("UNCHECKED_CAST") + fun setUp(binaryMessenger: BinaryMessenger, api: DTExchangePrivacyApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val gdprConsentArg = args[0] as Boolean + var wrapped: List + try { + api.setGDPRConsent(gdprConsentArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val gdprConsentStringArg = args[0] as String + var wrapped: List + try { + api.setGDPRConsentString(gdprConsentStringArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val usPrivacyStringArg = args[0] as String + var wrapped: List + try { + api.setUSPrivacyString(usPrivacyStringArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt index 6477b3a14..62540fd2d 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt +++ b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt @@ -1,10 +1,27 @@ package io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange +import com.fyber.inneractive.sdk.external.InneractiveAdManager import io.flutter.embedding.engine.plugins.FlutterPlugin -/** Class that serves as bridge to get the adapter android dependency and make it available to a Flutter app. */ -class GmaMediationDTExchangePlugin: FlutterPlugin { - override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {} +/** Manages DTExchangePrivacyApi and implements the needed methods. */ +class GmaMediationDTExchangePlugin: FlutterPlugin, DTExchangePrivacyApi { + override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + DTExchangePrivacyApi.setUp(flutterPluginBinding.binaryMessenger, this) + } - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {} + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + DTExchangePrivacyApi.setUp(binding.binaryMessenger, null) + } + + override fun setGDPRConsent(gdprConsent: Boolean) { + InneractiveAdManager.setGdprConsent(gdprConsent) + } + + override fun setGDPRConsentString(gdprConsentString: String) { + InneractiveAdManager.setGdprConsentString(gdprConsentString) + } + + override fun setUSPrivacyString(usPrivacyString: String) { + InneractiveAdManager.setUSPrivacyString(usPrivacyString) + } } diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt b/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt index 215f07eb9..dcbf6dbba 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt +++ b/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt @@ -1,27 +1,67 @@ package io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import kotlin.test.Test -import org.mockito.Mockito - -/* - * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation. - * - * Once you have built the plugin's example app, you can run these tests from the command - * line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or - * you can run them directly from IDEs that support JUnit such as Android Studio. - */ +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.fyber.inneractive.sdk.external.InneractiveAdManager +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mockStatic +import org.mockito.kotlin.eq +@RunWith(AndroidJUnit4::class) internal class GmaMediationDtexchangePluginTest { @Test - fun onMethodCall_getPlatformVersion_returnsExpectedValue() { - val plugin = GmaMediationDtexchangePlugin() + fun setGDPRConsent_withTrueValue_invokesSetGdprConsentWithTrueValue() { + val plugin = GmaMediationDTExchangePlugin() + mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> - val call = MethodCall("getPlatformVersion", null) - val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) - plugin.onMethodCall(call, mockResult) + plugin.setGDPRConsent(true) - Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) + mockedDTExchangeAdManager.verify { + InneractiveAdManager.setGdprConsent(eq(true)) + } + } + } + + @Test + fun setGDPRConsent_withFalseValue_invokesSetGdprConsentWithFalseValue() { + val plugin = GmaMediationDTExchangePlugin() + mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> + + plugin.setGDPRConsent(false) + + mockedDTExchangeAdManager.verify { + InneractiveAdManager.setGdprConsent(eq(false)) + } + } + } + + @Test + fun setGDPRConsentString_invokesSetGdprConsentString() { + val plugin = GmaMediationDTExchangePlugin() + mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> + + plugin.setGDPRConsentString(TEST_CONSENT_STRING) + + mockedDTExchangeAdManager.verify { + InneractiveAdManager.setGdprConsentString(eq(TEST_CONSENT_STRING)) + } + } + } + + @Test + fun setUSPrivacyString_invokesSetUSPrivacyString() { + val plugin = GmaMediationDTExchangePlugin() + mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> + + plugin.setUSPrivacyString(TEST_CONSENT_STRING) + + mockedDTExchangeAdManager.verify { + InneractiveAdManager.setUSPrivacyString(eq(TEST_CONSENT_STRING)) + } + } + } + + companion object { + const val TEST_CONSENT_STRING = "testConsentString" } } diff --git a/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift new file mode 100644 index 000000000..993e4f46c --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift @@ -0,0 +1,100 @@ +// Autogenerated from Pigeon (v18.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol DTExchangePrivacyApi { + func setGDPRConsent(gdprConsent: Bool) throws + func setGDPRConsentString(gdprConsentString: String) throws + func setUSPrivacyString(usPrivacyString: String) throws +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class DTExchangePrivacyApiSetup { + /// The codec used by DTExchangePrivacyApi. + /// Sets up an instance of `DTExchangePrivacyApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: DTExchangePrivacyApi?, messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + let setGDPRConsentChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent\(channelSuffix)", binaryMessenger: binaryMessenger) + if let api = api { + setGDPRConsentChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let gdprConsentArg = args[0] as! Bool + do { + try api.setGDPRConsent(gdprConsent: gdprConsentArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setGDPRConsentChannel.setMessageHandler(nil) + } + let setGDPRConsentStringChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString\(channelSuffix)", binaryMessenger: binaryMessenger) + if let api = api { + setGDPRConsentStringChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let gdprConsentStringArg = args[0] as! String + do { + try api.setGDPRConsentString(gdprConsentString: gdprConsentStringArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setGDPRConsentStringChannel.setMessageHandler(nil) + } + let setUSPrivacyStringChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString\(channelSuffix)", binaryMessenger: binaryMessenger) + if let api = api { + setUSPrivacyStringChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let usPrivacyStringArg = args[0] as! String + do { + try api.setUSPrivacyString(usPrivacyString: usPrivacyStringArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setUSPrivacyStringChannel.setMessageHandler(nil) + } + } +} diff --git a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart new file mode 100644 index 000000000..024e2bf9a --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart @@ -0,0 +1,96 @@ +// Autogenerated from Pigeon (v18.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +class DTExchangePrivacyApi { + /// Constructor for [DTExchangePrivacyApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + DTExchangePrivacyApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : __pigeon_binaryMessenger = binaryMessenger, + __pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? __pigeon_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = StandardMessageCodec(); + + final String __pigeon_messageChannelSuffix; + + Future setGDPRConsent(bool gdprConsent) async { + final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([gdprConsent]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setGDPRConsentString(String gdprConsentString) async { + final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([gdprConsentString]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setUSPrivacyString(String usPrivacyString) async { + final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([usPrivacyString]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } +} diff --git a/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart b/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart index d645a3381..4862db04d 100644 --- a/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart +++ b/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart @@ -12,5 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// This empty class is needed to allow correct compatibility analysis with host platforms. -class GmaMediationDTExchange {} +import 'package:gma_mediation_dtexchange/dtexchange_privacy_api.g.dart'; + +/// This class has entrypoint to call DT Exchange's SDK APIs. +class GmaMediationDTExchange { + Future setGDPRConsent(bool gdprConsent) async { + DTExchangePrivacyApi().setGDPRConsent(gdprConsent); + } + + Future setGDPRConsentString(String gdprConsentString) async { + DTExchangePrivacyApi().setGDPRConsentString(gdprConsentString); + } + + Future setUSPrivacyString(String usPrivacyString) async { + DTExchangePrivacyApi().setUSPrivacyString(usPrivacyString); + } +} diff --git a/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart new file mode 100644 index 000000000..e95a83510 --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart @@ -0,0 +1,36 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/dtexchange_privacy_api.g.dart', + dartOptions: DartOptions(), + kotlinOut: + 'android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt', + kotlinOptions: KotlinOptions( + package: + 'io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange',), + swiftOut: 'ios/Classes/DTExchangePrivacyApi.g.swift', + swiftOptions: SwiftOptions(), + dartPackageName: 'gma_mediation_dtexchange', +),) +@HostApi() +abstract class DTExchangePrivacyApi { + void setGDPRConsent(bool gdprConsent); + + void setGDPRConsentString(String gdprConsentString); + + void setUSPrivacyString(String usPrivacyString); +} diff --git a/packages/mediation/gma_mediation_dtexchange/pubspec.yaml b/packages/mediation/gma_mediation_dtexchange/pubspec.yaml index 6862acfdb..06564edf9 100644 --- a/packages/mediation/gma_mediation_dtexchange/pubspec.yaml +++ b/packages/mediation/gma_mediation_dtexchange/pubspec.yaml @@ -18,6 +18,7 @@ dev_dependencies: flutter_test: sdk: flutter lint: ^2.3.0 + pigeon: ^18.0.0 flutter: plugin: From 608cfe6e52d5824f679444e7cdaa011e4fbd7867 Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Mon, 15 Apr 2024 16:04:09 -0700 Subject: [PATCH 2/9] Added iOS Privacy API --- .../example/ios/Flutter/Debug.xcconfig | 1 + .../example/ios/Flutter/Release.xcconfig | 1 + .../example/ios/Podfile | 43 ++++++++++++ .../ios/Runner.xcodeproj/project.pbxproj | 24 +++++-- .../contents.xcworkspacedata | 3 + .../GmaMediationDtexchangePluginTests.swift | 69 +++++++++++++++++++ .../example/ios/RunnerTests/RunnerTests.swift | 26 ------- .../GmaMediationDTExchangePlugin.swift | 51 +++++++++++++- 8 files changed, 185 insertions(+), 33 deletions(-) create mode 100644 packages/mediation/gma_mediation_dtexchange/example/ios/Podfile create mode 100644 packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift delete mode 100644 packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/RunnerTests.swift diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Debug.xcconfig b/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Debug.xcconfig index 592ceee85..ec97fc6f3 100644 --- a/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Debug.xcconfig +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Release.xcconfig b/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Release.xcconfig index 592ceee85..c4855bfe2 100644 --- a/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Release.xcconfig +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/Podfile b/packages/mediation/gma_mediation_dtexchange/example/ios/Podfile new file mode 100644 index 000000000..38b28ff0d --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj b/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj index a4c29d867..d28ca38f1 100644 --- a/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,7 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 331C808B294A63AB00263BE5 /* GmaMediationDtexchangePluginTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* GmaMediationDtexchangePluginTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -42,7 +42,7 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C807B294A618700263BE5 /* GmaMediationDtexchangePluginTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GmaMediationDtexchangePluginTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; @@ -58,6 +58,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 7479BD3A993BCA69DD5BAE53 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -71,11 +78,18 @@ 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, + 331C807B294A618700263BE5 /* GmaMediationDtexchangePluginTests.swift */, ); path = RunnerTests; sourceTree = ""; }; + 7F5876306538D9102F2D1064 /* Pods */ = { + isa = PBXGroup; + children = ( + ); + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -94,6 +108,7 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + 7F5876306538D9102F2D1064 /* Pods */, ); sourceTree = ""; }; @@ -130,6 +145,7 @@ buildPhases = ( 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + 7479BD3A993BCA69DD5BAE53 /* Frameworks */, ); buildRules = ( ); @@ -260,7 +276,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + 331C808B294A63AB00263BE5 /* GmaMediationDtexchangePluginTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16e..21a3cc14c 100644 --- a/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift b/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift new file mode 100644 index 000000000..2b090970f --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift @@ -0,0 +1,69 @@ +import UIKit +import XCTest + +@testable import gma_mediation_dtexchange + +class GmaMediationDtexchangePluginTests: XCTestCase { + func testSetGDPRConsent() { + let dtExchangeFake = DTExchangePrivacyFake() + let plugin = GmaMediationDTExchangePlugin.init(dtExchangeApi: dtExchangeFake) + + do { + try plugin.setGDPRConsent(gdprConsent: true) + } catch { + fatalError("testSetGDPRConsent FAILED: setGDPRConsent did not complete.") + } + + XCTAssertEqual(dtExchangeFake.gdprConsent, true) + } + + func testSetGDPRConsentString() { + let dtExchangeFake = DTExchangePrivacyFake() + let plugin = GmaMediationDTExchangePlugin.init(dtExchangeApi: dtExchangeFake) + + do { + try plugin.setGDPRConsentString(gdprConsentString: "testString") + } catch { + fatalError("testSetGDPRConsentString FAILED: setGDPRConsentString did not complete.") + } + + XCTAssertEqual(dtExchangeFake.gdprString, "testString") + } + + func testSetUSPrivacyString() { + let dtExchangeFake = DTExchangePrivacyFake() + let plugin = GmaMediationDTExchangePlugin.init(dtExchangeApi: dtExchangeFake) + + do { + try plugin.setUSPrivacyString(usPrivacyString: "testString") + } catch { + fatalError("testSetUSPrivacyString FAILED: setUSPrivacyString did not complete.") + } + + XCTAssertEqual(dtExchangeFake.usPrivacyString, "testString") + } +} + +class DTExchangePrivacyFake : DTExchangePrivacyProtocol { + var gdprConsent: Bool + var gdprString: String + var usPrivacyString: String + + init() { + gdprConsent = false + gdprString = "" + usPrivacyString = "" + } + + func setGDPRConsent(gdprConsent: Bool) { + self.gdprConsent = gdprConsent + } + + func setGDPRConsentString(gdprConsentString: String) { + self.gdprString = gdprConsentString + } + + func setUSPrivacyString(usPrivacyString: String) { + self.usPrivacyString = usPrivacyString + } +} diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/RunnerTests.swift b/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 93479ea0b..000000000 --- a/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Flutter -import UIKit -import XCTest - -@testable import gma_mediation_dtexchange - -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - -class RunnerTests: XCTestCase { - - func testGetPlatformVersion() { - let plugin = GmaMediationDtexchangePlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) - } - -} diff --git a/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift b/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift index 15402e8c9..1dc8f7439 100644 --- a/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift +++ b/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift @@ -1,7 +1,52 @@ import Flutter +import IASDKCore import UIKit -/// Class that serves as bridge to get the adapter iOS dependency and make it available to a Flutter app. -public class GmaMediationDTExchangePlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) {} +/// Manages DTExchangePrivacyApi and implements the needed methods. +public class GmaMediationDTExchangePlugin: NSObject, FlutterPlugin, DTExchangePrivacyApi { + let dtExchangeApi: DTExchangePrivacyProtocol + + init (dtExchangeApi: DTExchangePrivacyProtocol) { + self.dtExchangeApi = dtExchangeApi + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let messenger : FlutterBinaryMessenger = registrar.messenger() + let api : DTExchangePrivacyApi&NSObjectProtocol=GmaMediationDTExchangePlugin.init(dtExchangeApi: DTExchangePrivacyImpl()) + DTExchangePrivacyApiSetup.setUp(binaryMessenger: messenger, api: api) + } + + func setGDPRConsent(gdprConsent: Bool) throws { + dtExchangeApi.setGDPRConsent(gdprConsent: gdprConsent) + } + + func setGDPRConsentString(gdprConsentString: String) throws { + dtExchangeApi.setGDPRConsentString(gdprConsentString: gdprConsentString) + } + + func setUSPrivacyString(usPrivacyString: String) throws { + dtExchangeApi.setUSPrivacyString(usPrivacyString: usPrivacyString) + } +} + +protocol DTExchangePrivacyProtocol { + func setGDPRConsent(gdprConsent: Bool) + + func setGDPRConsentString(gdprConsentString: String) + + func setUSPrivacyString(usPrivacyString: String) +} + +class DTExchangePrivacyImpl : DTExchangePrivacyProtocol { + func setGDPRConsent(gdprConsent: Bool) { + IASDKCore.sharedInstance().gdprConsent = gdprConsent ? IAGDPRConsentType.given : IAGDPRConsentType.denied + } + + func setGDPRConsentString(gdprConsentString: String) { + IASDKCore.sharedInstance().gdprConsentString = gdprConsentString + } + + func setUSPrivacyString(usPrivacyString: String) { + IASDKCore.sharedInstance().ccpaString = usPrivacyString + } } From 548c97e38c715e8d921a85c3f0006badce89cdde Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 16 Apr 2024 09:44:13 -0700 Subject: [PATCH 3/9] Format Fix --- .../DTExchangePrivacyApi.g.kt | 9 ++++- .../ios/Classes/DTExchangePrivacyApi.g.swift | 8 ++++ .../lib/dtexchange_privacy_api.g.dart | 39 ++++++++++++------- .../pigeons/dtexchange_privacy_api.dart | 30 ++++++++------ 4 files changed, 61 insertions(+), 25 deletions(-) diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt index 5d14701f0..943651eb0 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt +++ b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt @@ -42,10 +42,17 @@ class FlutterError ( override val message: String? = null, val details: Any? = null ) : Throwable() -/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +/** + * The generated classes set the channels to call the methods in the corresponding kotlin DTExchangePrivacyApi interface and swift DTExchangePrivacyApi protocol from the dart layer. + * + * Generated interface from Pigeon that represents a handler of messages from Flutter. + */ interface DTExchangePrivacyApi { + /** Used to configure GDPR on the Android or iOS DTExchange SDK */ fun setGDPRConsent(gdprConsent: Boolean) + /** Used to configure GDPR String on the Android or iOS DTExchange SDK */ fun setGDPRConsentString(gdprConsentString: String) + /** Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK */ fun setUSPrivacyString(usPrivacyString: String) companion object { diff --git a/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift index 993e4f46c..893e2534d 100644 --- a/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift +++ b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift @@ -38,10 +38,15 @@ private func nilOrValue(_ value: Any?) -> T? { if value is NSNull { return nil } return value as! T? } +/// The generated classes set the channels to call the methods in the corresponding kotlin DTExchangePrivacyApi interface and swift DTExchangePrivacyApi protocol from the dart layer. +/// /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol DTExchangePrivacyApi { + /// Used to configure GDPR on the Android or iOS DTExchange SDK func setGDPRConsent(gdprConsent: Bool) throws + /// Used to configure GDPR String on the Android or iOS DTExchange SDK func setGDPRConsentString(gdprConsentString: String) throws + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK func setUSPrivacyString(usPrivacyString: String) throws } @@ -51,6 +56,7 @@ class DTExchangePrivacyApiSetup { /// Sets up an instance of `DTExchangePrivacyApi` to handle messages through the `binaryMessenger`. static func setUp(binaryMessenger: FlutterBinaryMessenger, api: DTExchangePrivacyApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + /// Used to configure GDPR on the Android or iOS DTExchange SDK let setGDPRConsentChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent\(channelSuffix)", binaryMessenger: binaryMessenger) if let api = api { setGDPRConsentChannel.setMessageHandler { message, reply in @@ -66,6 +72,7 @@ class DTExchangePrivacyApiSetup { } else { setGDPRConsentChannel.setMessageHandler(nil) } + /// Used to configure GDPR String on the Android or iOS DTExchange SDK let setGDPRConsentStringChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString\(channelSuffix)", binaryMessenger: binaryMessenger) if let api = api { setGDPRConsentStringChannel.setMessageHandler { message, reply in @@ -81,6 +88,7 @@ class DTExchangePrivacyApiSetup { } else { setGDPRConsentStringChannel.setMessageHandler(nil) } + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK let setUSPrivacyStringChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString\(channelSuffix)", binaryMessenger: binaryMessenger) if let api = api { setUSPrivacyStringChannel.setMessageHandler { message, reply in diff --git a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart index 024e2bf9a..1adf1e40b 100644 --- a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart +++ b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart @@ -15,22 +15,29 @@ PlatformException _createConnectionError(String channelName) { ); } +/// The generated classes set the channels to call the methods in the corresponding kotlin DTExchangePrivacyApi interface and swift DTExchangePrivacyApi protocol from the dart layer. class DTExchangePrivacyApi { /// Constructor for [DTExchangePrivacyApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - DTExchangePrivacyApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + DTExchangePrivacyApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + __pigeon_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? __pigeon_binaryMessenger; - static const MessageCodec pigeonChannelCodec = StandardMessageCodec(); + static const MessageCodec pigeonChannelCodec = + StandardMessageCodec(); final String __pigeon_messageChannelSuffix; + /// Used to configure GDPR on the Android or iOS DTExchange SDK Future setGDPRConsent(bool gdprConsent) async { - final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + final String __pigeon_channelName = + 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, @@ -50,15 +57,18 @@ class DTExchangePrivacyApi { } } + /// Used to configure GDPR String on the Android or iOS DTExchange SDK Future setGDPRConsentString(String gdprConsentString) async { - final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + final String __pigeon_channelName = + 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([gdprConsentString]) as List?; + final List? __pigeon_replyList = await __pigeon_channel + .send([gdprConsentString]) as List?; if (__pigeon_replyList == null) { throw _createConnectionError(__pigeon_channelName); } else if (__pigeon_replyList.length > 1) { @@ -72,15 +82,18 @@ class DTExchangePrivacyApi { } } + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK Future setUSPrivacyString(String usPrivacyString) async { - final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + final String __pigeon_channelName = + 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([usPrivacyString]) as List?; + final List? __pigeon_replyList = await __pigeon_channel + .send([usPrivacyString]) as List?; if (__pigeon_replyList == null) { throw _createConnectionError(__pigeon_channelName); } else if (__pigeon_replyList.length > 1) { diff --git a/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart index e95a83510..24a6d4d37 100644 --- a/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart +++ b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart @@ -14,23 +14,31 @@ import 'package:pigeon/pigeon.dart'; -@ConfigurePigeon(PigeonOptions( - dartOut: 'lib/dtexchange_privacy_api.g.dart', - dartOptions: DartOptions(), - kotlinOut: - 'android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt', - kotlinOptions: KotlinOptions( +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/dtexchange_privacy_api.g.dart', + dartOptions: DartOptions(), + kotlinOut: + 'android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt', + kotlinOptions: KotlinOptions( package: - 'io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange',), - swiftOut: 'ios/Classes/DTExchangePrivacyApi.g.swift', - swiftOptions: SwiftOptions(), - dartPackageName: 'gma_mediation_dtexchange', -),) + 'io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange', + ), + swiftOut: 'ios/Classes/DTExchangePrivacyApi.g.swift', + swiftOptions: SwiftOptions(), + dartPackageName: 'gma_mediation_dtexchange', + ), +) @HostApi() + +/// The generated classes set the channels to call the methods in the corresponding kotlin DTExchangePrivacyApi interface and swift DTExchangePrivacyApi protocol from the dart layer. abstract class DTExchangePrivacyApi { + /// Used to configure GDPR on the Android or iOS DTExchange SDK void setGDPRConsent(bool gdprConsent); + /// Used to configure GDPR String on the Android or iOS DTExchange SDK void setGDPRConsentString(String gdprConsentString); + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK void setUSPrivacyString(String usPrivacyString); } From 8ee1c3af2acdb4ff81d0cd98ace5c55338b00493 Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 16 Apr 2024 10:12:51 -0700 Subject: [PATCH 4/9] Added Android and iOS jobs to the DT Exchange github action --- .../workflows/gma_mediation_dtexchange.yaml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/.github/workflows/gma_mediation_dtexchange.yaml b/.github/workflows/gma_mediation_dtexchange.yaml index d5c5818d2..980aab911 100644 --- a/.github/workflows/gma_mediation_dtexchange.yaml +++ b/.github/workflows/gma_mediation_dtexchange.yaml @@ -26,6 +26,57 @@ on: - main jobs: + android: + runs-on: macos-latest + if: github.event_name == 'pull_request' + timeout-minutes: 30 + steps: + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + with: + fetch-depth: 0 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + - name: "Install Flutter" + run: ./.github/workflows/scripts/install-flutter.sh stable + - name: "Install Tools" + run: ./.github/workflows/scripts/install-tools.sh + - name: "Build Example" + run: ./.github/workflows/scripts/build-example.sh android ./lib/main.dart packages/mediation/gma_mediation_dtexchange/example + - name: "Unit Tests" + run: | + cd packages/mediation/gma_mediation_dtexchange/example/android + ./gradlew :gma_mediation_dtexchange:testDebugUnitTest + + iOS: + runs-on: macos-latest + timeout-minutes: 40 + steps: + - uses: swift-actions/setup-swift@v2 + with: + swift-version: "5.7.2" + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + with: + fetch-depth: 0 + - name: "Install Flutter" + run: ./.github/workflows/scripts/install-flutter.sh stable + - name: "Install Tools" + run: | + ./.github/workflows/scripts/install-tools.sh + - name: "Unit Tests" + run: | + cd packages/mediation/gma_mediation_dtexchange/example/ios + flutter clean + flutter pub get + flutter precache --ios + pod install + xcodebuild -configuration Debug -resultBundlePath TestResults VERBOSE_SCRIPT_LOGGING=YES -workspace Runner.xcworkspace -scheme Runner -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14 Pro,OS=16.2' test + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: iOSTestResults + path: packages/mediation/gma_mediation_dtexchange/example/ios/TestResults.xcresult flutter: runs-on: ubuntu-latest if: github.event_name == 'pull_request' From ca89367b9ebdd7a84cbd87be0ef3db53f717ef32 Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 21 May 2024 14:54:59 -0700 Subject: [PATCH 5/9] Updated Privacy APIs on Android plugin --- .../DTExchangePrivacyApi.g.kt | 73 +++++++++++-------- .../GmaMediationDTExchangePlugin.kt | 12 ++- .../GmaMediationDtexchangePluginTest.kt | 31 +++++--- .../lib/dtexchange_privacy_api.g.dart | 72 ++++++++++-------- .../lib/gma_mediation_dtexchange.dart | 12 ++- .../pigeons/dtexchange_privacy_api.dart | 14 ++-- .../gma_mediation_dtexchange/pubspec.yaml | 4 +- 7 files changed, 134 insertions(+), 84 deletions(-) diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt index 943651eb0..ba689dcf9 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt +++ b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangePrivacyApi.g.kt @@ -1,5 +1,6 @@ -// Autogenerated from Pigeon (v18.0.0), do not edit directly. +// Autogenerated from Pigeon (v19.0.0), do not edit directly. // See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") package io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange @@ -16,14 +17,14 @@ private fun wrapResult(result: Any?): List { } private fun wrapError(exception: Throwable): List { - if (exception is FlutterError) { - return listOf( + return if (exception is FlutterError) { + listOf( exception.code, exception.message, exception.details ) } else { - return listOf( + listOf( exception.javaClass.simpleName, exception.toString(), "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) @@ -48,12 +49,14 @@ class FlutterError ( * Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface DTExchangePrivacyApi { - /** Used to configure GDPR on the Android or iOS DTExchange SDK */ - fun setGDPRConsent(gdprConsent: Boolean) - /** Used to configure GDPR String on the Android or iOS DTExchange SDK */ - fun setGDPRConsentString(gdprConsentString: String) - /** Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK */ + /** Used to configure LGDP on the Android or iOS DTExchange SDK. */ + fun setLgpdConsent(wasConsentGiven: Boolean) + /** Used to clear the LGDP flag on the Android or iOS DTExchange SDK. */ + fun clearLgpdConsentData() + /** Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK. */ fun setUSPrivacyString(usPrivacyString: String) + /** Used to clear the US Privacy flag on the Android or iOS DTExchange SDK. */ + fun clearUSPrivacyString() companion object { /** The codec used by DTExchangePrivacyApi. */ @@ -61,21 +64,19 @@ interface DTExchangePrivacyApi { StandardMessageCodec() } /** Sets up an instance of `DTExchangePrivacyApi` to handle messages through the `binaryMessenger`. */ - @Suppress("UNCHECKED_CAST") fun setUp(binaryMessenger: BinaryMessenger, api: DTExchangePrivacyApi?, messageChannelSuffix: String = "") { val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent$separatedMessageChannelSuffix", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setLgpdConsent$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val gdprConsentArg = args[0] as Boolean - var wrapped: List - try { - api.setGDPRConsent(gdprConsentArg) - wrapped = listOf(null) + val wasConsentGivenArg = args[0] as Boolean + val wrapped: List = try { + api.setLgpdConsent(wasConsentGivenArg) + listOf(null) } catch (exception: Throwable) { - wrapped = wrapError(exception) + wrapError(exception) } reply.reply(wrapped) } @@ -84,17 +85,14 @@ interface DTExchangePrivacyApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString$separatedMessageChannelSuffix", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearLgpdConsentData$separatedMessageChannelSuffix", codec) if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val gdprConsentStringArg = args[0] as String - var wrapped: List - try { - api.setGDPRConsentString(gdprConsentStringArg) - wrapped = listOf(null) + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + api.clearLgpdConsentData() + listOf(null) } catch (exception: Throwable) { - wrapped = wrapError(exception) + wrapError(exception) } reply.reply(wrapped) } @@ -108,12 +106,27 @@ interface DTExchangePrivacyApi { channel.setMessageHandler { message, reply -> val args = message as List val usPrivacyStringArg = args[0] as String - var wrapped: List - try { + val wrapped: List = try { api.setUSPrivacyString(usPrivacyStringArg) - wrapped = listOf(null) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearUSPrivacyString$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + api.clearUSPrivacyString() + listOf(null) } catch (exception: Throwable) { - wrapped = wrapError(exception) + wrapError(exception) } reply.reply(wrapped) } diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt index 62540fd2d..d07fd5298 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt +++ b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDTExchangePlugin.kt @@ -13,15 +13,19 @@ class GmaMediationDTExchangePlugin: FlutterPlugin, DTExchangePrivacyApi { DTExchangePrivacyApi.setUp(binding.binaryMessenger, null) } - override fun setGDPRConsent(gdprConsent: Boolean) { - InneractiveAdManager.setGdprConsent(gdprConsent) + override fun setLgpdConsent(wasConsentGiven: Boolean) { + InneractiveAdManager.setLgpdConsent(wasConsentGiven) } - override fun setGDPRConsentString(gdprConsentString: String) { - InneractiveAdManager.setGdprConsentString(gdprConsentString) + override fun clearLgpdConsentData() { + InneractiveAdManager.clearLgpdConsentData() } override fun setUSPrivacyString(usPrivacyString: String) { InneractiveAdManager.setUSPrivacyString(usPrivacyString) } + + override fun clearUSPrivacyString() { + InneractiveAdManager.clearUSPrivacyString() + } } diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt b/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt index dcbf6dbba..e0a2238fc 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt +++ b/packages/mediation/gma_mediation_dtexchange/android/src/test/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/GmaMediationDtexchangePluginTest.kt @@ -10,40 +10,40 @@ import org.mockito.kotlin.eq @RunWith(AndroidJUnit4::class) internal class GmaMediationDtexchangePluginTest { @Test - fun setGDPRConsent_withTrueValue_invokesSetGdprConsentWithTrueValue() { + fun setLgpdConsent_withTrueValue_invokesSetLgpdConsentWithTrueValue() { val plugin = GmaMediationDTExchangePlugin() mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> - plugin.setGDPRConsent(true) + plugin.setLgpdConsent(true) mockedDTExchangeAdManager.verify { - InneractiveAdManager.setGdprConsent(eq(true)) + InneractiveAdManager.setLgpdConsent(eq(true)) } } } @Test - fun setGDPRConsent_withFalseValue_invokesSetGdprConsentWithFalseValue() { + fun setLgpdConsent_withFalseValue_invokesSetLgpdConsentWithFalseValue() { val plugin = GmaMediationDTExchangePlugin() mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> - plugin.setGDPRConsent(false) + plugin.setLgpdConsent(false) mockedDTExchangeAdManager.verify { - InneractiveAdManager.setGdprConsent(eq(false)) + InneractiveAdManager.setLgpdConsent(eq(false)) } } } @Test - fun setGDPRConsentString_invokesSetGdprConsentString() { + fun clearLgpdConsentData_invokesClearLgpdConsentData() { val plugin = GmaMediationDTExchangePlugin() mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> - plugin.setGDPRConsentString(TEST_CONSENT_STRING) + plugin.clearLgpdConsentData() mockedDTExchangeAdManager.verify { - InneractiveAdManager.setGdprConsentString(eq(TEST_CONSENT_STRING)) + InneractiveAdManager.clearLgpdConsentData() } } } @@ -61,6 +61,19 @@ internal class GmaMediationDtexchangePluginTest { } } + @Test + fun clearUSPrivacyString_invokesClearUSPrivacyString() { + val plugin = GmaMediationDTExchangePlugin() + mockStatic(InneractiveAdManager::class.java).use { mockedDTExchangeAdManager -> + + plugin.clearUSPrivacyString() + + mockedDTExchangeAdManager.verify { + InneractiveAdManager.clearUSPrivacyString() + } + } + } + companion object { const val TEST_CONSENT_STRING = "testConsentString" } diff --git a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart index 1adf1e40b..de99fbd49 100644 --- a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart +++ b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart @@ -1,4 +1,4 @@ -// Autogenerated from Pigeon (v18.0.0), do not edit directly. +// Autogenerated from Pigeon (v19.0.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -20,30 +20,25 @@ class DTExchangePrivacyApi { /// Constructor for [DTExchangePrivacyApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - DTExchangePrivacyApi( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + DTExchangePrivacyApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + __pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? __pigeon_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - StandardMessageCodec(); + static const MessageCodec pigeonChannelCodec = StandardMessageCodec(); final String __pigeon_messageChannelSuffix; - /// Used to configure GDPR on the Android or iOS DTExchange SDK - Future setGDPRConsent(bool gdprConsent) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( + /// Used to configure LGDP on the Android or iOS DTExchange SDK. + Future setLgpdConsent(bool wasConsentGiven) async { + final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setLgpdConsent$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, ); final List? __pigeon_replyList = - await __pigeon_channel.send([gdprConsent]) as List?; + await __pigeon_channel.send([wasConsentGiven]) as List?; if (__pigeon_replyList == null) { throw _createConnectionError(__pigeon_channelName); } else if (__pigeon_replyList.length > 1) { @@ -57,18 +52,16 @@ class DTExchangePrivacyApi { } } - /// Used to configure GDPR String on the Android or iOS DTExchange SDK - Future setGDPRConsentString(String gdprConsentString) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( + /// Used to clear the LGDP flag on the Android or iOS DTExchange SDK. + Future clearLgpdConsentData() async { + final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearLgpdConsentData$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel - .send([gdprConsentString]) as List?; + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; if (__pigeon_replyList == null) { throw _createConnectionError(__pigeon_channelName); } else if (__pigeon_replyList.length > 1) { @@ -82,18 +75,39 @@ class DTExchangePrivacyApi { } } - /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK. Future setUSPrivacyString(String usPrivacyString) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( + final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([usPrivacyString]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + /// Used to clear the US Privacy flag on the Android or iOS DTExchange SDK. + Future clearUSPrivacyString() async { + final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearUSPrivacyString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel - .send([usPrivacyString]) as List?; + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; if (__pigeon_replyList == null) { throw _createConnectionError(__pigeon_channelName); } else if (__pigeon_replyList.length > 1) { diff --git a/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart b/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart index 4862db04d..1821de350 100644 --- a/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart +++ b/packages/mediation/gma_mediation_dtexchange/lib/gma_mediation_dtexchange.dart @@ -16,15 +16,19 @@ import 'package:gma_mediation_dtexchange/dtexchange_privacy_api.g.dart'; /// This class has entrypoint to call DT Exchange's SDK APIs. class GmaMediationDTExchange { - Future setGDPRConsent(bool gdprConsent) async { - DTExchangePrivacyApi().setGDPRConsent(gdprConsent); + Future setLgpdConsent(bool wasConsentGiven) async { + DTExchangePrivacyApi().setLgpdConsent(wasConsentGiven); } - Future setGDPRConsentString(String gdprConsentString) async { - DTExchangePrivacyApi().setGDPRConsentString(gdprConsentString); + Future clearLgpdConsentData() async { + DTExchangePrivacyApi().clearLgpdConsentData(); } Future setUSPrivacyString(String usPrivacyString) async { DTExchangePrivacyApi().setUSPrivacyString(usPrivacyString); } + + Future clearUSPrivacyString() async { + DTExchangePrivacyApi().clearUSPrivacyString(); + } } diff --git a/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart index 24a6d4d37..5d314e70d 100644 --- a/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart +++ b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart @@ -30,15 +30,17 @@ import 'package:pigeon/pigeon.dart'; ), ) @HostApi() - /// The generated classes set the channels to call the methods in the corresponding kotlin DTExchangePrivacyApi interface and swift DTExchangePrivacyApi protocol from the dart layer. abstract class DTExchangePrivacyApi { - /// Used to configure GDPR on the Android or iOS DTExchange SDK - void setGDPRConsent(bool gdprConsent); + /// Used to configure LGDP on the Android or iOS DTExchange SDK. + void setLgpdConsent(bool wasConsentGiven); - /// Used to configure GDPR String on the Android or iOS DTExchange SDK - void setGDPRConsentString(String gdprConsentString); + /// Used to clear the LGDP flag on the Android or iOS DTExchange SDK. + void clearLgpdConsentData(); - /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK. void setUSPrivacyString(String usPrivacyString); + + /// Used to clear the US Privacy flag on the Android or iOS DTExchange SDK. + void clearUSPrivacyString(); } diff --git a/packages/mediation/gma_mediation_dtexchange/pubspec.yaml b/packages/mediation/gma_mediation_dtexchange/pubspec.yaml index 5570d9292..c15b9a3e3 100644 --- a/packages/mediation/gma_mediation_dtexchange/pubspec.yaml +++ b/packages/mediation/gma_mediation_dtexchange/pubspec.yaml @@ -14,11 +14,11 @@ dependencies: plugin_platform_interface: ^2.0.2 dev_dependencies: - flutter_lints: ^3.0.0 + flutter_lints: ^4.0.0 flutter_test: sdk: flutter lint: ^2.3.0 - pigeon: ^18.0.0 + pigeon: ^19.0.0 flutter: plugin: From 52cba269a184fe650bd63cd1d1315ff5f976e867 Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 21 May 2024 14:58:29 -0700 Subject: [PATCH 6/9] Format fix --- .../ios/Classes/DTExchangePrivacyApi.g.swift | 79 ++++++++++++++----- .../lib/dtexchange_privacy_api.g.dart | 41 ++++++---- .../pigeons/dtexchange_privacy_api.dart | 1 + 3 files changed, 86 insertions(+), 35 deletions(-) diff --git a/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift index 893e2534d..ef5dd6be6 100644 --- a/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift +++ b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangePrivacyApi.g.swift @@ -1,4 +1,4 @@ -// Autogenerated from Pigeon (v18.0.0), do not edit directly. +// Autogenerated from Pigeon (v19.0.0), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -11,11 +11,36 @@ import Foundation #error("Unsupported platform.") #endif +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Any? + + init(code: String, message: String?, details: Any?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + private func wrapResult(_ result: Any?) -> [Any?] { return [result] } private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } if let flutterError = error as? FlutterError { return [ flutterError.code, @@ -42,12 +67,14 @@ private func nilOrValue(_ value: Any?) -> T? { /// /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol DTExchangePrivacyApi { - /// Used to configure GDPR on the Android or iOS DTExchange SDK - func setGDPRConsent(gdprConsent: Bool) throws - /// Used to configure GDPR String on the Android or iOS DTExchange SDK - func setGDPRConsentString(gdprConsentString: String) throws - /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK + /// Used to configure LGDP on the Android or iOS DTExchange SDK. + func setLgpdConsent(wasConsentGiven: Bool) throws + /// Used to clear the LGDP flag on the Android or iOS DTExchange SDK. + func clearLgpdConsentData() throws + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK. func setUSPrivacyString(usPrivacyString: String) throws + /// Used to clear the US Privacy flag on the Android or iOS DTExchange SDK. + func clearUSPrivacyString() throws } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -56,39 +83,37 @@ class DTExchangePrivacyApiSetup { /// Sets up an instance of `DTExchangePrivacyApi` to handle messages through the `binaryMessenger`. static func setUp(binaryMessenger: FlutterBinaryMessenger, api: DTExchangePrivacyApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - /// Used to configure GDPR on the Android or iOS DTExchange SDK - let setGDPRConsentChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsent\(channelSuffix)", binaryMessenger: binaryMessenger) + /// Used to configure LGDP on the Android or iOS DTExchange SDK. + let setLgpdConsentChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setLgpdConsent\(channelSuffix)", binaryMessenger: binaryMessenger) if let api = api { - setGDPRConsentChannel.setMessageHandler { message, reply in + setLgpdConsentChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let gdprConsentArg = args[0] as! Bool + let wasConsentGivenArg = args[0] as! Bool do { - try api.setGDPRConsent(gdprConsent: gdprConsentArg) + try api.setLgpdConsent(wasConsentGiven: wasConsentGivenArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) } } } else { - setGDPRConsentChannel.setMessageHandler(nil) + setLgpdConsentChannel.setMessageHandler(nil) } - /// Used to configure GDPR String on the Android or iOS DTExchange SDK - let setGDPRConsentStringChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setGDPRConsentString\(channelSuffix)", binaryMessenger: binaryMessenger) + /// Used to clear the LGDP flag on the Android or iOS DTExchange SDK. + let clearLgpdConsentDataChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearLgpdConsentData\(channelSuffix)", binaryMessenger: binaryMessenger) if let api = api { - setGDPRConsentStringChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let gdprConsentStringArg = args[0] as! String + clearLgpdConsentDataChannel.setMessageHandler { _, reply in do { - try api.setGDPRConsentString(gdprConsentString: gdprConsentStringArg) + try api.clearLgpdConsentData() reply(wrapResult(nil)) } catch { reply(wrapError(error)) } } } else { - setGDPRConsentStringChannel.setMessageHandler(nil) + clearLgpdConsentDataChannel.setMessageHandler(nil) } - /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK + /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK. let setUSPrivacyStringChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString\(channelSuffix)", binaryMessenger: binaryMessenger) if let api = api { setUSPrivacyStringChannel.setMessageHandler { message, reply in @@ -104,5 +129,19 @@ class DTExchangePrivacyApiSetup { } else { setUSPrivacyStringChannel.setMessageHandler(nil) } + /// Used to clear the US Privacy flag on the Android or iOS DTExchange SDK. + let clearUSPrivacyStringChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearUSPrivacyString\(channelSuffix)", binaryMessenger: binaryMessenger) + if let api = api { + clearUSPrivacyStringChannel.setMessageHandler { _, reply in + do { + try api.clearUSPrivacyString() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearUSPrivacyStringChannel.setMessageHandler(nil) + } } } diff --git a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart index de99fbd49..19917f254 100644 --- a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart +++ b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_privacy_api.g.dart @@ -20,25 +20,30 @@ class DTExchangePrivacyApi { /// Constructor for [DTExchangePrivacyApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - DTExchangePrivacyApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + DTExchangePrivacyApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + __pigeon_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? __pigeon_binaryMessenger; - static const MessageCodec pigeonChannelCodec = StandardMessageCodec(); + static const MessageCodec pigeonChannelCodec = + StandardMessageCodec(); final String __pigeon_messageChannelSuffix; /// Used to configure LGDP on the Android or iOS DTExchange SDK. Future setLgpdConsent(bool wasConsentGiven) async { - final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setLgpdConsent$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + final String __pigeon_channelName = + 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setLgpdConsent$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([wasConsentGiven]) as List?; + final List? __pigeon_replyList = await __pigeon_channel + .send([wasConsentGiven]) as List?; if (__pigeon_replyList == null) { throw _createConnectionError(__pigeon_channelName); } else if (__pigeon_replyList.length > 1) { @@ -54,8 +59,10 @@ class DTExchangePrivacyApi { /// Used to clear the LGDP flag on the Android or iOS DTExchange SDK. Future clearLgpdConsentData() async { - final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearLgpdConsentData$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + final String __pigeon_channelName = + 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearLgpdConsentData$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, @@ -77,14 +84,16 @@ class DTExchangePrivacyApi { /// Used to configure consent to Sell Personal Information on the Android or iOS DTExchange SDK. Future setUSPrivacyString(String usPrivacyString) async { - final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + final String __pigeon_channelName = + 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.setUSPrivacyString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([usPrivacyString]) as List?; + final List? __pigeon_replyList = await __pigeon_channel + .send([usPrivacyString]) as List?; if (__pigeon_replyList == null) { throw _createConnectionError(__pigeon_channelName); } else if (__pigeon_replyList.length > 1) { @@ -100,8 +109,10 @@ class DTExchangePrivacyApi { /// Used to clear the US Privacy flag on the Android or iOS DTExchange SDK. Future clearUSPrivacyString() async { - final String __pigeon_channelName = 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearUSPrivacyString$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + final String __pigeon_channelName = + 'dev.flutter.pigeon.gma_mediation_dtexchange.DTExchangePrivacyApi.clearUSPrivacyString$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( __pigeon_channelName, pigeonChannelCodec, binaryMessenger: __pigeon_binaryMessenger, diff --git a/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart index 5d314e70d..1344795d0 100644 --- a/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart +++ b/packages/mediation/gma_mediation_dtexchange/pigeons/dtexchange_privacy_api.dart @@ -30,6 +30,7 @@ import 'package:pigeon/pigeon.dart'; ), ) @HostApi() + /// The generated classes set the channels to call the methods in the corresponding kotlin DTExchangePrivacyApi interface and swift DTExchangePrivacyApi protocol from the dart layer. abstract class DTExchangePrivacyApi { /// Used to configure LGDP on the Android or iOS DTExchange SDK. From 8a8e37682ab0963f83820ad07e72a8befc6fb0db Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 21 May 2024 15:00:55 -0700 Subject: [PATCH 7/9] Added detachFromEngine method --- .../ios/Classes/GmaMediationDTExchangePlugin.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift b/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift index 1dc8f7439..77f0504b8 100644 --- a/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift +++ b/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift @@ -15,6 +15,10 @@ public class GmaMediationDTExchangePlugin: NSObject, FlutterPlugin, DTExchangePr let api : DTExchangePrivacyApi&NSObjectProtocol=GmaMediationDTExchangePlugin.init(dtExchangeApi: DTExchangePrivacyImpl()) DTExchangePrivacyApiSetup.setUp(binaryMessenger: messenger, api: api) } + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + let messenger : FlutterBinaryMessenger = registrar.messenger() + DTExchangePrivacyApiSetup.setUp(binaryMessenger: messenger, api: nil) + } func setGDPRConsent(gdprConsent: Bool) throws { dtExchangeApi.setGDPRConsent(gdprConsent: gdprConsent) From be657667cb59d1cadabfba20a5be0269ca4b2b5a Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 21 May 2024 15:32:55 -0700 Subject: [PATCH 8/9] Updated Privacy API on iOS plugin --- .../ios/Runner.xcodeproj/project.pbxproj | 95 +++++++++++++++++++ .../GmaMediationDtexchangePluginTests.swift | 51 ++++++---- .../GmaMediationDTExchangePlugin.swift | 32 ++++--- 3 files changed, 151 insertions(+), 27 deletions(-) diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj b/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj index d28ca38f1..9ba859137 100644 --- a/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/Runner.xcodeproj/project.pbxproj @@ -11,9 +11,11 @@ 331C808B294A63AB00263BE5 /* GmaMediationDtexchangePluginTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* GmaMediationDtexchangePluginTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 7ED3FF60DFA5AF8AFF6AB4C8 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E92C8C6658B2F16CF151B264 /* libPods-Runner.a */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + B7373BCFDC6F242653274BD8 /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0FE6932FC6A221D2A065BA19 /* libPods-RunnerTests.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,6 +42,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0FE6932FC6A221D2A065BA19 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 331C807B294A618700263BE5 /* GmaMediationDtexchangePluginTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GmaMediationDtexchangePluginTests.swift; sourceTree = ""; }; @@ -47,6 +50,7 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7890833C8A06A38A9C6B8346 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -55,6 +59,12 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9B3AD38CDF99309487DCE609 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + DD3DB214A5A7FC659D11247C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + E6B8122A81F4D5FEF3259BB4 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + E92C8C6658B2F16CF151B264 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + EEF3DFF0CD2042A5E4AA0DCA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F8929DB9C0880FE085C306CE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,6 +72,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B7373BCFDC6F242653274BD8 /* libPods-RunnerTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -69,6 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7ED3FF60DFA5AF8AFF6AB4C8 /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -83,9 +95,24 @@ path = RunnerTests; sourceTree = ""; }; + 477D1DB2ED00F2BF4C86A6A4 /* Frameworks */ = { + isa = PBXGroup; + children = ( + E92C8C6658B2F16CF151B264 /* libPods-Runner.a */, + 0FE6932FC6A221D2A065BA19 /* libPods-RunnerTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 7F5876306538D9102F2D1064 /* Pods */ = { isa = PBXGroup; children = ( + F8929DB9C0880FE085C306CE /* Pods-Runner.debug.xcconfig */, + 7890833C8A06A38A9C6B8346 /* Pods-Runner.release.xcconfig */, + 9B3AD38CDF99309487DCE609 /* Pods-Runner.profile.xcconfig */, + EEF3DFF0CD2042A5E4AA0DCA /* Pods-RunnerTests.debug.xcconfig */, + DD3DB214A5A7FC659D11247C /* Pods-RunnerTests.release.xcconfig */, + E6B8122A81F4D5FEF3259BB4 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -109,6 +136,7 @@ 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, 7F5876306538D9102F2D1064 /* Pods */, + 477D1DB2ED00F2BF4C86A6A4 /* Frameworks */, ); sourceTree = ""; }; @@ -143,6 +171,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 1BA28C831D9FE41B481A5CD7 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, 7479BD3A993BCA69DD5BAE53 /* Frameworks */, @@ -161,12 +190,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + FF8E996C495CEC35947A4FF9 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 835FC7364862FD04126FFAAF /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -238,6 +269,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 1BA28C831D9FE41B481A5CD7 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -254,6 +307,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 835FC7364862FD04126FFAAF /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -269,6 +339,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + FF8E996C495CEC35947A4FF9 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -394,6 +486,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = EEF3DFF0CD2042A5E4AA0DCA /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +504,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DD3DB214A5A7FC659D11247C /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -426,6 +520,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = E6B8122A81F4D5FEF3259BB4 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift b/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift index 2b090970f..bfe8262a1 100644 --- a/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift +++ b/packages/mediation/gma_mediation_dtexchange/example/ios/RunnerTests/GmaMediationDtexchangePluginTests.swift @@ -4,30 +4,30 @@ import XCTest @testable import gma_mediation_dtexchange class GmaMediationDtexchangePluginTests: XCTestCase { - func testSetGDPRConsent() { + func testSetLgpdConsent() { let dtExchangeFake = DTExchangePrivacyFake() let plugin = GmaMediationDTExchangePlugin.init(dtExchangeApi: dtExchangeFake) do { - try plugin.setGDPRConsent(gdprConsent: true) + try plugin.setLgpdConsent(wasConsentGiven: true) } catch { - fatalError("testSetGDPRConsent FAILED: setGDPRConsent did not complete.") + fatalError("testSetLgpdConsent FAILED: setLgpdConsent did not complete.") } - XCTAssertEqual(dtExchangeFake.gdprConsent, true) + XCTAssertEqual(dtExchangeFake.lgdpConsent, true) } - func testSetGDPRConsentString() { + func testClearLgpdConsentData() { let dtExchangeFake = DTExchangePrivacyFake() let plugin = GmaMediationDTExchangePlugin.init(dtExchangeApi: dtExchangeFake) do { - try plugin.setGDPRConsentString(gdprConsentString: "testString") + try plugin.clearLgpdConsentData() } catch { - fatalError("testSetGDPRConsentString FAILED: setGDPRConsentString did not complete.") + fatalError("testClearLgpdConsentData FAILED: clearLgpdConsentData did not complete.") } - XCTAssertEqual(dtExchangeFake.gdprString, "testString") + XCTAssertEqual(dtExchangeFake.clearLgdp, 1) } func testSetUSPrivacyString() { @@ -42,28 +42,47 @@ class GmaMediationDtexchangePluginTests: XCTestCase { XCTAssertEqual(dtExchangeFake.usPrivacyString, "testString") } + + func testClearUSPrivacyString() { + let dtExchangeFake = DTExchangePrivacyFake() + let plugin = GmaMediationDTExchangePlugin.init(dtExchangeApi: dtExchangeFake) + + do { + try plugin.clearUSPrivacyString() + } catch { + fatalError("testClearUSPrivacyString FAILED: clearUSPrivacyString did not complete.") + } + + XCTAssertEqual(dtExchangeFake.clearUSPrivacy, 1) + } } class DTExchangePrivacyFake : DTExchangePrivacyProtocol { - var gdprConsent: Bool - var gdprString: String + var lgdpConsent: Bool + var clearLgdp: Int var usPrivacyString: String + var clearUSPrivacy: Int init() { - gdprConsent = false - gdprString = "" + lgdpConsent = false + clearLgdp = 0 usPrivacyString = "" + clearUSPrivacy = 0 } - func setGDPRConsent(gdprConsent: Bool) { - self.gdprConsent = gdprConsent + func setLgpdConsent(wasConsentGiven: Bool) { + self.lgdpConsent = wasConsentGiven } - func setGDPRConsentString(gdprConsentString: String) { - self.gdprString = gdprConsentString + func clearLgpdConsentData() { + self.clearLgdp += 1 } func setUSPrivacyString(usPrivacyString: String) { self.usPrivacyString = usPrivacyString } + + func clearUSPrivacyString() { + self.clearUSPrivacy += 1 + } } diff --git a/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift b/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift index 77f0504b8..11671ac31 100644 --- a/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift +++ b/packages/mediation/gma_mediation_dtexchange/ios/Classes/GmaMediationDTExchangePlugin.swift @@ -20,37 +20,47 @@ public class GmaMediationDTExchangePlugin: NSObject, FlutterPlugin, DTExchangePr DTExchangePrivacyApiSetup.setUp(binaryMessenger: messenger, api: nil) } - func setGDPRConsent(gdprConsent: Bool) throws { - dtExchangeApi.setGDPRConsent(gdprConsent: gdprConsent) + func setLgpdConsent(wasConsentGiven: Bool) throws { + dtExchangeApi.setLgpdConsent(wasConsentGiven: wasConsentGiven) } - func setGDPRConsentString(gdprConsentString: String) throws { - dtExchangeApi.setGDPRConsentString(gdprConsentString: gdprConsentString) + func clearLgpdConsentData() throws { + dtExchangeApi.clearLgpdConsentData() } func setUSPrivacyString(usPrivacyString: String) throws { dtExchangeApi.setUSPrivacyString(usPrivacyString: usPrivacyString) } + + func clearUSPrivacyString() throws { + dtExchangeApi.clearUSPrivacyString() + } } protocol DTExchangePrivacyProtocol { - func setGDPRConsent(gdprConsent: Bool) + func setLgpdConsent(wasConsentGiven: Bool) - func setGDPRConsentString(gdprConsentString: String) + func clearLgpdConsentData() func setUSPrivacyString(usPrivacyString: String) + + func clearUSPrivacyString() } class DTExchangePrivacyImpl : DTExchangePrivacyProtocol { - func setGDPRConsent(gdprConsent: Bool) { - IASDKCore.sharedInstance().gdprConsent = gdprConsent ? IAGDPRConsentType.given : IAGDPRConsentType.denied + func setLgpdConsent(wasConsentGiven: Bool) { + IASDKCore.sharedInstance().lgpdConsent = wasConsentGiven ? IALGPDConsentType.given : IALGPDConsentType.denied } - func setGDPRConsentString(gdprConsentString: String) { - IASDKCore.sharedInstance().gdprConsentString = gdprConsentString + func clearLgpdConsentData() { + IASDKCore.sharedInstance().clearLGPDConsentData() } - + func setUSPrivacyString(usPrivacyString: String) { IASDKCore.sharedInstance().ccpaString = usPrivacyString } + + func clearUSPrivacyString() { + IASDKCore.sharedInstance().ccpaString = nil + } } From 5571f113a3cdec7467917a501d69467f47cd1e07 Mon Sep 17 00:00:00 2001 From: Aldo Becerril Date: Tue, 21 May 2024 15:39:15 -0700 Subject: [PATCH 9/9] Updated iOS versions to run swift tests --- .github/workflows/gma_mediation_dtexchange.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gma_mediation_dtexchange.yaml b/.github/workflows/gma_mediation_dtexchange.yaml index 75284ef6c..f2ad16083 100644 --- a/.github/workflows/gma_mediation_dtexchange.yaml +++ b/.github/workflows/gma_mediation_dtexchange.yaml @@ -71,7 +71,7 @@ jobs: flutter pub get flutter precache --ios pod install - xcodebuild -configuration Debug -resultBundlePath TestResults VERBOSE_SCRIPT_LOGGING=YES -workspace Runner.xcworkspace -scheme Runner -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14 Pro,OS=16.2' test + xcodebuild -configuration Debug -resultBundlePath TestResults VERBOSE_SCRIPT_LOGGING=YES -workspace Runner.xcworkspace -scheme Runner -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' test - uses: actions/upload-artifact@v4 if: failure() with: