diff --git a/packages/mediation/gma_mediation_dtexchange/android/build.gradle b/packages/mediation/gma_mediation_dtexchange/android/build.gradle index 908f4aa32..c8571dd26 100644 --- a/packages/mediation/gma_mediation_dtexchange/android/build.gradle +++ b/packages/mediation/gma_mediation_dtexchange/android/build.gradle @@ -50,7 +50,8 @@ android { } dependencies { - implementation 'com.google.ads.mediation:fyber:8.2.6.1' + implementation 'com.google.ads.mediation:fyber:8.2.7.0' + implementation 'androidx.core:core-ktx:1.8.0' testImplementation 'org.jetbrains.kotlin:kotlin-test' testImplementation 'org.mockito:mockito-core:5.0.0' } diff --git a/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangeFlutterMediationExtras.kt b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangeFlutterMediationExtras.kt new file mode 100644 index 000000000..b03fe310c --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/android/src/main/kotlin/io/flutter/plugins/googlemobileads/mediation/gma_mediation_dtexchange/DTExchangeFlutterMediationExtras.kt @@ -0,0 +1,54 @@ +// 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. + +package io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange + +import android.os.Bundle +import android.util.Pair +import androidx.core.os.bundleOf +import com.fyber.inneractive.sdk.external.InneractiveMediationDefs +import com.google.ads.mediation.fyber.FyberMediationAdapter +// import com.google.ads.mediation.fyber.FyberMediationAdapter.KEY_MUTE_VIDEO +import com.google.android.gms.ads.mediation.MediationExtrasReceiver +import io.flutter.plugins.googlemobileads.FlutterMediationExtras + +class DTExchangeFlutterMediationExtras : FlutterMediationExtras() { + private var flutterExtras: Map? = null + + override fun setMediationExtras(extras: MutableMap?) { + flutterExtras = extras + } + override fun getMediationExtras(): Pair, Bundle> { + val extrasMap = flutterExtras + if (extrasMap == null) { + return Pair, Bundle>(FyberMediationAdapter::class.java, bundleOf()) + } + val extrasBundle = bundleOf() + val muteVideo = extrasMap[MUTE_VIDEO] + if (muteVideo is Boolean) { + // extrasBundle.putBoolean(KEY_MUTE_VIDEO, muteVideo) + extrasBundle.putBoolean(MUTE_VIDEO, muteVideo) + } + val age = extrasMap[AGE] + if (age is Int) { + extrasBundle.putInt(InneractiveMediationDefs.KEY_AGE, age) + } + return Pair, Bundle>(FyberMediationAdapter::class.java, extrasBundle) + } + + companion object { + private const val MUTE_VIDEO = "muteVideo" + private const val AGE = "age" + } +} \ No newline at end of file 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/ios/Classes/DTExchangeFlutterMediationExtras.swift b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangeFlutterMediationExtras.swift new file mode 100644 index 000000000..bca0bfe87 --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/ios/Classes/DTExchangeFlutterMediationExtras.swift @@ -0,0 +1,57 @@ +// 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 Foundation +import DTExchangeAdapter + +@objc protocol FLTMediationExtras { + var extras: NSMutableDictionary { get } + func getMediationExtras() -> GADAdNetworkExtras +} + +@objc(DTExchangeFlutterMediationExtras) +class DTExchangeFlutterMediationExtras : NSObject, FLTMediationExtras { + var extras: NSMutableDictionary = [:] + + func getMediationExtras() -> GADAdNetworkExtras { + let fyberExtras = GADMAdapterFyberExtras() + if let muteVideo = extras["muteVideo"] as? Bool { + fyberExtras.muteAudio = muteVideo + } + if (extras["age"] != nil || extras["gender"] != nil || extras["zipCode"] != nil) { + let userData = IAUserData.build({ builder in + if let age = self.extras["age"] as? UInt { + builder.age = age + } + if let gender = self.extras["gender"] as? UInt { + switch gender { + case 1: + builder.gender = IAUserGenderType.male + case 2: + builder.gender = IAUserGenderType.female + case 3: + builder.gender = IAUserGenderType.other + default: + builder.gender = IAUserGenderType.unknown + } + } + if let zipCode = self.extras["zipCode"] as? String { + builder.zipCode = zipCode + } + }) + fyberExtras.userData = userData + } + return fyberExtras + } +} diff --git a/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_mediation_extras.dart b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_mediation_extras.dart new file mode 100644 index 000000000..763bfe320 --- /dev/null +++ b/packages/mediation/gma_mediation_dtexchange/lib/dtexchange_mediation_extras.dart @@ -0,0 +1,60 @@ +// 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:google_mobile_ads/google_mobile_ads.dart'; + +/// Class with additional parameters to attach to the [AdRequest] or [AdManagerAdRequest] when using the [GmaMediationDTExchange] adapter. +class DTExchangeMediationExtras implements MediationExtras { + DTExchangeMediationExtras({ + this.muteVideo, + this.age, + this.gender, + this.zipCode, + }); + + bool? muteVideo; + int? age; + DTEUserGenderType? gender; + String? zipCode; + + @override + String getAndroidClassName() { + return "io.flutter.plugins.googlemobileads.mediation.gma_mediation_dtexchange.DTExchangeFlutterMediationExtras"; + } + + @override + String getIOSClassName() { + return "DTExchangeFlutterMediationExtras"; + } + + @override + Map getExtras() { + return { + "muteVideo": muteVideo, + "age": age, + "gender": gender?.intValue, + "zipCode": zipCode, + }; + } +} + +/// Available gender types to be send on the User Data. Only used by iOS adapter. +enum DTEUserGenderType { + unknown, + male, + female, + other; + + int get intValue => index; +}