From 46a712f38301ca20178ba01ec19af68d80cdcaea Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 30 Jul 2024 20:44:37 -0600 Subject: [PATCH] [interactive_media_ads] Adds initial iOS implementation (#7063) iOS implementation for https://github.com/flutter/flutter/issues/134228 --- packages/interactive_media_ads/CHANGELOG.md | 5 + .../AdsRequestProxyApi.kt | 6 +- .../AdsRequestProxyApiTest.kt | 4 +- .../ios/Runner.xcodeproj/project.pbxproj | 171 +- .../contents.xcworkspacedata | 3 + .../example/ios/Runner/AppDelegate.swift | 2 +- .../RunnerTests/AdDisplayContainerTests.swift | 20 + .../ios/RunnerTests/AdErrorTests.swift | 65 + .../ios/RunnerTests/AdEventTests.swift | 50 + .../RunnerTests/AdLoadingErrorDataTests.swift | 36 + .../ios/RunnerTests/AdsLoadedDataTests.swift | 36 + .../RunnerTests/AdsLoaderDelegateTests.swift | 63 + .../ios/RunnerTests/AdsLoaderTests.swift | 82 + .../RunnerTests/AdsManagerDelegateTests.swift | 101 + .../ios/RunnerTests/AdsManagerTests.swift | 149 + .../AdsRenderingSettingsTests.swift | 21 + .../ios/RunnerTests/AdsRequestTests.swift | 28 + .../RunnerTests/ContentPlayheadTests.swift | 32 + .../example/ios/RunnerTests/RunnerTests.swift | 30 - .../RunnerTests/TestProxyApiRegistrar.swift | 37 + .../ios/RunnerTests/ViewControllerTests.swift | 50 + .../example/lib/main.dart | 11 +- .../ios/interactive_media_ads.podspec | 1 + .../ios/interactive_media_ads/Package.swift | 12 +- .../AdDisplayContainerProxyAPIDelegate.swift | 20 + .../AdErrorProxyAPIDelegate.swift | 84 + .../AdEventProxyAPIDelegate.swift | 71 + .../AdLoadingErrorDataProxyAPIDelegate.swift | 18 + .../AdsLoadedDataProxyAPIDelegate.swift | 18 + .../AdsLoaderDelegateProxyAPIDelegate.swift | 38 + .../AdsLoaderProxyAPIDelegate.swift | 34 + .../AdsManagerDelegateProxyAPIDelegate.swift | 43 + .../AdsManagerProxyAPIDelegate.swift | 50 + ...AdsRenderingSettingsProxyAPIDelegate.swift | 18 + .../AdsRequestProxyAPIDelegate.swift | 32 + .../ContentPlayheadProxyAPIDelegate.swift | 29 + .../FlutterViewFactory.swift | 45 + .../InteractiveMediaAdsLibrary.g.swift | 2893 ++++++++++++++++ .../InteractiveMediaAdsPlugin.swift | 27 +- .../ProxyApiDelegate.swift | 112 + .../ViewControllerProxyAPIDelegate.swift | 38 + .../ViewProxyAPIDelegate.swift | 16 + .../lib/interactive_media_ads.dart | 1 + .../lib/src/ad_display_container.dart | 5 + .../android/android_ad_display_container.dart | 1 + .../lib/src/android/android_ads_loader.dart | 6 +- .../lib/src/android/android_ads_manager.dart | 9 +- .../lib/src/android/android_view_widget.dart | 11 +- .../android/enum_converter_extensions.dart | 85 - .../lib/src/android/enum_converter_utils.dart | 69 + .../lib/src/ios/enum_converter_utils.dart | 64 + .../lib/src/ios/interactive_media_ads.g.dart | 3051 +++++++++++++++++ .../src/ios/interactive_media_ads_proxy.dart | 71 + .../lib/src/ios/ios_ad_display_container.dart | 104 + .../lib/src/ios/ios_ads_loader.dart | 110 + .../lib/src/ios/ios_ads_manager.dart | 51 + .../lib/src/ios/ios_ads_manager_delegate.dart | 98 + .../src/ios/ios_interactive_media_ads.dart | 38 + .../platform_ad_display_container.dart | 4 + .../pigeons/interactive_media_ads_ios.dart | 508 +++ packages/interactive_media_ads/pubspec.yaml | 5 +- .../test/ios/ad_display_container_test.dart | 94 + .../ios/ad_display_container_test.mocks.dart | 198 ++ .../test/ios/ads_loader_test.dart | 248 ++ .../test/ios/ads_loader_test.mocks.dart | 523 +++ .../test/ios/ads_manager_delegate_tests.dart | 267 ++ .../test/ios/ads_manager_tests.dart | 86 + .../test/ios/ads_manager_tests.mocks.dart | 127 + .../test/version_test.dart | 30 +- 69 files changed, 10301 insertions(+), 164 deletions(-) create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdDisplayContainerTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdErrorTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdEventTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdLoadingErrorDataTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdsLoadedDataTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderDelegateTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerDelegateTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdsRenderingSettingsTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/AdsRequestTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/ContentPlayheadTests.swift delete mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/RunnerTests.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/TestProxyApiRegistrar.swift create mode 100644 packages/interactive_media_ads/example/ios/RunnerTests/ViewControllerTests.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdDisplayContainerProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdErrorProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdEventProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdLoadingErrorDataProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoadedDataProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderDelegateProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerDelegateProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRenderingSettingsProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ContentPlayheadProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/FlutterViewFactory.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsLibrary.g.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ProxyApiDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewControllerProxyAPIDelegate.swift create mode 100644 packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewProxyAPIDelegate.swift delete mode 100644 packages/interactive_media_ads/lib/src/android/enum_converter_extensions.dart create mode 100644 packages/interactive_media_ads/lib/src/android/enum_converter_utils.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/enum_converter_utils.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/interactive_media_ads.g.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/interactive_media_ads_proxy.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/ios_ad_display_container.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/ios_ads_loader.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/ios_ads_manager.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/ios_ads_manager_delegate.dart create mode 100644 packages/interactive_media_ads/lib/src/ios/ios_interactive_media_ads.dart create mode 100644 packages/interactive_media_ads/pigeons/interactive_media_ads_ios.dart create mode 100644 packages/interactive_media_ads/test/ios/ad_display_container_test.dart create mode 100644 packages/interactive_media_ads/test/ios/ad_display_container_test.mocks.dart create mode 100644 packages/interactive_media_ads/test/ios/ads_loader_test.dart create mode 100644 packages/interactive_media_ads/test/ios/ads_loader_test.mocks.dart create mode 100644 packages/interactive_media_ads/test/ios/ads_manager_delegate_tests.dart create mode 100644 packages/interactive_media_ads/test/ios/ads_manager_tests.dart create mode 100644 packages/interactive_media_ads/test/ios/ads_manager_tests.mocks.dart diff --git a/packages/interactive_media_ads/CHANGELOG.md b/packages/interactive_media_ads/CHANGELOG.md index 75bde2001d9ef..dc9a3bf59a8b1 100644 --- a/packages/interactive_media_ads/CHANGELOG.md +++ b/packages/interactive_media_ads/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.1.1 + +* Adds iOS implementation. +* Adds support for setting the layout direction of the `AdDisplayContainer`. + ## 0.1.0+2 * Bumps androidx.annotation:annotation from 1.7.1 to 1.8.1. diff --git a/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt index a1cd312bcc985..639048631bfe3 100644 --- a/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt +++ b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt @@ -21,10 +21,14 @@ class AdsRequestProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : * * This must match the version in pubspec.yaml. */ - const val pluginVersion = "0.1.0+2" + const val pluginVersion = "0.1.1" } override fun setAdTagUrl(pigeon_instance: AdsRequest, adTagUrl: String) { + // Ensure adTag can append a custom parameter. + require(adTagUrl.contains("?")) + require(!adTagUrl.contains("#")) + pigeon_instance.adTagUrl = "$adTagUrl&request_agent=Flutter-IMA-$pluginVersion" } diff --git a/packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApiTest.kt b/packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApiTest.kt index 66c3d35ee555c..42f0cc88b84e5 100644 --- a/packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApiTest.kt +++ b/packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApiTest.kt @@ -16,10 +16,10 @@ class AdsRequestProxyApiTest { val api = TestProxyApiRegistrar().getPigeonApiAdsRequest() val instance = mock() - api.setAdTagUrl(instance, "adTag") + api.setAdTagUrl(instance, "adTag?") verify(instance).adTagUrl = - "adTag&request_agent=Flutter-IMA-${AdsRequestProxyApi.pluginVersion}" + "adTag?&request_agent=Flutter-IMA-${AdsRequestProxyApi.pluginVersion}" } @Test diff --git a/packages/interactive_media_ads/example/ios/Runner.xcodeproj/project.pbxproj b/packages/interactive_media_ads/example/ios/Runner.xcodeproj/project.pbxproj index 966e3a40fea77..65f90052507b4 100644 --- a/packages/interactive_media_ads/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/interactive_media_ads/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,9 +8,24 @@ /* 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 */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3D282E63E10407DBACF20FD6 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 544903031C10E0FA3D89D2CE /* Pods_RunnerTests.framework */; }; + 4E107A500F4C07EF26C07FFF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDCBAC040E6F614A1CDCF896 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 8F599BB12C2DD1FD0090A0DF /* AdsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BB02C2DD1FD0090A0DF /* AdsManagerTests.swift */; }; + 8F599BB32C2DD87D0090A0DF /* AdsLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BB22C2DD87D0090A0DF /* AdsLoaderTests.swift */; }; + 8F599BB52C2DD8EC0090A0DF /* AdsLoaderDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BB42C2DD8EC0090A0DF /* AdsLoaderDelegateTests.swift */; }; + 8F599BB72C3327F10090A0DF /* AdsManagerDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BB62C3327F10090A0DF /* AdsManagerDelegateTests.swift */; }; + 8F599BB92C332A320090A0DF /* AdsRenderingSettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BB82C332A320090A0DF /* AdsRenderingSettingsTests.swift */; }; + 8F599BBB2C332C010090A0DF /* AdsRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BBA2C332C010090A0DF /* AdsRequestTests.swift */; }; + 8F599BBD2C332CFE0090A0DF /* ContentPlayheadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BBC2C332CFE0090A0DF /* ContentPlayheadTests.swift */; }; + 8F599BBF2C3335B40090A0DF /* ViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F599BBE2C3335B40090A0DF /* ViewControllerTests.swift */; }; + 8F977DCF2C2B99C600A90D4B /* AdDisplayContainerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F977DCE2C2B99C600A90D4B /* AdDisplayContainerTests.swift */; }; + 8F977DD32C2BA15100A90D4B /* TestProxyApiRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F977DD22C2BA15100A90D4B /* TestProxyApiRegistrar.swift */; }; + 8F977DD52C2C777600A90D4B /* AdErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F977DD42C2C777600A90D4B /* AdErrorTests.swift */; }; + 8F977DD72C2C89A600A90D4B /* AdEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F977DD62C2C89A600A90D4B /* AdEventTests.swift */; }; + 8F977DD92C2C8C6A00A90D4B /* AdLoadingErrorDataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F977DD82C2C8C6A00A90D4B /* AdLoadingErrorDataTests.swift */; }; + 8F977DDB2C2C8D2E00A90D4B /* AdsLoadedDataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F977DDA2C2C8D2E00A90D4B /* AdsLoadedDataTests.swift */; }; 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 */; }; @@ -42,12 +57,32 @@ /* 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 = ""; }; + 153699881E6FE1D0B5372678 /* 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 = ""; }; 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 = ""; }; + 41604FD1E0DA824F933934B2 /* 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 = ""; }; + 465840C2278A5FCA3EA77E43 /* 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 = ""; }; + 544903031C10E0FA3D89D2CE /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5B63D978173E0F79E02D7128 /* 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 = ""; }; 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 = ""; }; + 7A0E5CD036C0A19847922937 /* 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 = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 89C6230E68C80A6F4B207726 /* 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 = ""; }; + 8F599BB02C2DD1FD0090A0DF /* AdsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsManagerTests.swift; sourceTree = ""; }; + 8F599BB22C2DD87D0090A0DF /* AdsLoaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsLoaderTests.swift; sourceTree = ""; }; + 8F599BB42C2DD8EC0090A0DF /* AdsLoaderDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsLoaderDelegateTests.swift; sourceTree = ""; }; + 8F599BB62C3327F10090A0DF /* AdsManagerDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsManagerDelegateTests.swift; sourceTree = ""; }; + 8F599BB82C332A320090A0DF /* AdsRenderingSettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsRenderingSettingsTests.swift; sourceTree = ""; }; + 8F599BBA2C332C010090A0DF /* AdsRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsRequestTests.swift; sourceTree = ""; }; + 8F599BBC2C332CFE0090A0DF /* ContentPlayheadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentPlayheadTests.swift; sourceTree = ""; }; + 8F599BBE2C3335B40090A0DF /* ViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerTests.swift; sourceTree = ""; }; + 8F977DCE2C2B99C600A90D4B /* AdDisplayContainerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdDisplayContainerTests.swift; sourceTree = ""; }; + 8F977DD22C2BA15100A90D4B /* TestProxyApiRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProxyApiRegistrar.swift; sourceTree = ""; }; + 8F977DD42C2C777600A90D4B /* AdErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdErrorTests.swift; sourceTree = ""; }; + 8F977DD62C2C89A600A90D4B /* AdEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdEventTests.swift; sourceTree = ""; }; + 8F977DD82C2C8C6A00A90D4B /* AdLoadingErrorDataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdLoadingErrorDataTests.swift; sourceTree = ""; }; + 8F977DDA2C2C8D2E00A90D4B /* AdsLoadedDataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsLoadedDataTests.swift; 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 = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -55,13 +90,23 @@ 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 = ""; }; + DDCBAC040E6F614A1CDCF896 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 3BE96F44453EDBDD7D23B8A5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D282E63E10407DBACF20FD6 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 4E107A500F4C07EF26C07FFF /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -71,7 +116,20 @@ 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, + 8F977DCE2C2B99C600A90D4B /* AdDisplayContainerTests.swift */, + 8F977DD22C2BA15100A90D4B /* TestProxyApiRegistrar.swift */, + 8F977DD42C2C777600A90D4B /* AdErrorTests.swift */, + 8F977DD62C2C89A600A90D4B /* AdEventTests.swift */, + 8F977DD82C2C8C6A00A90D4B /* AdLoadingErrorDataTests.swift */, + 8F977DDA2C2C8D2E00A90D4B /* AdsLoadedDataTests.swift */, + 8F599BB02C2DD1FD0090A0DF /* AdsManagerTests.swift */, + 8F599BB22C2DD87D0090A0DF /* AdsLoaderTests.swift */, + 8F599BB42C2DD8EC0090A0DF /* AdsLoaderDelegateTests.swift */, + 8F599BB62C3327F10090A0DF /* AdsManagerDelegateTests.swift */, + 8F599BB82C332A320090A0DF /* AdsRenderingSettingsTests.swift */, + 8F599BBA2C332C010090A0DF /* AdsRequestTests.swift */, + 8F599BBC2C332CFE0090A0DF /* ContentPlayheadTests.swift */, + 8F599BBE2C3335B40090A0DF /* ViewControllerTests.swift */, ); path = RunnerTests; sourceTree = ""; @@ -94,6 +152,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + AF32999759207BFF55E206F8 /* Pods */, + A4081A23792594E766916ABA /* Frameworks */, ); sourceTree = ""; }; @@ -121,6 +181,28 @@ path = Runner; sourceTree = ""; }; + A4081A23792594E766916ABA /* Frameworks */ = { + isa = PBXGroup; + children = ( + DDCBAC040E6F614A1CDCF896 /* Pods_Runner.framework */, + 544903031C10E0FA3D89D2CE /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + AF32999759207BFF55E206F8 /* Pods */ = { + isa = PBXGroup; + children = ( + 7A0E5CD036C0A19847922937 /* Pods-Runner.debug.xcconfig */, + 465840C2278A5FCA3EA77E43 /* Pods-Runner.release.xcconfig */, + 153699881E6FE1D0B5372678 /* Pods-Runner.profile.xcconfig */, + 89C6230E68C80A6F4B207726 /* Pods-RunnerTests.debug.xcconfig */, + 5B63D978173E0F79E02D7128 /* Pods-RunnerTests.release.xcconfig */, + 41604FD1E0DA824F933934B2 /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -128,8 +210,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 021D2273D927B5073948A888 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + 3BE96F44453EDBDD7D23B8A5 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +229,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 8BF613E92E45E672229E9718 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + F9AB3D76E1CFC93475F15A54 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -222,6 +308,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 021D2273D927B5073948A888 /* [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; @@ -238,6 +346,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 8BF613E92E45E672229E9718 /* [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; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +383,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + F9AB3D76E1CFC93475F15A54 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -260,7 +407,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + 8F599BBF2C3335B40090A0DF /* ViewControllerTests.swift in Sources */, + 8F977DD92C2C8C6A00A90D4B /* AdLoadingErrorDataTests.swift in Sources */, + 8F599BB32C2DD87D0090A0DF /* AdsLoaderTests.swift in Sources */, + 8F977DD72C2C89A600A90D4B /* AdEventTests.swift in Sources */, + 8F977DD32C2BA15100A90D4B /* TestProxyApiRegistrar.swift in Sources */, + 8F599BBB2C332C010090A0DF /* AdsRequestTests.swift in Sources */, + 8F599BB72C3327F10090A0DF /* AdsManagerDelegateTests.swift in Sources */, + 8F599BBD2C332CFE0090A0DF /* ContentPlayheadTests.swift in Sources */, + 8F977DCF2C2B99C600A90D4B /* AdDisplayContainerTests.swift in Sources */, + 8F599BB52C2DD8EC0090A0DF /* AdsLoaderDelegateTests.swift in Sources */, + 8F599BB92C332A320090A0DF /* AdsRenderingSettingsTests.swift in Sources */, + 8F977DD52C2C777600A90D4B /* AdErrorTests.swift in Sources */, + 8F599BB12C2DD1FD0090A0DF /* AdsManagerTests.swift in Sources */, + 8F977DDB2C2C8D2E00A90D4B /* AdsLoadedDataTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -379,6 +539,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 89C6230E68C80A6F4B207726 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -396,6 +557,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 5B63D978173E0F79E02D7128 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +573,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 41604FD1E0DA824F933934B2 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/packages/interactive_media_ads/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/interactive_media_ads/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f1..21a3cc14c74e9 100644 --- a/packages/interactive_media_ads/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/interactive_media_ads/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/interactive_media_ads/example/ios/Runner/AppDelegate.swift b/packages/interactive_media_ads/example/ios/Runner/AppDelegate.swift index d83c0ff0beea4..4580c8e76da45 100644 --- a/packages/interactive_media_ads/example/ios/Runner/AppDelegate.swift +++ b/packages/interactive_media_ads/example/ios/Runner/AppDelegate.swift @@ -5,7 +5,7 @@ import Flutter import UIKit -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdDisplayContainerTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdDisplayContainerTests.swift new file mode 100644 index 0000000000000..be3bad2680490 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdDisplayContainerTests.swift @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import XCTest + +@testable import interactive_media_ads + +final class AdDisplayContainerTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdDisplayContainer(registrar) + + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api, adContainer: UIView(), adContainerViewController: UIViewController()) + + XCTAssertNotNil(instance) + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdErrorTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdErrorTests.swift new file mode 100644 index 0000000000000..c770b6738ac08 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdErrorTests.swift @@ -0,0 +1,65 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdErrorTests: XCTestCase { + func testType() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdError(registrar) + + let instance = TestAdError.customInit() + + let value = try? api.pigeonDelegate.type(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, .loadingFailed) + } + + func testCode() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdError(registrar) + + let instance = TestAdError.customInit() + + let value = try? api.pigeonDelegate.code(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, .apiError) + } + + func testMessage() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdError(registrar) + + let instance = TestAdError.customInit() + + let value = try? api.pigeonDelegate.message(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, "message") + } +} + +class TestAdError: IMAAdError { + // Workaround to subclass an Objective-C class that has an `init` constructor with NS_UNAVAILABLE + static func customInit() -> IMAAdError { + let instance = + TestAdError.perform(NSSelectorFromString("new")).takeRetainedValue() as! TestAdError + return instance + } + + override var type: IMAErrorType { + return .adLoadingFailed + } + + override var code: IMAErrorCode { + return .API_ERROR + } + + override var message: String? { + return "message" + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdEventTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdEventTests.swift new file mode 100644 index 0000000000000..301ba3129303f --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdEventTests.swift @@ -0,0 +1,50 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdEventTests: XCTestCase { + func testType() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdEvent(registrar) + + let instance = TestAdEvent.customInit() + + let value = try? api.pigeonDelegate.type(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, .adBreakEnded) + } + + func testMessage() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdEvent(registrar) + + let instance = TestAdEvent.customInit() + + let value = try? api.pigeonDelegate.typeString(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, "message") + } +} + +class TestAdEvent: IMAAdEvent { + // Workaround to subclass an Objective-C class that has an `init` constructor with NS_UNAVAILABLE + static func customInit() -> TestAdEvent { + let instance = + TestAdEvent.perform(NSSelectorFromString("new")).takeRetainedValue() as! TestAdEvent + return instance + } + + override var type: IMAAdEventType { + return .AD_BREAK_ENDED + } + + override var typeString: String { + return "message" + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdLoadingErrorDataTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdLoadingErrorDataTests.swift new file mode 100644 index 0000000000000..1797c16dae2b6 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdLoadingErrorDataTests.swift @@ -0,0 +1,36 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdLoadingErrorTests: XCTestCase { + func testAdError() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdLoadingErrorData(registrar) + + let instance = TestAdLoadingErrorData.customInit() + + let value = try? api.pigeonDelegate.adError(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(value is TestAdError) + } +} + +class TestAdLoadingErrorData: IMAAdLoadingErrorData { + // Workaround to subclass an Objective-C class that has an `init` constructor with NS_UNAVAILABLE + static func customInit() -> TestAdLoadingErrorData { + let instance = + TestAdLoadingErrorData.perform(NSSelectorFromString("new")).takeRetainedValue() + as! TestAdLoadingErrorData + return instance + } + + override var adError: IMAAdError { + return TestAdError.customInit() + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoadedDataTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoadedDataTests.swift new file mode 100644 index 0000000000000..d5afe99c23071 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoadedDataTests.swift @@ -0,0 +1,36 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdsLoadedDataTests: XCTestCase { + func testAdsManager() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsLoadedData(registrar) + + let instance = TestAdsLoadedData.customInit() + + let value = try? api.pigeonDelegate.adsManager(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(value is TestAdsManager) + } +} + +class TestAdsLoadedData: IMAAdsLoadedData { + // Workaround to subclass an Objective-C class that has an `init` constructor with NS_UNAVAILABLE + static func customInit() -> TestAdsLoadedData { + let instance = + TestAdsLoadedData.perform(NSSelectorFromString("new")).takeRetainedValue() + as! TestAdsLoadedData + return instance + } + + override var adsManager: IMAAdsManager? { + return TestAdsManager.customInit() + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderDelegateTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderDelegateTests.swift new file mode 100644 index 0000000000000..6e50f0c5e771f --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderDelegateTests.swift @@ -0,0 +1,63 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdsLoaderDelegateTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsLoaderDelegate(registrar) + + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api) + + XCTAssertTrue(instance is AdsLoaderDelegateImpl) + } + + func testAdLoaderLoadedWith() { + let api = TestAdsLoaderDelegateApi() + let instance = AdsLoaderDelegateImpl(api: api) + + let adsLoader = IMAAdsLoader(settings: nil) + let data = TestAdsLoadedData() + instance.adsLoader(adsLoader, adsLoadedWith: data) + + XCTAssertEqual(api.adLoaderLoadedWithArgs, [adsLoader, data]) + } + + func testAdsLoaderFailedWithErrorData() { + let api = TestAdsLoaderDelegateApi() + let instance = AdsLoaderDelegateImpl(api: api) + + let adsLoader = IMAAdsLoader(settings: nil) + let error = TestAdLoadingErrorData.customInit() + instance.adsLoader(adsLoader, failedWith: error) + + XCTAssertEqual(api.adsLoaderFailedWithErrorDataArgs, [adsLoader, error]) + } +} + +class TestAdsLoaderDelegateApi: PigeonApiProtocolIMAAdsLoaderDelegate { + var adLoaderLoadedWithArgs: [AnyHashable?]? = nil + var adsLoaderFailedWithErrorDataArgs: [AnyHashable?]? = nil + + func adLoaderLoadedWith( + pigeonInstance pigeonInstanceArg: IMAAdsLoaderDelegate, loader loaderArg: IMAAdsLoader, + adsLoadedData adsLoadedDataArg: IMAAdsLoadedData, + completion: @escaping (Result) -> Void + ) { + adLoaderLoadedWithArgs = [loaderArg, adsLoadedDataArg] + } + + func adsLoaderFailedWithErrorData( + pigeonInstance pigeonInstanceArg: IMAAdsLoaderDelegate, loader loaderArg: IMAAdsLoader, + adErrorData adErrorDataArg: IMAAdLoadingErrorData, + completion: @escaping (Result) -> Void + ) { + adsLoaderFailedWithErrorDataArgs = [loaderArg, adErrorDataArg] + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderTests.swift new file mode 100644 index 0000000000000..1d7263efdbb09 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdsLoaderTests.swift @@ -0,0 +1,82 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdsLoaderTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsLoader(registrar) + + let settings = IMASettings() + settings.ppid = "ppid" + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api, settings: settings) + + XCTAssertNotNil(instance) + XCTAssertEqual(instance?.settings.ppid, settings.ppid) + } + + func testContentComplete() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsLoader(registrar) + + let instance = TestAdsLoader(settings: nil) + + try? api.pigeonDelegate.contentComplete(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.contentCompleteCalled) + } + + func testRequestAds() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsLoader(registrar) + + let instance = TestAdsLoader(settings: nil) + + let request = IMAAdsRequest( + adTagUrl: "", + adDisplayContainer: IMAAdDisplayContainer(adContainer: UIView(), viewController: nil), + contentPlayhead: ContentPlayheadImpl(), userContext: nil) + try? api.pigeonDelegate.requestAds( + pigeonApi: api, pigeonInstance: instance, request: request) + + XCTAssertIdentical(instance.adsRequested, request) + } + + func testSetDelegate() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsLoader(registrar) + + let instance = TestAdsLoader(settings: nil) + + let delegate = AdsLoaderDelegateImpl( + api: registrar.apiDelegate.pigeonApiIMAAdsLoaderDelegate(registrar)) + try? api.pigeonDelegate.setDelegate( + pigeonApi: api, pigeonInstance: instance, delegate: delegate) + + XCTAssertIdentical(instance.delegate, delegate) + } +} + +class TestAdsLoader: IMAAdsLoader { + var contentCompleteCalled = false + var adsRequested: IMAAdsRequest? = nil + + override init(settings: IMASettings?) { + super.init(settings: settings) + } + + override func contentComplete() { + contentCompleteCalled = true + } + + override func requestAds(with request: IMAAdsRequest) { + adsRequested = request + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerDelegateTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerDelegateTests.swift new file mode 100644 index 0000000000000..303502971dada --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerDelegateTests.swift @@ -0,0 +1,101 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdsManagerDelegateTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManagerDelegate(registrar) + + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api) + + XCTAssertTrue(instance is AdsManagerDelegateImpl) + } + + func testDidReceiveAdEvent() { + let api = TestAdsManagerDelegateApi() + let instance = AdsManagerDelegateImpl(api: api) + + let manager = TestAdsManager.customInit() + let event = TestAdEvent.customInit() + instance.adsManager(manager, didReceive: event) + + XCTAssertEqual(api.didReceiveAdEventArgs, [manager, event]) + } + + func testDidReceiveAdError() { + let api = TestAdsManagerDelegateApi() + let instance = AdsManagerDelegateImpl(api: api) + + let manager = TestAdsManager.customInit() + let error = TestAdError.customInit() + instance.adsManager(manager, didReceive: error) + + XCTAssertEqual(api.didReceiveAdErrorArgs, [manager, error]) + } + + func testDidRequestContentPause() { + let api = TestAdsManagerDelegateApi() + let instance = AdsManagerDelegateImpl(api: api) + + let manager = TestAdsManager.customInit() + instance.adsManagerDidRequestContentPause(manager) + + XCTAssertEqual(api.didRequestContentPauseArgs, [manager]) + } + + func testDidRequestContentResume() { + let api = TestAdsManagerDelegateApi() + let instance = AdsManagerDelegateImpl(api: api) + + let manager = TestAdsManager.customInit() + instance.adsManagerDidRequestContentResume(manager) + + XCTAssertEqual(api.didRequestContentResumeArgs, [manager]) + } +} + +class TestAdsManagerDelegateApi: PigeonApiProtocolIMAAdsManagerDelegate { + var didReceiveAdEventArgs: [AnyHashable?]? = nil + var didReceiveAdErrorArgs: [AnyHashable?]? = nil + var didRequestContentPauseArgs: [AnyHashable?]? = nil + var didRequestContentResumeArgs: [AnyHashable?]? = nil + + func didReceiveAdEvent( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, event eventArg: IMAAdEvent, + completion: @escaping (Result) -> Void + ) { + didReceiveAdEventArgs = [adsManagerArg, eventArg] + } + + func didReceiveAdError( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, error errorArg: IMAAdError, + completion: @escaping (Result) -> Void + ) { + didReceiveAdErrorArgs = [adsManagerArg, errorArg] + } + + func didRequestContentPause( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, + completion: @escaping (Result) -> Void + ) { + didRequestContentPauseArgs = [adsManagerArg] + } + + func didRequestContentResume( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, + completion: @escaping (Result) -> Void + ) { + didRequestContentResumeArgs = [adsManagerArg] + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerTests.swift new file mode 100644 index 0000000000000..48c232dc751e6 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdsManagerTests.swift @@ -0,0 +1,149 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdsManagerTests: XCTestCase { + func testSetDelegate() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + let delegate = AdsManagerDelegateImpl( + api: registrar.apiDelegate.pigeonApiIMAAdsManagerDelegate(registrar)) + try? api.pigeonDelegate.setDelegate( + pigeonApi: api, pigeonInstance: instance, delegate: delegate) + + XCTAssertIdentical(instance.delegate, delegate) + } + + func testInitialize() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + let renderingSettings = IMAAdsRenderingSettings() + try? api.pigeonDelegate.initialize( + pigeonApi: api, pigeonInstance: instance, adsRenderingSettings: renderingSettings) + + XCTAssertEqual(instance.renderingSettings, renderingSettings) + } + + func testStart() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + try? api.pigeonDelegate.start(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.startCalled) + } + + func testPause() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + try? api.pigeonDelegate.pause(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.pauseCalled) + } + + func testSkip() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + try? api.pigeonDelegate.skip(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.skipCalled) + } + + func testDiscardAdBreak() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + try? api.pigeonDelegate.discardAdBreak(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.discardAdBreakCalled) + } + + func testResume() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + try? api.pigeonDelegate.resume(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.resumeCalled) + } + + func testDestroy() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar) + + let instance = TestAdsManager.customInit() + + try? api.pigeonDelegate.destroy(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.destroyCalled) + } +} + +class TestAdsManager: IMAAdsManager { + var renderingSettings: IMAAdsRenderingSettings? = nil + var startCalled = false + var pauseCalled = false + var skipCalled = false + var discardAdBreakCalled = false + var resumeCalled = false + var destroyCalled = false + + // Workaround to subclass an Objective-C class that has an `init` constructor with NS_UNAVAILABLE + static func customInit() -> TestAdsManager { + let instance = + TestAdsManager.perform(NSSelectorFromString("new")).takeRetainedValue() as! TestAdsManager + return instance + } + + override func initialize(with adsRenderingSettings: IMAAdsRenderingSettings?) { + renderingSettings = adsRenderingSettings + } + + override func start() { + startCalled = true + } + + override func pause() { + pauseCalled = true + } + + override func skip() { + skipCalled = true + } + + override func discardAdBreak() { + discardAdBreakCalled = true + } + + override func resume() { + resumeCalled = true + } + + override func destroy() { + destroyCalled = true + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdsRenderingSettingsTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdsRenderingSettingsTests.swift new file mode 100644 index 0000000000000..5964ac4b86610 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdsRenderingSettingsTests.swift @@ -0,0 +1,21 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdsRenderingSettingsTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsRenderingSettings(registrar) + + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api) + + XCTAssertTrue(instance != nil) + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/AdsRequestTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/AdsRequestTests.swift new file mode 100644 index 0000000000000..21b52654ad9d5 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/AdsRequestTests.swift @@ -0,0 +1,28 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class AdsRequestTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAAdsRequest(registrar) + + let container = IMAAdDisplayContainer(adContainer: UIView(), viewController: nil) + let contentPlayhead = ContentPlayheadImpl() + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api, adTagUrl: "adTag?", adDisplayContainer: container, + contentPlayhead: contentPlayhead) + + XCTAssertNotNil(instance) + XCTAssertEqual( + instance?.adTagUrl, + "adTag?&request_agent=Flutter-IMA-\(AdsRequestProxyAPIDelegate.pluginVersion)") + XCTAssertIdentical(instance?.adDisplayContainer, container) + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/ContentPlayheadTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/ContentPlayheadTests.swift new file mode 100644 index 0000000000000..3d4b60fa35b84 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/ContentPlayheadTests.swift @@ -0,0 +1,32 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleInteractiveMediaAds +import XCTest + +@testable import interactive_media_ads + +final class ContentPlayheadTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAContentPlayhead(registrar) + + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api) + + XCTAssertNotNil(instance) + } + + func testSetCurrentTime() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiIMAContentPlayhead(registrar) + + let instance = ContentPlayheadImpl() + try? api.pigeonDelegate.setCurrentTime( + pigeonApi: api, pigeonInstance: instance, timeInterval: 12) + + XCTAssertEqual(instance.currentTime, 12) + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/RunnerTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index cea3cbd3a1fb5..0000000000000 --- a/packages/interactive_media_ads/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import UIKit -import XCTest - -@testable import interactive_media_ads - -// 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 = InteractiveMediaAdsPlugin() - - 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/interactive_media_ads/example/ios/RunnerTests/TestProxyApiRegistrar.swift b/packages/interactive_media_ads/example/ios/RunnerTests/TestProxyApiRegistrar.swift new file mode 100644 index 0000000000000..cb723d71de716 --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/TestProxyApiRegistrar.swift @@ -0,0 +1,37 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import XCTest + +@testable import interactive_media_ads + +class TestProxyApiRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar { + private class TestBinaryMessenger: NSObject, FlutterBinaryMessenger { + func send(onChannel channel: String, message: Data?) { + + } + + func send( + onChannel channel: String, message: Data?, binaryReply callback: FlutterBinaryReply? = nil + ) { + + } + + func setMessageHandlerOnChannel( + _ channel: String, binaryMessageHandler handler: FlutterBinaryMessageHandler? = nil + ) -> FlutterBinaryMessengerConnection { + return 0 + } + + func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) { + + } + } + + init() { + let testBinaryMessenger = TestBinaryMessenger() + super.init(binaryMessenger: testBinaryMessenger, apiDelegate: ProxyApiDelegate()) + } +} diff --git a/packages/interactive_media_ads/example/ios/RunnerTests/ViewControllerTests.swift b/packages/interactive_media_ads/example/ios/RunnerTests/ViewControllerTests.swift new file mode 100644 index 0000000000000..73ccd24c40bec --- /dev/null +++ b/packages/interactive_media_ads/example/ios/RunnerTests/ViewControllerTests.swift @@ -0,0 +1,50 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import XCTest + +@testable import interactive_media_ads + +final class ViewControllerTests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiUIViewController(registrar) + + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api) + + XCTAssertNotNil(instance) + } + + func testView() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiUIViewController(registrar) + + let instance = UIViewController() + let view = try? api.pigeonDelegate.view(pigeonApi: api, pigeonInstance: instance) + + XCTAssertNotNil(view) + } + + func testViewDidAppear() { + let api = TestUIViewControllerApi() + let instance = ViewControllerImpl(api: api) + + instance.viewDidAppear(true) + + XCTAssertEqual(api.viewDidAppearArgs, [instance, true]) + } +} + +class TestUIViewControllerApi: PigeonApiProtocolUIViewController { + var viewDidAppearArgs: [AnyHashable?]? = nil + + func viewDidAppear( + pigeonInstance pigeonInstanceArg: UIViewController, animated animatedArg: Bool, + completion: @escaping (Result) -> Void + ) { + viewDidAppearArgs = [pigeonInstanceArg, animatedArg] + } +} diff --git a/packages/interactive_media_ads/example/lib/main.dart b/packages/interactive_media_ads/example/lib/main.dart index 3d62d776aa15e..8cac5c867b88a 100644 --- a/packages/interactive_media_ads/example/lib/main.dart +++ b/packages/interactive_media_ads/example/lib/main.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_driver/driver_extension.dart'; // #docregion imports @@ -20,15 +19,7 @@ void integrationTestMain() { } void main() { - runApp( - MaterialApp( - // TODO(bparrishMines): Remove this check once the iOS implementation - // is added. - home: defaultTargetPlatform == TargetPlatform.android - ? const AdExampleWidget() - : Container(), - ), - ); + runApp(const MaterialApp(home: AdExampleWidget())); } // #docregion example_widget diff --git a/packages/interactive_media_ads/ios/interactive_media_ads.podspec b/packages/interactive_media_ads/ios/interactive_media_ads.podspec index bb42cc28763bd..093c7d3d93246 100644 --- a/packages/interactive_media_ads/ios/interactive_media_ads.podspec +++ b/packages/interactive_media_ads/ios/interactive_media_ads.podspec @@ -16,6 +16,7 @@ Downloaded by pub (not CocoaPods). s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/interactive_media_ads/interactive_media_ads' } s.source_files = 'interactive_media_ads/Sources/interactive_media_ads/**/*.swift' s.dependency 'Flutter' + s.dependency 'GoogleAds-IMA-iOS-SDK', '~> 3.23' s.platform = :ios, '12.0' # Flutter.framework does not contain a i386 slice. diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Package.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Package.swift index 1864dffbb7873..1ef9d7838d008 100644 --- a/packages/interactive_media_ads/ios/interactive_media_ads/Package.swift +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Package.swift @@ -15,11 +15,19 @@ let package = Package( products: [ .library(name: "interactive-media-ads", targets: ["interactive_media_ads"]) ], - dependencies: [], + dependencies: [ + .package( + url: "https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios", + .upToNextMajor(from: "3.23.0")) + ], targets: [ .target( name: "interactive_media_ads", - dependencies: [], + dependencies: [ + .product( + name: "GoogleInteractiveMediaAds", + package: "swift-package-manager-google-interactive-media-ads-ios") + ], resources: [ .process("Resources") ] diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdDisplayContainerProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdDisplayContainerProxyAPIDelegate.swift new file mode 100644 index 0000000000000..a7ab7f0f504ca --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdDisplayContainerProxyAPIDelegate.swift @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdDisplayContainer`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdDisplayContainerProxyAPIDelegate: PigeonApiDelegateIMAAdDisplayContainer { + func pigeonDefaultConstructor( + pigeonApi: PigeonApiIMAAdDisplayContainer, adContainer: UIView, + adContainerViewController: UIViewController? + ) throws -> IMAAdDisplayContainer { + return IMAAdDisplayContainer( + adContainer: adContainer, viewController: adContainerViewController) + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdErrorProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdErrorProxyAPIDelegate.swift new file mode 100644 index 0000000000000..3005bbd81a26f --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdErrorProxyAPIDelegate.swift @@ -0,0 +1,84 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdError`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdErrorProxyAPIDelegate: PigeonApiDelegateIMAAdError { + func type(pigeonApi: PigeonApiIMAAdError, pigeonInstance: IMAAdError) throws -> AdErrorType { + switch pigeonInstance.type { + case .adLoadingFailed: + return .loadingFailed + case .adPlayingFailed: + return .adPlayingFailed + case .adUnknownErrorType: + return .unknown + @unknown default: + return .unknown + } + } + + func code(pigeonApi: PigeonApiIMAAdError, pigeonInstance: IMAAdError) throws -> AdErrorCode { + switch pigeonInstance.code { + case .VAST_MALFORMED_RESPONSE: + return .vastMalformedResponse + case .VAST_TRAFFICKING_ERROR: + return .vastTraffickingError + case .VAST_LOAD_TIMEOUT: + return .vastLoadTimeout + case .VAST_TOO_MANY_REDIRECTS: + return .vastTooManyRedirects + case .VAST_INVALID_URL: + return .vastInvalidUrl + case .VIDEO_PLAY_ERROR: + return .videoPlayError + case .VAST_MEDIA_LOAD_TIMEOUT: + return .vastMediaLoadTimeout + case .VAST_LINEAR_ASSET_MISMATCH: + return .vastLinearAssetMismatch + case .COMPANION_AD_LOADING_FAILED: + return .companionAdLoadingFailed + case .UNKNOWN_ERROR: + return .unknownError + case .PLAYLIST_MALFORMED_RESPONSE: + return .playlistMalformedResponse + case .FAILED_TO_REQUEST_ADS: + return .failedToRequestAds + case .REQUIRED_LISTENERS_NOT_ADDED: + return .requiredListenersNotAdded + case .VAST_ASSET_NOT_FOUND: + return .vastAssetNotFound + case .ADSLOT_NOT_VISIBLE: + return .adslotNotVisible + case .VAST_EMPTY_RESPONSE: + return .vastEmptyResponse + case .FAILED_LOADING_AD: + return .failedLoadingAd + case .STREAM_INITIALIZATION_FAILED: + return .streamInitializationFailed + case .INVALID_ARGUMENTS: + return .invalidArguments + case .API_ERROR: + return .apiError + case .OS_RUNTIME_TOO_OLD: + return .osRuntimeTooOld + case .VIDEO_ELEMENT_USED: + return .videoElementUsed + case .VIDEO_ELEMENT_REQUIRED: + return .videoElementRequired + case .CONTENT_PLAYHEAD_MISSING: + return .contentPlayheadMissing + @unknown default: + return .unknownError + } + } + + func message(pigeonApi: PigeonApiIMAAdError, pigeonInstance: IMAAdError) throws -> String? { + return pigeonInstance.message + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdEventProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdEventProxyAPIDelegate.swift new file mode 100644 index 0000000000000..7548c61bd297c --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdEventProxyAPIDelegate.swift @@ -0,0 +1,71 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdEvent`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdEventProxyAPIDelegate: PigeonApiDelegateIMAAdEvent { + func type(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> AdEventType { + switch pigeonInstance.type { + case .AD_BREAK_READY: + return .adBreakReady + case .AD_BREAK_FETCH_ERROR: + return .adBreakFetchError + case .AD_BREAK_ENDED: + return .adBreakEnded + case .AD_BREAK_STARTED: + return .adBreakStarted + case .AD_PERIOD_ENDED: + return .adPeriodEnded + case .AD_PERIOD_STARTED: + return .adPeriodStarted + case .ALL_ADS_COMPLETED: + return .allAdsCompleted + case .CLICKED: + return .clicked + case .COMPLETE: + return .completed + case .CUEPOINTS_CHANGED: + return .cuepointsChanged + case .ICON_FALLBACK_IMAGE_CLOSED: + return .iconFallbackImageClosed + case .ICON_TAPPED: + return .iconTapped + case .FIRST_QUARTILE: + return .firstQuartile + case .LOADED: + return .loaded + case .LOG: + return .log + case .MIDPOINT: + return .midpoint + case .PAUSE: + return .pause + case .RESUME: + return .resume + case .SKIPPED: + return .skipped + case .STARTED: + return .started + case .STREAM_LOADED: + return .streamLoaded + case .STREAM_STARTED: + return .streamStarted + case .TAPPED: + return .tapped + case .THIRD_QUARTILE: + return .thirdQuartile + @unknown default: + return .unknown + } + } + + func typeString(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> String { + return pigeonInstance.typeString + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdLoadingErrorDataProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdLoadingErrorDataProxyAPIDelegate.swift new file mode 100644 index 0000000000000..3179213941f59 --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdLoadingErrorDataProxyAPIDelegate.swift @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdLoadingErrorData`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdLoadingErrorDataProxyAPIDelegate: PigeonApiDelegateIMAAdLoadingErrorData { + func adError(pigeonApi: PigeonApiIMAAdLoadingErrorData, pigeonInstance: IMAAdLoadingErrorData) + throws -> IMAAdError + { + return pigeonInstance.adError + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoadedDataProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoadedDataProxyAPIDelegate.swift new file mode 100644 index 0000000000000..f387cbbd50dda --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoadedDataProxyAPIDelegate.swift @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdsLoadedData`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdsLoadedDataProxyAPIDelegate: PigeonApiDelegateIMAAdsLoadedData { + func adsManager(pigeonApi: PigeonApiIMAAdsLoadedData, pigeonInstance: IMAAdsLoadedData) throws + -> IMAAdsManager? + { + return pigeonInstance.adsManager + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderDelegateProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderDelegateProxyAPIDelegate.swift new file mode 100644 index 0000000000000..53eda9bc51c25 --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderDelegateProxyAPIDelegate.swift @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// Implementation of `IMAAdsManagerDelegate` that calls to Dart in callback methods. +class AdsLoaderDelegateImpl: IMAAdsLoaderDelegate { + let api: PigeonApiProtocolIMAAdsLoaderDelegate + + init(api: PigeonApiProtocolIMAAdsLoaderDelegate) { + self.api = api + } + + func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) { + api.adLoaderLoadedWith(pigeonInstance: self, loader: loader, adsLoadedData: adsLoadedData) { + _ in + } + } + + func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) { + api.adsLoaderFailedWithErrorData(pigeonInstance: self, loader: loader, adErrorData: adErrorData) + { _ in } + } +} + +/// ProxyApi delegate implementation for `IMAAdsLoaderDelegate`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdsLoaderDelegateProxyAPIDelegate: PigeonApiDelegateIMAAdsLoaderDelegate { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsLoaderDelegate) throws + -> IMAAdsLoaderDelegate + { + return AdsLoaderDelegateImpl(api: pigeonApi) + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderProxyAPIDelegate.swift new file mode 100644 index 0000000000000..d1cf5fe56cb5e --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsLoaderProxyAPIDelegate.swift @@ -0,0 +1,34 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdsLoader`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdsLoaderProxyAPIDelegate: PigeonApiDelegateIMAAdsLoader { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsLoader, settings: IMASettings?) throws + -> IMAAdsLoader + { + return IMAAdsLoader(settings: settings) + } + + func contentComplete(pigeonApi: PigeonApiIMAAdsLoader, pigeonInstance: IMAAdsLoader) throws { + pigeonInstance.contentComplete() + } + + func requestAds( + pigeonApi: PigeonApiIMAAdsLoader, pigeonInstance: IMAAdsLoader, request: IMAAdsRequest + ) throws { + pigeonInstance.requestAds(with: request) + } + + func setDelegate( + pigeonApi: PigeonApiIMAAdsLoader, pigeonInstance: IMAAdsLoader, delegate: IMAAdsLoaderDelegate? + ) throws { + pigeonInstance.delegate = delegate + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerDelegateProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerDelegateProxyAPIDelegate.swift new file mode 100644 index 0000000000000..8b48f77a30bae --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerDelegateProxyAPIDelegate.swift @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// Implementation of `IMAAdsManagerDelegate` that calls to Dart in callback methods. +class AdsManagerDelegateImpl: NSObject, IMAAdsManagerDelegate { + let api: PigeonApiProtocolIMAAdsManagerDelegate + + init(api: PigeonApiProtocolIMAAdsManagerDelegate) { + self.api = api + } + + func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) { + api.didReceiveAdEvent(pigeonInstance: self, adsManager: adsManager, event: event) { _ in } + } + + func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) { + api.didReceiveAdError(pigeonInstance: self, adsManager: adsManager, error: error) { _ in } + } + + func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) { + api.didRequestContentPause(pigeonInstance: self, adsManager: adsManager) { _ in } + } + + func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) { + api.didRequestContentResume(pigeonInstance: self, adsManager: adsManager) { _ in } + } +} + +/// ProxyApi delegate implementation for `IMAAdsManagerDelegate`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdsManagerDelegateProxyAPIDelegate: PigeonApiDelegateIMAAdsManagerDelegate { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsManagerDelegate) throws + -> IMAAdsManagerDelegate + { + return AdsManagerDelegateImpl(api: pigeonApi) + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerProxyAPIDelegate.swift new file mode 100644 index 0000000000000..3916362e4cb77 --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsManagerProxyAPIDelegate.swift @@ -0,0 +1,50 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdsManager`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdsManagerProxyAPIDelegate: PigeonApiDelegateIMAAdsManager { + func setDelegate( + pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager, + delegate: IMAAdsManagerDelegate? + ) throws { + pigeonInstance.delegate = delegate as? AdsManagerDelegateImpl + } + + func initialize( + pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager, + adsRenderingSettings: IMAAdsRenderingSettings? + ) throws { + pigeonInstance.initialize(with: adsRenderingSettings) + } + + func start(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws { + pigeonInstance.start() + } + + func pause(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws { + pigeonInstance.pause() + } + + func skip(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws { + pigeonInstance.skip() + } + + func discardAdBreak(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws { + pigeonInstance.discardAdBreak() + } + + func resume(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws { + pigeonInstance.resume() + } + + func destroy(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws { + pigeonInstance.destroy() + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRenderingSettingsProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRenderingSettingsProxyAPIDelegate.swift new file mode 100644 index 0000000000000..8567aded6b29f --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRenderingSettingsProxyAPIDelegate.swift @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdsRenderingSettings`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdsRenderingSettingsProxyAPIDelegate: PigeonApiDelegateIMAAdsRenderingSettings { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsRenderingSettings) throws + -> IMAAdsRenderingSettings + { + return IMAAdsRenderingSettings() + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift new file mode 100644 index 0000000000000..19e47f1187c6f --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift @@ -0,0 +1,32 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// ProxyApi delegate implementation for `IMAAdsRequest`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class AdsRequestProxyAPIDelegate: PigeonApiDelegateIMAAdsRequest { + /// The current version of the `interactive_media_ads` plugin. + /// + /// This must match the version in pubspec.yaml. + static let pluginVersion = "0.1.1" + + func pigeonDefaultConstructor( + pigeonApi: PigeonApiIMAAdsRequest, adTagUrl: String, adDisplayContainer: IMAAdDisplayContainer, + contentPlayhead: IMAContentPlayhead? + ) throws -> IMAAdsRequest { + // Ensure adTag can append a custom parameter. + assert(adTagUrl.contains("?")) + assert(!adTagUrl.contains("#")) + + let adTagWithRequestAgent = + "\(adTagUrl)&request_agent=Flutter-IMA-\(AdsRequestProxyAPIDelegate.pluginVersion)" + return IMAAdsRequest( + adTagUrl: adTagWithRequestAgent, adDisplayContainer: adDisplayContainer, + contentPlayhead: contentPlayhead as? ContentPlayheadImpl, userContext: nil) + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ContentPlayheadProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ContentPlayheadProxyAPIDelegate.swift new file mode 100644 index 0000000000000..2c7848216f3d0 --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ContentPlayheadProxyAPIDelegate.swift @@ -0,0 +1,29 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// Implementation of `IMAContentPlayhead` with a settable time interval. +class ContentPlayheadImpl: NSObject, IMAContentPlayhead { + var currentTime: TimeInterval = 0.0 +} + +/// ProxyApi delegate implementation for `IMAContentPlayhead`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class ContentPlayheadProxyAPIDelegate: PigeonApiDelegateIMAContentPlayhead { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAContentPlayhead) throws -> IMAContentPlayhead + { + return ContentPlayheadImpl() + } + + // This is not an actual method on IMAContentPlayhead, but added so it can handle the sync callback. + func setCurrentTime( + pigeonApi: PigeonApiIMAContentPlayhead, pigeonInstance: IMAContentPlayhead, timeInterval: Double + ) throws { + (pigeonInstance as! ContentPlayheadImpl).currentTime = timeInterval + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/FlutterViewFactory.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/FlutterViewFactory.swift new file mode 100644 index 0000000000000..857ac8a14f505 --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/FlutterViewFactory.swift @@ -0,0 +1,45 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import Foundation + +/// Implementation of `FlutterPlatformViewFactory` that converts any `UIView` in a +/// `PigeonInstanceManager` to a `FlutterPlatformView`. +class FlutterViewFactory: NSObject, FlutterPlatformViewFactory { + unowned let instanceManager: InteractiveMediaAdsLibraryPigeonInstanceManager + + class PlatformViewImpl: NSObject, FlutterPlatformView { + let uiView: UIView + + init(uiView: UIView) { + self.uiView = uiView + } + + func view() -> UIView { + return uiView + } + } + + init(instanceManager: InteractiveMediaAdsLibraryPigeonInstanceManager) { + self.instanceManager = instanceManager + } + + func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) + -> FlutterPlatformView + { + let identifier: Int64 = args is Int64 ? args as! Int64 : Int64(args as! Int32) + let instance: AnyObject? = instanceManager.instance(forIdentifier: identifier) + + if let instance = instance as? FlutterPlatformView { + return instance + } else { + return PlatformViewImpl(uiView: instance as! UIView) + } + } + + func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { + return FlutterStandardMessageCodec.sharedInstance() + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsLibrary.g.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsLibrary.g.swift new file mode 100644 index 0000000000000..782f2f14cd85c --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsLibrary.g.swift @@ -0,0 +1,2893 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v21.2.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation +import GoogleInteractiveMediaAds +import UIKit + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #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, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func createConnectionError(withChannelName channelName: String) -> PigeonError { + return PigeonError( + code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + details: "") +} + +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? +} +/// Handles the callback when an object is deallocated. +protocol InteractiveMediaAdsLibraryPigeonFinalizerDelegate: AnyObject { + /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. + func onDeinit(identifier: Int64) +} + +// Attaches to an object to receive a callback when the object is deallocated. +internal final class InteractiveMediaAdsLibraryPigeonFinalizer { + private static let associatedObjectKey = malloc(1)! + + private let identifier: Int64 + // Reference to the delegate is weak because the callback should be ignored if the + // `InstanceManager` is deallocated. + private weak var delegate: InteractiveMediaAdsLibraryPigeonFinalizerDelegate? + + private init(identifier: Int64, delegate: InteractiveMediaAdsLibraryPigeonFinalizerDelegate) { + self.identifier = identifier + self.delegate = delegate + } + + internal static func attach( + to instance: AnyObject, identifier: Int64, + delegate: InteractiveMediaAdsLibraryPigeonFinalizerDelegate + ) { + let finalizer = InteractiveMediaAdsLibraryPigeonFinalizer( + identifier: identifier, delegate: delegate) + objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) + } + + static func detach(from instance: AnyObject) { + objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) + } + + deinit { + delegate?.onDeinit(identifier: identifier) + } +} + +/// Maintains instances used to communicate with the corresponding objects in Dart. +/// +/// Objects stored in this container are represented by an object in Dart that is also stored in +/// an InstanceManager with the same identifier. +/// +/// When an instance is added with an identifier, either can be used to retrieve the other. +/// +/// Added instances are added as a weak reference and a strong reference. When the strong +/// reference is removed and the weak reference is deallocated,`InteractiveMediaAdsLibraryPigeonFinalizerDelegate.onDeinit` +/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is +/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), +/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually +/// again. +/// +/// Accessing and inserting to an InstanceManager is thread safe. +final class InteractiveMediaAdsLibraryPigeonInstanceManager { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private static let minHostCreatedIdentifier: Int64 = 65536 + + private let lockQueue = DispatchQueue(label: "InteractiveMediaAdsLibraryPigeonInstanceManager") + private let identifiers: NSMapTable = NSMapTable( + keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) + private let weakInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) + private let strongInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) + private let finalizerDelegate: InteractiveMediaAdsLibraryPigeonFinalizerDelegate + private var nextIdentifier: Int64 = minHostCreatedIdentifier + + public init(finalizerDelegate: InteractiveMediaAdsLibraryPigeonFinalizerDelegate) { + self.finalizerDelegate = finalizerDelegate + } + + /// Adds a new instance that was instantiated from Dart. + /// + /// The same instance can be added multiple times, but each identifier must be unique. This allows + /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. + /// + /// - Parameters: + /// - instance: the instance to be stored + /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique + func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + lockQueue.async { + self.addInstance(instance, withIdentifier: identifier) + } + } + + /// Adds a new instance that was instantiated from the host platform. + /// + /// - Parameters: + /// - instance: the instance to be stored. This must be unique to all other added instances. + /// - Returns: the unique identifier (>= 0) stored with instance + func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { + assert(!containsInstance(instance), "Instance of \(instance) has already been added.") + var identifier: Int64 = -1 + lockQueue.sync { + identifier = nextIdentifier + nextIdentifier += 1 + self.addInstance(instance, withIdentifier: identifier) + } + return identifier + } + + /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier paired to an instance. + /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if + /// the manager doesn't contain the value + func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) + strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + /// Retrieves the instance associated with identifier. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier associated with an instance + /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func instance(forIdentifier instanceIdentifier: Int64) -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + assert(identifier >= 0) + assert( + weakInstances.object(forKey: identifier as NSNumber) == nil, + "Identifier has already been added: \(identifier)") + identifiers.setObject(NSNumber(value: identifier), forKey: instance) + weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) + strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) + InteractiveMediaAdsLibraryPigeonFinalizer.attach( + to: instance, identifier: identifier, delegate: finalizerDelegate) + } + + /// Retrieves the identifier paired with an instance. + /// + /// If the manager contains a strong reference to `instance`, it will return the identifier + /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new + /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. + /// + /// If this method returns a nonnull identifier, this method also expects the Dart + /// `InteractiveMediaAdsLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + /// identifier is associated with. + /// + /// - Parameters: + /// - instance: an instance that may be stored in the manager + /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { + var identifier: Int64? = nil + lockQueue.sync { + if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { + strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) + identifier = existingIdentifier + } + } + return identifier + } + + /// Whether this manager contains the given `instance`. + /// + /// - Parameters: + /// - instance: the instance whose presence in this manager is to be tested + /// - Returns: whether this manager contains the given `instance` + func containsInstance(_ instance: AnyObject) -> Bool { + var containsInstance = false + lockQueue.sync { + containsInstance = identifiers.object(forKey: instance) != nil + } + return containsInstance + } + + /// Removes all of the instances from this manager. + /// + /// The manager will be empty after this call returns. + func removeAllObjects() throws { + lockQueue.sync { + identifiers.removeAllObjects() + weakInstances.removeAllObjects() + strongInstances.removeAllObjects() + nextIdentifier = InteractiveMediaAdsLibraryPigeonInstanceManager.minHostCreatedIdentifier + } + } + + /// The number of instances stored as a strong reference. + /// + /// For debugging and testing purposes. + internal var strongInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = strongInstances.count + } + return count + } + + /// The number of instances stored as a weak reference. + /// + /// For debugging and testing purposes. NSMapTables that store keys or objects as weak + /// reference will be reclaimed non-deterministically. + internal var weakInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = weakInstances.count + } + return count + } +} + +private class InteractiveMediaAdsLibraryPigeonInstanceManagerApi { + /// The codec used for serializing messages. + let codec = FlutterStandardMessageCodec.sharedInstance() + + /// Handles sending and receiving messages with Dart. + unowned let binaryMessenger: FlutterBinaryMessenger + + init(binaryMessenger: FlutterBinaryMessenger) { + self.binaryMessenger = binaryMessenger + } + + /// Sets up an instance of `InteractiveMediaAdsLibraryPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, + instanceManager: InteractiveMediaAdsLibraryPigeonInstanceManager? + ) { + let codec = FlutterStandardMessageCodec.sharedInstance() + let removeStrongReferenceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.removeStrongReference", + binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + removeStrongReferenceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + do { + let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removeStrongReferenceChannel.setMessageHandler(nil) + } + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.clear", + binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + clearChannel.setMessageHandler { _, reply in + do { + try instanceManager.removeAllObjects() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearChannel.setMessageHandler(nil) + } + } + + /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. + func removeStrongReference( + identifier identifierArg: Int64, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.removeStrongReference" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([identifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol InteractiveMediaAdsLibraryPigeonProxyApiDelegate { + /// An implementation of [PigeonApiIMAAdDisplayContainer] used to add a new Dart instance of + /// `IMAAdDisplayContainer` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdDisplayContainer( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) -> PigeonApiIMAAdDisplayContainer + /// An implementation of [PigeonApiUIView] used to add a new Dart instance of + /// `UIView` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiUIView(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiUIView + /// An implementation of [PigeonApiUIViewController] used to add a new Dart instance of + /// `UIViewController` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiUIViewController(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiUIViewController + /// An implementation of [PigeonApiIMAContentPlayhead] used to add a new Dart instance of + /// `IMAContentPlayhead` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAContentPlayhead(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAContentPlayhead + /// An implementation of [PigeonApiIMAAdsLoader] used to add a new Dart instance of + /// `IMAAdsLoader` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdsLoader(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsLoader + /// An implementation of [PigeonApiIMASettings] used to add a new Dart instance of + /// `IMASettings` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMASettings(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMASettings + /// An implementation of [PigeonApiIMAAdsRequest] used to add a new Dart instance of + /// `IMAAdsRequest` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdsRequest(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsRequest + /// An implementation of [PigeonApiIMAAdsLoaderDelegate] used to add a new Dart instance of + /// `IMAAdsLoaderDelegate` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdsLoaderDelegate(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsLoaderDelegate + /// An implementation of [PigeonApiIMAAdsLoadedData] used to add a new Dart instance of + /// `IMAAdsLoadedData` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdsLoadedData(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsLoadedData + /// An implementation of [PigeonApiIMAAdLoadingErrorData] used to add a new Dart instance of + /// `IMAAdLoadingErrorData` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdLoadingErrorData( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) -> PigeonApiIMAAdLoadingErrorData + /// An implementation of [PigeonApiIMAAdError] used to add a new Dart instance of + /// `IMAAdError` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdError(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdError + /// An implementation of [PigeonApiIMAAdsManager] used to add a new Dart instance of + /// `IMAAdsManager` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdsManager(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsManager + /// An implementation of [PigeonApiIMAAdsManagerDelegate] used to add a new Dart instance of + /// `IMAAdsManagerDelegate` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdsManagerDelegate( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) -> PigeonApiIMAAdsManagerDelegate + /// An implementation of [PigeonApiIMAAdEvent] used to add a new Dart instance of + /// `IMAAdEvent` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdEvent(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdEvent + /// An implementation of [PigeonApiIMAAdsRenderingSettings] used to add a new Dart instance of + /// `IMAAdsRenderingSettings` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiIMAAdsRenderingSettings( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) -> PigeonApiIMAAdsRenderingSettings + /// An implementation of [PigeonApiNSObject] used to add a new Dart instance of + /// `NSObject` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiNSObject(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiNSObject +} + +extension InteractiveMediaAdsLibraryPigeonProxyApiDelegate { + func pigeonApiUIView(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiUIView + { + return PigeonApiUIView(pigeonRegistrar: registrar, delegate: PigeonApiDelegateUIView()) + } + func pigeonApiIMASettings(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMASettings + { + return PigeonApiIMASettings( + pigeonRegistrar: registrar, delegate: PigeonApiDelegateIMASettings()) + } + func pigeonApiNSObject(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiNSObject + { + return PigeonApiNSObject(pigeonRegistrar: registrar, delegate: PigeonApiDelegateNSObject()) + } +} + +open class InteractiveMediaAdsLibraryPigeonProxyApiRegistrar { + let binaryMessenger: FlutterBinaryMessenger + let apiDelegate: InteractiveMediaAdsLibraryPigeonProxyApiDelegate + let instanceManager: InteractiveMediaAdsLibraryPigeonInstanceManager + /// Whether APIs should ignore calling to Dart. + public var ignoreCallsToDart = false + private var _codec: FlutterStandardMessageCodec? + var codec: FlutterStandardMessageCodec { + if _codec == nil { + _codec = FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: self)) + } + return _codec! + } + + private class InstanceManagerApiFinalizerDelegate: + InteractiveMediaAdsLibraryPigeonFinalizerDelegate + { + let api: InteractiveMediaAdsLibraryPigeonInstanceManagerApi + + init(_ api: InteractiveMediaAdsLibraryPigeonInstanceManagerApi) { + self.api = api + } + + public func onDeinit(identifier: Int64) { + api.removeStrongReference(identifier: identifier) { + _ in + } + } + } + + init( + binaryMessenger: FlutterBinaryMessenger, + apiDelegate: InteractiveMediaAdsLibraryPigeonProxyApiDelegate + ) { + self.binaryMessenger = binaryMessenger + self.apiDelegate = apiDelegate + self.instanceManager = InteractiveMediaAdsLibraryPigeonInstanceManager( + finalizerDelegate: InstanceManagerApiFinalizerDelegate( + InteractiveMediaAdsLibraryPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) + } + + func setUp() { + InteractiveMediaAdsLibraryPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiIMAAdDisplayContainer.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAAdDisplayContainer(self)) + PigeonApiUIViewController.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiUIViewController(self)) + PigeonApiIMAContentPlayhead.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAContentPlayhead(self)) + PigeonApiIMAAdsLoader.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAAdsLoader(self)) + PigeonApiIMAAdsRequest.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAAdsRequest(self)) + PigeonApiIMAAdsLoaderDelegate.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAAdsLoaderDelegate(self)) + PigeonApiIMAAdsManager.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAAdsManager(self)) + PigeonApiIMAAdsManagerDelegate.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAAdsManagerDelegate(self)) + PigeonApiIMAAdsRenderingSettings.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiIMAAdsRenderingSettings(self)) + } + func tearDown() { + InteractiveMediaAdsLibraryPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: nil) + PigeonApiIMAAdDisplayContainer.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiUIViewController.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiIMAContentPlayhead.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiIMAAdsLoader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiIMAAdsRequest.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiIMAAdsLoaderDelegate.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiIMAAdsManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiIMAAdsManagerDelegate.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiIMAAdsRenderingSettings.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: nil) + } +} +private class InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter: FlutterStandardReaderWriter +{ + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + + private class InteractiveMediaAdsLibraryPigeonProxyApiCodecReader: + InteractiveMediaAdsLibraryPigeonCodecReader + { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + + init(data: Data, pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + let identifier = self.readValue() + let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( + forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) + return instance + default: + return super.readValue(ofType: type) + } + } + } + + private class InteractiveMediaAdsLibraryPigeonProxyApiCodecWriter: + InteractiveMediaAdsLibraryPigeonCodecWriter + { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + + init(data: NSMutableData, pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func writeValue(_ value: Any) { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] + || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String + || value is AdErrorType || value is AdErrorCode || value is AdEventType + || value is KeyValueObservingOptions || value is KeyValueChange + || value is KeyValueChangeKey + { + super.writeValue(value) + return + } + + if let instance = value as? IMAAdDisplayContainer { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdDisplayContainer(pigeonRegistrar) + .pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? UIView { + pigeonRegistrar.apiDelegate.pigeonApiUIView(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? UIViewController { + pigeonRegistrar.apiDelegate.pigeonApiUIViewController(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAContentPlayhead { + pigeonRegistrar.apiDelegate.pigeonApiIMAContentPlayhead(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdsLoader { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdsLoader(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMASettings { + pigeonRegistrar.apiDelegate.pigeonApiIMASettings(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdsRequest { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdsRequest(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdsLoaderDelegate { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdsLoaderDelegate(pigeonRegistrar) + .pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdsLoadedData { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdsLoadedData(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdLoadingErrorData { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdLoadingErrorData(pigeonRegistrar) + .pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdError { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdError(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdsManager { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdsManager(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdsManagerDelegate { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdsManagerDelegate(pigeonRegistrar) + .pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdEvent { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdEvent(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? IMAAdsRenderingSettings { + pigeonRegistrar.apiDelegate.pigeonApiIMAAdsRenderingSettings(pigeonRegistrar) + .pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? NSObject { + pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + + if let instance = value as AnyObject?, + pigeonRegistrar.instanceManager.containsInstance(instance) + { + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) + } else { + print("Unsupported value: \(value) of \(type(of: value))") + assert(false, "Unsupported value for InteractiveMediaAdsLibraryPigeonProxyApiCodecWriter") + } + + } + } + + init(pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + } + + override func reader(with data: Data) -> FlutterStandardReader { + return InteractiveMediaAdsLibraryPigeonProxyApiCodecReader( + data: data, pigeonRegistrar: pigeonRegistrar) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return InteractiveMediaAdsLibraryPigeonProxyApiCodecWriter( + data: data, pigeonRegistrar: pigeonRegistrar) + } +} + +/// Possible error types while loading or playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAErrorType.html. +enum AdErrorType: Int { + /// An error occurred while loading the ads. + case loadingFailed = 0 + /// An error occurred while playing the ads. + case adPlayingFailed = 1 + /// An unexpected error occurred while loading or playing the ads. + /// + /// This may mean that the SDK wasn’t loaded properly or the wrapper doesn't + /// recognize this value. + case unknown = 2 +} + +/// Possible error codes raised while loading or playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAErrorCode.html. +enum AdErrorCode: Int { + /// The ad slot is not visible on the page. + case adslotNotVisible = 0 + /// Generic invalid usage of the API. + case apiError = 1 + /// A companion ad failed to load or render. + case companionAdLoadingFailed = 2 + /// Content playhead was not passed in, but list of ads has been returned from + /// the server. + case contentPlayheadMissing = 3 + /// There was an error loading the ad. + case failedLoadingAd = 4 + /// There was a problem requesting ads from the server. + case failedToRequestAds = 5 + /// Invalid arguments were provided to SDK methods. + case invalidArguments = 6 + /// The version of the runtime is too old. + case osRuntimeTooOld = 7 + /// Ads list response was malformed. + case playlistMalformedResponse = 8 + /// Listener for at least one of the required vast events was not added. + case requiredListenersNotAdded = 9 + /// There was an error initializing the stream. + case streamInitializationFailed = 10 + /// An unexpected error occurred and the cause is not known. + case unknownError = 11 + /// No assets were found in the VAST ad response. + case vastAssetNotFound = 12 + /// A VAST response containing a single `` tag with no child tags. + case vastEmptyResponse = 13 + /// At least one VAST wrapper loaded and a subsequent wrapper or inline ad + /// load has resulted in a 404 response code. + case vastInvalidUrl = 14 + /// Assets were found in the VAST ad response for a linear ad, but none of + /// them matched the video player's capabilities. + case vastLinearAssetMismatch = 15 + /// The VAST URI provided, or a VAST URI provided in a subsequent Wrapper + /// element, was either unavailable or reached a timeout, as defined by the + /// video player. + case vastLoadTimeout = 16 + /// The ad response was not recognized as a valid VAST ad. + case vastMalformedResponse = 17 + /// Failed to load media assets from a VAST response. + case vastMediaLoadTimeout = 18 + /// The maximum number of VAST wrapper redirects has been reached. + case vastTooManyRedirects = 19 + /// Trafficking error. + /// + /// Video player received an ad type that it was not expecting and/or cannot + /// display. + case vastTraffickingError = 20 + /// Another VideoAdsManager is still using the video. + case videoElementUsed = 21 + /// A video element was not specified where it was required. + case videoElementRequired = 22 + /// There was an error playing the video ad. + case videoPlayError = 23 +} + +/// Different event types sent by the IMAAdsManager to its delegate. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAAdEventType.html. +enum AdEventType: Int { + /// Fired the first time each ad break ends. + case adBreakEnded = 0 + /// Fired when an ad break will not play back any ads. + case adBreakFetchError = 1 + /// Fired when an ad break is ready. + case adBreakReady = 2 + /// Fired first time each ad break begins playback. + case adBreakStarted = 3 + /// Fired every time the stream switches from advertising or slate to content. + case adPeriodEnded = 4 + /// Fired every time the stream switches from content to advertising or slate. + case adPeriodStarted = 5 + /// All valid ads managed by the ads manager have completed or the ad response + /// did not return any valid ads. + case allAdsCompleted = 6 + /// Fired when an ad is clicked. + case clicked = 7 + /// Single ad has finished. + case completed = 8 + /// Cuepoints changed for VOD stream (only used for dynamic ad insertion). + case cuepointsChanged = 9 + /// First quartile of a linear ad was reached. + case firstQuartile = 10 + /// The user has closed the icon fallback image dialog. + case iconFallbackImageClosed = 11 + /// The user has tapped an ad icon. + case iconTapped = 12 + /// An ad was loaded. + case loaded = 13 + /// A log event for the ads being played. + case log = 14 + /// Midpoint of a linear ad was reached. + case midpoint = 15 + /// Ad paused. + case pause = 16 + /// Ad resumed. + case resume = 17 + /// Fired when an ad was skipped. + case skipped = 18 + /// Fired when an ad starts playing. + case started = 19 + /// Stream request has loaded (only used for dynamic ad insertion). + case streamLoaded = 20 + /// Stream has started playing (only used for dynamic ad insertion). + case streamStarted = 21 + /// Ad tapped. + case tapped = 22 + /// Third quartile of a linear ad was reached.. + case thirdQuartile = 23 + /// The event type is not recognized by this wrapper. + case unknown = 24 +} + +/// The values that can be returned in a change dictionary. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvalueobservingoptions?language=objc. +enum KeyValueObservingOptions: Int { + /// Indicates that the change dictionary should provide the new attribute + /// value, if applicable. + case newValue = 0 + /// Indicates that the change dictionary should contain the old attribute + /// value, if applicable. + case oldValue = 1 + /// If specified, a notification should be sent to the observer immediately, + /// before the observer registration method even returns. + case initialValue = 2 + /// Whether separate notifications should be sent to the observer before and + /// after each change, instead of a single notification after the change. + case priorNotification = 3 +} + +/// The kinds of changes that can be observed.. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvaluechange?language=objc. +enum KeyValueChange: Int { + /// Indicates that the value of the observed key path was set to a new value. + case setting = 0 + /// Indicates that an object has been inserted into the to-many relationship + /// that is being observed. + case insertion = 1 + /// Indicates that an object has been removed from the to-many relationship + /// that is being observed. + case removal = 2 + /// Indicates that an object has been replaced in the to-many relationship + /// that is being observed. + case replacement = 3 +} + +/// The keys that can appear in the change dictionary.. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvaluechangekey?language=objc. +enum KeyValueChangeKey: Int { + /// If the value of the kindKey entry is NSKeyValueChange.insertion, + /// NSKeyValueChange.removal, or NSKeyValueChange.replacement, the value of + /// this key is an NSIndexSet object that contains the indexes of the + /// inserted, removed, or replaced objects. + case indexes = 0 + /// An NSNumber object that contains a value corresponding to one of the + /// NSKeyValueChange enums, indicating what sort of change has occurred. + case kind = 1 + /// If the value of the kindKey entry is NSKeyValueChange.setting, and new was + /// specified when the observer was registered, the value of this key is the + /// new value for the attribute. + case newValue = 2 + /// If the prior option was specified when the observer was registered this + /// notification is sent prior to a change. + case notificationIsPrior = 3 + /// If the value of the kindKey entry is NSKeyValueChange.setting, and old was + /// specified when the observer was registered, the value of this key is the + /// value before the attribute was changed. + case oldValue = 4 + /// The key is not recognized by this wrapper. + case unknown = 5 +} +private class InteractiveMediaAdsLibraryPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + var enumResult: AdErrorType? = nil + let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int) + if let enumResultAsInt = enumResultAsInt { + enumResult = AdErrorType(rawValue: enumResultAsInt) + } + return enumResult + case 130: + var enumResult: AdErrorCode? = nil + let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int) + if let enumResultAsInt = enumResultAsInt { + enumResult = AdErrorCode(rawValue: enumResultAsInt) + } + return enumResult + case 131: + var enumResult: AdEventType? = nil + let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int) + if let enumResultAsInt = enumResultAsInt { + enumResult = AdEventType(rawValue: enumResultAsInt) + } + return enumResult + case 132: + var enumResult: KeyValueObservingOptions? = nil + let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int) + if let enumResultAsInt = enumResultAsInt { + enumResult = KeyValueObservingOptions(rawValue: enumResultAsInt) + } + return enumResult + case 133: + var enumResult: KeyValueChange? = nil + let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int) + if let enumResultAsInt = enumResultAsInt { + enumResult = KeyValueChange(rawValue: enumResultAsInt) + } + return enumResult + case 134: + var enumResult: KeyValueChangeKey? = nil + let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int) + if let enumResultAsInt = enumResultAsInt { + enumResult = KeyValueChangeKey(rawValue: enumResultAsInt) + } + return enumResult + default: + return super.readValue(ofType: type) + } + } +} + +private class InteractiveMediaAdsLibraryPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? AdErrorType { + super.writeByte(129) + super.writeValue(value.rawValue) + } else if let value = value as? AdErrorCode { + super.writeByte(130) + super.writeValue(value.rawValue) + } else if let value = value as? AdEventType { + super.writeByte(131) + super.writeValue(value.rawValue) + } else if let value = value as? KeyValueObservingOptions { + super.writeByte(132) + super.writeValue(value.rawValue) + } else if let value = value as? KeyValueChange { + super.writeByte(133) + super.writeValue(value.rawValue) + } else if let value = value as? KeyValueChangeKey { + super.writeByte(134) + super.writeValue(value.rawValue) + } else { + super.writeValue(value) + } + } +} + +private class InteractiveMediaAdsLibraryPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return InteractiveMediaAdsLibraryPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return InteractiveMediaAdsLibraryPigeonCodecWriter(data: data) + } +} + +class InteractiveMediaAdsLibraryPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = InteractiveMediaAdsLibraryPigeonCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonCodecReaderWriter()) +} + +protocol PigeonApiDelegateIMAAdDisplayContainer { + func pigeonDefaultConstructor( + pigeonApi: PigeonApiIMAAdDisplayContainer, adContainer: UIView, + adContainerViewController: UIViewController? + ) throws -> IMAAdDisplayContainer +} + +protocol PigeonApiProtocolIMAAdDisplayContainer { +} + +final class PigeonApiIMAAdDisplayContainer: PigeonApiProtocolIMAAdDisplayContainer { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdDisplayContainer + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdDisplayContainer + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAAdDisplayContainer? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.interactive_media_ads.IMAAdDisplayContainer.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + let adContainerArg = args[1] as! UIView + let adContainerViewControllerArg: UIViewController? = nilOrValue(args[2]) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api, adContainer: adContainerArg, + adContainerViewController: adContainerViewControllerArg), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAAdDisplayContainer and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdDisplayContainer, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdDisplayContainer.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +open class PigeonApiDelegateUIView { +} + +protocol PigeonApiProtocolUIView { +} + +final class PigeonApiUIView: PigeonApiProtocolUIView { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateUIView + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateUIView + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of UIView and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: UIView, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.interactive_media_ads.UIView.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateUIViewController { + func pigeonDefaultConstructor(pigeonApi: PigeonApiUIViewController) throws -> UIViewController + /// Retrieves the view that the controller manages. + /// + /// For convenience this is a `final` attached field despite this being + /// settable. Since this is not a part of the IMA SDK this is slightly changed + /// for convenience. Note that this wrapper should not add the ability to set + /// this property as it should not be needed anyways. + func view(pigeonApi: PigeonApiUIViewController, pigeonInstance: UIViewController) throws -> UIView +} + +protocol PigeonApiProtocolUIViewController { + /// Notifies the view controller that its view was added to a view hierarchy. + func viewDidAppear( + pigeonInstance pigeonInstanceArg: UIViewController, animated animatedArg: Bool, + completion: @escaping (Result) -> Void) +} + +final class PigeonApiUIViewController: PigeonApiProtocolUIViewController { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateUIViewController + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateUIViewController + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiUIViewController? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.UIViewController.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + let viewChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.UIViewController.view", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + viewChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! UIViewController + let pigeonIdentifierArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.view(pigeonApi: api, pigeonInstance: pigeonInstanceArg), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + viewChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of UIViewController and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: UIViewController, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.UIViewController.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + /// Notifies the view controller that its view was added to a view hierarchy. + func viewDidAppear( + pigeonInstance pigeonInstanceArg: UIViewController, animated animatedArg: Bool, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.UIViewController.viewDidAppear" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, animatedArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + +} +protocol PigeonApiDelegateIMAContentPlayhead { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAContentPlayhead) throws -> IMAContentPlayhead + /// Reflects the current playback time in seconds for the content. + func setCurrentTime( + pigeonApi: PigeonApiIMAContentPlayhead, pigeonInstance: IMAContentPlayhead, timeInterval: Double + ) throws +} + +protocol PigeonApiProtocolIMAContentPlayhead { +} + +final class PigeonApiIMAContentPlayhead: PigeonApiProtocolIMAContentPlayhead { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAContentPlayhead + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAContentPlayhead + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAContentPlayhead? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + let setCurrentTimeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.setCurrentTime", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setCurrentTimeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAContentPlayhead + let timeIntervalArg = args[1] as! Double + do { + try api.pigeonDelegate.setCurrentTime( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, timeInterval: timeIntervalArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setCurrentTimeChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAContentPlayhead and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAContentPlayhead, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdsLoader { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsLoader, settings: IMASettings?) throws + -> IMAAdsLoader + /// Signal to the SDK that the content has completed. + func contentComplete(pigeonApi: PigeonApiIMAAdsLoader, pigeonInstance: IMAAdsLoader) throws + /// Request ads from the ad server. + func requestAds( + pigeonApi: PigeonApiIMAAdsLoader, pigeonInstance: IMAAdsLoader, request: IMAAdsRequest) throws + /// Delegate that receives `IMAAdsLoaderDelegate` callbacks. + /// + /// Note that this sets to a `weak` property in Swift. + func setDelegate( + pigeonApi: PigeonApiIMAAdsLoader, pigeonInstance: IMAAdsLoader, delegate: IMAAdsLoaderDelegate?) + throws +} + +protocol PigeonApiProtocolIMAAdsLoader { +} + +final class PigeonApiIMAAdsLoader: PigeonApiProtocolIMAAdsLoader { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdsLoader + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdsLoader + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAAdsLoader? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + let settingsArg: IMASettings? = nilOrValue(args[1]) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api, settings: settingsArg), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + let contentCompleteChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.contentComplete", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + contentCompleteChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsLoader + do { + try api.pigeonDelegate.contentComplete(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + contentCompleteChannel.setMessageHandler(nil) + } + let requestAdsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.requestAds", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + requestAdsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsLoader + let requestArg = args[1] as! IMAAdsRequest + do { + try api.pigeonDelegate.requestAds( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, request: requestArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + requestAdsChannel.setMessageHandler(nil) + } + let setDelegateChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.setDelegate", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setDelegateChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsLoader + let delegateArg: IMAAdsLoaderDelegate? = nilOrValue(args[1]) + do { + try api.pigeonDelegate.setDelegate( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, delegate: delegateArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setDelegateChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAAdsLoader and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdsLoader, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +open class PigeonApiDelegateIMASettings { +} + +protocol PigeonApiProtocolIMASettings { +} + +final class PigeonApiIMASettings: PigeonApiProtocolIMASettings { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMASettings + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMASettings + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of IMASettings and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMASettings, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMASettings.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdsRequest { + /// Initializes an ads request instance with the given ad tag URL and ad + /// display container. + func pigeonDefaultConstructor( + pigeonApi: PigeonApiIMAAdsRequest, adTagUrl: String, adDisplayContainer: IMAAdDisplayContainer, + contentPlayhead: IMAContentPlayhead? + ) throws -> IMAAdsRequest +} + +protocol PigeonApiProtocolIMAAdsRequest { +} + +final class PigeonApiIMAAdsRequest: PigeonApiProtocolIMAAdsRequest { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdsRequest + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdsRequest + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAAdsRequest? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsRequest.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + let adTagUrlArg = args[1] as! String + let adDisplayContainerArg = args[2] as! IMAAdDisplayContainer + let contentPlayheadArg: IMAContentPlayhead? = nilOrValue(args[3]) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api, adTagUrl: adTagUrlArg, adDisplayContainer: adDisplayContainerArg, + contentPlayhead: contentPlayheadArg), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAAdsRequest and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdsRequest, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsRequest.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdsLoaderDelegate { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsLoaderDelegate) throws + -> IMAAdsLoaderDelegate +} + +protocol PigeonApiProtocolIMAAdsLoaderDelegate { + /// Called when ads are successfully loaded from the ad servers by the loader. + func adLoaderLoadedWith( + pigeonInstance pigeonInstanceArg: IMAAdsLoaderDelegate, loader loaderArg: IMAAdsLoader, + adsLoadedData adsLoadedDataArg: IMAAdsLoadedData, + completion: @escaping (Result) -> Void) + /// Error reported by the ads loader when loading or requesting an ad fails. + func adsLoaderFailedWithErrorData( + pigeonInstance pigeonInstanceArg: IMAAdsLoaderDelegate, loader loaderArg: IMAAdsLoader, + adErrorData adErrorDataArg: IMAAdLoadingErrorData, + completion: @escaping (Result) -> Void) +} + +final class PigeonApiIMAAdsLoaderDelegate: PigeonApiProtocolIMAAdsLoaderDelegate { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdsLoaderDelegate + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdsLoaderDelegate + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAAdsLoaderDelegate? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAAdsLoaderDelegate and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdsLoaderDelegate, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + print( + "Error: Attempting to create a new Dart instance of IMAAdsLoaderDelegate, but the class has a nonnull callback method." + ) + } + /// Called when ads are successfully loaded from the ad servers by the loader. + func adLoaderLoadedWith( + pigeonInstance pigeonInstanceArg: IMAAdsLoaderDelegate, loader loaderArg: IMAAdsLoader, + adsLoadedData adsLoadedDataArg: IMAAdsLoadedData, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adLoaderLoadedWith" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, loaderArg, adsLoadedDataArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + + /// Error reported by the ads loader when loading or requesting an ad fails. + func adsLoaderFailedWithErrorData( + pigeonInstance pigeonInstanceArg: IMAAdsLoaderDelegate, loader loaderArg: IMAAdsLoader, + adErrorData adErrorDataArg: IMAAdLoadingErrorData, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adsLoaderFailedWithErrorData" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, loaderArg, adErrorDataArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + +} +protocol PigeonApiDelegateIMAAdsLoadedData { + /// The ads manager instance created by the ads loader. + /// + /// Will be null when using dynamic ad insertion. + func adsManager(pigeonApi: PigeonApiIMAAdsLoadedData, pigeonInstance: IMAAdsLoadedData) throws + -> IMAAdsManager? +} + +protocol PigeonApiProtocolIMAAdsLoadedData { +} + +final class PigeonApiIMAAdsLoadedData: PigeonApiProtocolIMAAdsLoadedData { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdsLoadedData + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdsLoadedData + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of IMAAdsLoadedData and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdsLoadedData, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let adsManagerArg = try! pigeonDelegate.adsManager( + pigeonApi: self, pigeonInstance: pigeonInstance) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsLoadedData.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg, adsManagerArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdLoadingErrorData { + /// The ad error that occurred while loading the ad. + func adError(pigeonApi: PigeonApiIMAAdLoadingErrorData, pigeonInstance: IMAAdLoadingErrorData) + throws -> IMAAdError +} + +protocol PigeonApiProtocolIMAAdLoadingErrorData { +} + +final class PigeonApiIMAAdLoadingErrorData: PigeonApiProtocolIMAAdLoadingErrorData { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdLoadingErrorData + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdLoadingErrorData + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of IMAAdLoadingErrorData and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdLoadingErrorData, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let adErrorArg = try! pigeonDelegate.adError(pigeonApi: self, pigeonInstance: pigeonInstance) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdLoadingErrorData.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg, adErrorArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdError { + /// The type of error that occurred during ad loading or ad playing. + func type(pigeonApi: PigeonApiIMAAdError, pigeonInstance: IMAAdError) throws -> AdErrorType + /// The error code for obtaining more specific information about the error. + func code(pigeonApi: PigeonApiIMAAdError, pigeonInstance: IMAAdError) throws -> AdErrorCode + /// A brief description about the error. + func message(pigeonApi: PigeonApiIMAAdError, pigeonInstance: IMAAdError) throws -> String? +} + +protocol PigeonApiProtocolIMAAdError { +} + +final class PigeonApiIMAAdError: PigeonApiProtocolIMAAdError { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdError + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdError + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of IMAAdError and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdError, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let typeArg = try! pigeonDelegate.type(pigeonApi: self, pigeonInstance: pigeonInstance) + let codeArg = try! pigeonDelegate.code(pigeonApi: self, pigeonInstance: pigeonInstance) + let messageArg = try! pigeonDelegate.message(pigeonApi: self, pigeonInstance: pigeonInstance) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdError.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg, typeArg, codeArg, messageArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdsManager { + /// The `IMAAdsManagerDelegate` to notify with events during ad playback. + func setDelegate( + pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager, + delegate: IMAAdsManagerDelegate?) throws + /// Initializes and loads the ad. + func initialize( + pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager, + adsRenderingSettings: IMAAdsRenderingSettings?) throws + /// Starts advertisement playback. + func start(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws + /// Pauses advertisement. + func pause(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws + /// Resumes the current ad. + func resume(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws + /// Skips the advertisement if the ad is skippable and the skip offset has + /// been reached. + func skip(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws + /// If an ad break is currently playing, discard it and resume content. + func discardAdBreak(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws + /// Causes the ads manager to stop the ad and clean its internal state. + func destroy(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws +} + +protocol PigeonApiProtocolIMAAdsManager { +} + +final class PigeonApiIMAAdsManager: PigeonApiProtocolIMAAdsManager { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdsManager + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdsManager + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAAdsManager? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let setDelegateChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.setDelegate", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setDelegateChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + let delegateArg: IMAAdsManagerDelegate? = nilOrValue(args[1]) + do { + try api.pigeonDelegate.setDelegate( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, delegate: delegateArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setDelegateChannel.setMessageHandler(nil) + } + let initializeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.initialize", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + initializeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + let adsRenderingSettingsArg: IMAAdsRenderingSettings? = nilOrValue(args[1]) + do { + try api.pigeonDelegate.initialize( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, + adsRenderingSettings: adsRenderingSettingsArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + initializeChannel.setMessageHandler(nil) + } + let startChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.start", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + startChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + do { + try api.pigeonDelegate.start(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + startChannel.setMessageHandler(nil) + } + let pauseChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pause", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pauseChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + do { + try api.pigeonDelegate.pause(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pauseChannel.setMessageHandler(nil) + } + let resumeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.resume", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + resumeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + do { + try api.pigeonDelegate.resume(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + resumeChannel.setMessageHandler(nil) + } + let skipChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.skip", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + skipChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + do { + try api.pigeonDelegate.skip(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + skipChannel.setMessageHandler(nil) + } + let discardAdBreakChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.discardAdBreak", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + discardAdBreakChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + do { + try api.pigeonDelegate.discardAdBreak(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + discardAdBreakChannel.setMessageHandler(nil) + } + let destroyChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.destroy", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + destroyChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! IMAAdsManager + do { + try api.pigeonDelegate.destroy(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + destroyChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAAdsManager and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdsManager, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdsManagerDelegate { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsManagerDelegate) throws + -> IMAAdsManagerDelegate +} + +protocol PigeonApiProtocolIMAAdsManagerDelegate { + /// Called when there is an IMAAdEvent. + func didReceiveAdEvent( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, event eventArg: IMAAdEvent, + completion: @escaping (Result) -> Void) + /// Called when there was an error playing the ad. + func didReceiveAdError( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, error errorArg: IMAAdError, + completion: @escaping (Result) -> Void) + /// Called when an ad is ready to play. + func didRequestContentPause( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, + completion: @escaping (Result) -> Void) + /// Called when an ad has finished or an error occurred during the playback. + func didRequestContentResume( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, + completion: @escaping (Result) -> Void) +} + +final class PigeonApiIMAAdsManagerDelegate: PigeonApiProtocolIMAAdsManagerDelegate { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdsManagerDelegate + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdsManagerDelegate + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAAdsManagerDelegate? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAAdsManagerDelegate and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdsManagerDelegate, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + print( + "Error: Attempting to create a new Dart instance of IMAAdsManagerDelegate, but the class has a nonnull callback method." + ) + } + /// Called when there is an IMAAdEvent. + func didReceiveAdEvent( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, event eventArg: IMAAdEvent, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdEvent" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, adsManagerArg, eventArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + + /// Called when there was an error playing the ad. + func didReceiveAdError( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, error errorArg: IMAAdError, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdError" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, adsManagerArg, errorArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + + /// Called when an ad is ready to play. + func didRequestContentPause( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentPause" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, adsManagerArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + + /// Called when an ad has finished or an error occurred during the playback. + func didRequestContentResume( + pigeonInstance pigeonInstanceArg: IMAAdsManagerDelegate, + adsManager adsManagerArg: IMAAdsManager, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentResume" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, adsManagerArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } + +} +protocol PigeonApiDelegateIMAAdEvent { + /// Type of the event. + func type(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> AdEventType + /// Stringified type of the event. + func typeString(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> String +} + +protocol PigeonApiProtocolIMAAdEvent { +} + +final class PigeonApiIMAAdEvent: PigeonApiProtocolIMAAdEvent { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdEvent + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdEvent + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of IMAAdEvent and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdEvent, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let typeArg = try! pigeonDelegate.type(pigeonApi: self, pigeonInstance: pigeonInstance) + let typeStringArg = try! pigeonDelegate.typeString( + pigeonApi: self, pigeonInstance: pigeonInstance) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdEvent.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg, typeArg, typeStringArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +protocol PigeonApiDelegateIMAAdsRenderingSettings { + func pigeonDefaultConstructor(pigeonApi: PigeonApiIMAAdsRenderingSettings) throws + -> IMAAdsRenderingSettings +} + +protocol PigeonApiProtocolIMAAdsRenderingSettings { +} + +final class PigeonApiIMAAdsRenderingSettings: PigeonApiProtocolIMAAdsRenderingSettings { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateIMAAdsRenderingSettings + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateIMAAdsRenderingSettings + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiIMAAdsRenderingSettings? + ) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: InteractiveMediaAdsLibraryPigeonProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.interactive_media_ads.IMAAdsRenderingSettings.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32) + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of IMAAdsRenderingSettings and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: IMAAdsRenderingSettings, + completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = + "dev.flutter.pigeon.interactive_media_ads.IMAAdsRenderingSettings.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} +open class PigeonApiDelegateNSObject { +} + +protocol PigeonApiProtocolNSObject { +} + +final class PigeonApiNSObject: PigeonApiProtocolNSObject { + unowned let pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateNSObject + init( + pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateNSObject + ) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of NSObject and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: NSObject, completion: @escaping (Result) -> Void + ) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } + if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(Void())) + return + } + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.interactive_media_ads.NSObject.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(Void())) + } + } + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsPlugin.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsPlugin.swift index 5b94fd6a24aad..e0bc5caec0af6 100644 --- a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsPlugin.swift +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsPlugin.swift @@ -6,19 +6,24 @@ import Flutter import UIKit public class InteractiveMediaAdsPlugin: NSObject, FlutterPlugin { + var proxyApiRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar? + + init(binaryMessenger: FlutterBinaryMessenger) { + proxyApiRegistrar = InteractiveMediaAdsLibraryPigeonProxyApiRegistrar( + binaryMessenger: binaryMessenger, apiDelegate: ProxyApiDelegate()) + proxyApiRegistrar?.setUp() + } + public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel( - name: "interactive_media_ads", binaryMessenger: registrar.messenger()) - let instance = InteractiveMediaAdsPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) + let plugin = InteractiveMediaAdsPlugin(binaryMessenger: registrar.messenger()) + let viewFactory = FlutterViewFactory(instanceManager: plugin.proxyApiRegistrar!.instanceManager) + registrar.register(viewFactory, withId: "interactive_media_ads.packages.flutter.dev/view") + registrar.publish(plugin) } - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "getPlatformVersion": - result("iOS " + UIDevice.current.systemVersion) - default: - result(FlutterMethodNotImplemented) - } + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + proxyApiRegistrar!.ignoreCallsToDart = true + proxyApiRegistrar!.tearDown() + proxyApiRegistrar = nil } } diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ProxyApiDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ProxyApiDelegate.swift new file mode 100644 index 0000000000000..fc3a28cc7f77e --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ProxyApiDelegate.swift @@ -0,0 +1,112 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import GoogleInteractiveMediaAds + +/// Implementation of `PigeonProxyApiDelegate` that provides each ProxyApi delegate implementation +/// and any additional resources needed by an implementation. +open class ProxyApiDelegate: InteractiveMediaAdsLibraryPigeonProxyApiDelegate { + func pigeonApiUIView(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiUIView + { + return PigeonApiUIView(pigeonRegistrar: registrar, delegate: ViewProxyAPIDelegate()) + } + + func pigeonApiIMAAdDisplayContainer( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) + -> PigeonApiIMAAdDisplayContainer + { + return PigeonApiIMAAdDisplayContainer( + pigeonRegistrar: registrar, delegate: AdDisplayContainerProxyAPIDelegate()) + } + + func pigeonApiUIViewController(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiUIViewController + { + return PigeonApiUIViewController( + pigeonRegistrar: registrar, delegate: ViewControllerProxyAPIDelegate()) + } + + func pigeonApiIMAContentPlayhead(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAContentPlayhead + { + return PigeonApiIMAContentPlayhead( + pigeonRegistrar: registrar, delegate: ContentPlayheadProxyAPIDelegate()) + } + + func pigeonApiIMAAdsLoader(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsLoader + { + return PigeonApiIMAAdsLoader(pigeonRegistrar: registrar, delegate: AdsLoaderProxyAPIDelegate()) + } + + func pigeonApiIMAAdsRequest(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsRequest + { + return PigeonApiIMAAdsRequest( + pigeonRegistrar: registrar, delegate: AdsRequestProxyAPIDelegate()) + } + + func pigeonApiIMAAdsLoaderDelegate(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsLoaderDelegate + { + return PigeonApiIMAAdsLoaderDelegate( + pigeonRegistrar: registrar, delegate: AdsLoaderDelegateProxyAPIDelegate()) + } + + func pigeonApiIMAAdsLoadedData(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsLoadedData + { + return PigeonApiIMAAdsLoadedData( + pigeonRegistrar: registrar, delegate: AdsLoadedDataProxyAPIDelegate()) + } + + func pigeonApiIMAAdLoadingErrorData( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) + -> PigeonApiIMAAdLoadingErrorData + { + return PigeonApiIMAAdLoadingErrorData( + pigeonRegistrar: registrar, delegate: AdLoadingErrorDataProxyAPIDelegate()) + } + + func pigeonApiIMAAdError(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdError + { + return PigeonApiIMAAdError(pigeonRegistrar: registrar, delegate: AdErrorProxyAPIDelegate()) + } + + func pigeonApiIMAAdsManager(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdsManager + { + return PigeonApiIMAAdsManager( + pigeonRegistrar: registrar, delegate: AdsManagerProxyAPIDelegate()) + } + + func pigeonApiIMAAdsManagerDelegate( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) + -> PigeonApiIMAAdsManagerDelegate + { + return PigeonApiIMAAdsManagerDelegate( + pigeonRegistrar: registrar, delegate: AdsManagerDelegateProxyAPIDelegate()) + } + + func pigeonApiIMAAdEvent(_ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar) + -> PigeonApiIMAAdEvent + { + return PigeonApiIMAAdEvent(pigeonRegistrar: registrar, delegate: AdEventProxyAPIDelegate()) + } + + func pigeonApiIMAAdsRenderingSettings( + _ registrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar + ) + -> PigeonApiIMAAdsRenderingSettings + { + PigeonApiIMAAdsRenderingSettings( + pigeonRegistrar: registrar, delegate: AdsRenderingSettingsProxyAPIDelegate()) + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewControllerProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewControllerProxyAPIDelegate.swift new file mode 100644 index 0000000000000..623ad1dd1e0ad --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewControllerProxyAPIDelegate.swift @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import UIKit + +class ViewControllerImpl: UIViewController { + let api: PigeonApiProtocolUIViewController + + init(api: PigeonApiProtocolUIViewController) { + self.api = api + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidAppear(_ animated: Bool) { + api.viewDidAppear(pigeonInstance: self, animated: animated) { _ in } + } +} + +/// ProxyApi delegate implementation for `UIViewController`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class ViewControllerProxyAPIDelegate: PigeonApiDelegateUIViewController { + func pigeonDefaultConstructor(pigeonApi: PigeonApiUIViewController) throws -> UIViewController { + return ViewControllerImpl(api: pigeonApi) + } + + func view(pigeonApi: PigeonApiUIViewController, pigeonInstance: UIViewController) throws -> UIView + { + return pigeonInstance.view + } +} diff --git a/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewProxyAPIDelegate.swift b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewProxyAPIDelegate.swift new file mode 100644 index 0000000000000..1352a6fa26965 --- /dev/null +++ b/packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/ViewProxyAPIDelegate.swift @@ -0,0 +1,16 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import UIKit + +/// ProxyApi delegate implementation for `UIView`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart +/// instance or handle method calls on the associated native class or an instance of that class. +class ViewProxyAPIDelegate: PigeonApiDelegateUIView { + func getWindow(pigeonApi: PigeonApiUIView, pigeonInstance: UIView) throws -> UIWindow? { + return pigeonInstance.window + } +} diff --git a/packages/interactive_media_ads/lib/interactive_media_ads.dart b/packages/interactive_media_ads/lib/interactive_media_ads.dart index b9e2aee98a3cb..954a27c9049ab 100644 --- a/packages/interactive_media_ads/lib/interactive_media_ads.dart +++ b/packages/interactive_media_ads/lib/interactive_media_ads.dart @@ -7,6 +7,7 @@ export 'src/ads_loader.dart'; export 'src/ads_manager_delegate.dart'; export 'src/android/android_interactive_media_ads.dart' show AndroidInteractiveMediaAds; +export 'src/ios/ios_interactive_media_ads.dart' show IOSInteractiveMediaAds; export 'src/platform_interface/platform_interface.dart' show AdError, diff --git a/packages/interactive_media_ads/lib/src/ad_display_container.dart b/packages/interactive_media_ads/lib/src/ad_display_container.dart index cc254a33e51d1..9c4aeed93872b 100644 --- a/packages/interactive_media_ads/lib/src/ad_display_container.dart +++ b/packages/interactive_media_ads/lib/src/ad_display_container.dart @@ -37,6 +37,7 @@ class AdDisplayContainer extends StatelessWidget { AdDisplayContainer({ Key? key, required void Function(AdDisplayContainer container) onContainerAdded, + TextDirection layoutDirection = TextDirection.ltr, }) : this.fromPlatformCreationParams( key: key, params: PlatformAdDisplayContainerCreationParams( @@ -45,6 +46,7 @@ class AdDisplayContainer extends StatelessWidget { platform: container, )); }, + layoutDirection: layoutDirection, ), ); @@ -95,6 +97,9 @@ class AdDisplayContainer extends StatelessWidget { void Function(PlatformAdDisplayContainer container) get onContainerAdded => platform.params.onContainerAdded; + /// The layout direction to use for the embedded AdDisplayContainer. + TextDirection get layoutDirection => platform.params.layoutDirection; + @override Widget build(BuildContext context) { return platform.build(context); diff --git a/packages/interactive_media_ads/lib/src/android/android_ad_display_container.dart b/packages/interactive_media_ads/lib/src/android/android_ad_display_container.dart index 9822a78f7c394..2c5f2c8eb8096 100644 --- a/packages/interactive_media_ads/lib/src/android/android_ad_display_container.dart +++ b/packages/interactive_media_ads/lib/src/android/android_ad_display_container.dart @@ -132,6 +132,7 @@ base class AndroidAdDisplayContainer extends PlatformAdDisplayContainer { key: params.key, view: _frameLayout, platformViewsServiceProxy: _androidParams._platformViewsProxy, + layoutDirection: params.layoutDirection, onPlatformViewCreated: () async { adDisplayContainer = await _androidParams._imaProxy .createAdDisplayContainerImaSdkFactory( diff --git a/packages/interactive_media_ads/lib/src/android/android_ads_loader.dart b/packages/interactive_media_ads/lib/src/android/android_ads_loader.dart index 03fde8d22f228..58fe19c0bdc8b 100644 --- a/packages/interactive_media_ads/lib/src/android/android_ads_loader.dart +++ b/packages/interactive_media_ads/lib/src/android/android_ads_loader.dart @@ -9,7 +9,7 @@ import 'package:flutter/widgets.dart'; import '../platform_interface/platform_interface.dart'; import 'android_ad_display_container.dart'; import 'android_ads_manager.dart'; -import 'enum_converter_extensions.dart'; +import 'enum_converter_utils.dart'; import 'interactive_media_ads.g.dart' as ima; import 'interactive_media_ads_proxy.dart'; @@ -131,8 +131,8 @@ base class AndroidAdsLoader extends PlatformAdsLoader { weakThis.target?.params.onAdsLoadError( AdsLoadErrorData( error: AdError( - type: event.error.errorType.asInterfaceErrorType(), - code: event.error.errorCode.asInterfaceErrorCode(), + type: toInterfaceErrorType(event.error.errorType), + code: toInterfaceErrorCode(event.error.errorCode), message: event.error.message, ), ), diff --git a/packages/interactive_media_ads/lib/src/android/android_ads_manager.dart b/packages/interactive_media_ads/lib/src/android/android_ads_manager.dart index 7bf158ff52ada..bca0a69f55a1a 100644 --- a/packages/interactive_media_ads/lib/src/android/android_ads_manager.dart +++ b/packages/interactive_media_ads/lib/src/android/android_ads_manager.dart @@ -7,7 +7,7 @@ import 'dart:async'; import 'package:meta/meta.dart'; import '../platform_interface/platform_interface.dart'; -import 'enum_converter_extensions.dart'; +import 'enum_converter_utils.dart'; import 'interactive_media_ads.g.dart' as ima; import 'interactive_media_ads_proxy.dart'; @@ -57,8 +57,7 @@ class AndroidAdsManager extends PlatformAdsManager { weakThis.target?._manager.addAdEventListener( proxy.newAdEventListener( onAdEvent: (_, ima.AdEvent event) { - late final AdEventType? eventType = - event.type.asInterfaceAdEventType(); + late final AdEventType? eventType = toInterfaceEventType(event.type); if (eventType == null) { return; } @@ -74,8 +73,8 @@ class AndroidAdsManager extends PlatformAdsManager { weakThis.target?._managerDelegate?.params.onAdErrorEvent?.call( AdErrorEvent( error: AdError( - type: event.error.errorType.asInterfaceErrorType(), - code: event.error.errorCode.asInterfaceErrorCode(), + type: toInterfaceErrorType(event.error.errorType), + code: toInterfaceErrorCode(event.error.errorCode), message: event.error.message, ), ), diff --git a/packages/interactive_media_ads/lib/src/android/android_view_widget.dart b/packages/interactive_media_ads/lib/src/android/android_view_widget.dart index a4c0b662e9878..3d6f9b8e6fc04 100644 --- a/packages/interactive_media_ads/lib/src/android/android_view_widget.dart +++ b/packages/interactive_media_ads/lib/src/android/android_view_widget.dart @@ -29,6 +29,10 @@ class AndroidViewWidget extends StatelessWidget { this.platformViewsServiceProxy = const PlatformViewsServiceProxy(), }) : instanceManager = instanceManager ?? ima.PigeonInstanceManager.instance; + /// The unique identifier for the view type to be embedded. + static const String _viewType = + 'interactive_media_ads.packages.flutter.dev/view'; + /// The reference to the Android native view that should be shown. final ima.View view; @@ -56,7 +60,7 @@ class AndroidViewWidget extends StatelessWidget { @override Widget build(BuildContext context) { return PlatformViewLink( - viewType: 'plugins.flutter.io/webview', + viewType: _viewType, surfaceFactory: ( BuildContext context, PlatformViewController controller, @@ -79,13 +83,12 @@ class AndroidViewWidget extends StatelessWidget { } AndroidViewController _initAndroidView(PlatformViewCreationParams params) { - const String viewType = 'interactive_media_ads.packages.flutter.dev/view'; final int? identifier = instanceManager.getIdentifier(view); if (displayWithHybridComposition) { return platformViewsServiceProxy.initExpensiveAndroidView( id: params.id, - viewType: viewType, + viewType: _viewType, layoutDirection: layoutDirection, creationParams: identifier, creationParamsCodec: const StandardMessageCodec(), @@ -93,7 +96,7 @@ class AndroidViewWidget extends StatelessWidget { } else { return platformViewsServiceProxy.initSurfaceAndroidView( id: params.id, - viewType: viewType, + viewType: _viewType, layoutDirection: layoutDirection, creationParams: identifier, creationParamsCodec: const StandardMessageCodec(), diff --git a/packages/interactive_media_ads/lib/src/android/enum_converter_extensions.dart b/packages/interactive_media_ads/lib/src/android/enum_converter_extensions.dart deleted file mode 100644 index 4d7293df4293e..0000000000000 --- a/packages/interactive_media_ads/lib/src/android/enum_converter_extensions.dart +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import '../platform_interface/platform_interface.dart'; -import 'interactive_media_ads.g.dart' as ima; - -/// Adds a method to convert native AdErrorType to platform interface -/// AdErrorType. -extension NativeAdErrorTypeConverter on ima.AdErrorType { - /// Converts [ima.AdErrorType] to [AdErrorType]. - AdErrorType asInterfaceErrorType() { - return switch (this) { - ima.AdErrorType.load => AdErrorType.loading, - ima.AdErrorType.play => AdErrorType.playing, - ima.AdErrorType.unknown => AdErrorType.unknown, - }; - } -} - -/// Adds a method to convert native AdEventType to platform interface -/// AdEventType. -extension NativeAdEventTypeConverter on ima.AdEventType { - /// Attempts to convert an [ima.AdEventType] to [AdEventType]. - /// - /// Returns null is the type is not supported by the platform interface. - AdEventType? asInterfaceAdEventType() { - return switch (this) { - ima.AdEventType.allAdsCompleted => AdEventType.allAdsCompleted, - ima.AdEventType.completed => AdEventType.complete, - ima.AdEventType.contentPauseRequested => - AdEventType.contentPauseRequested, - ima.AdEventType.contentResumeRequested => - AdEventType.contentResumeRequested, - ima.AdEventType.loaded => AdEventType.loaded, - ima.AdEventType.clicked => AdEventType.clicked, - _ => null, - }; - } -} - -/// Adds a method to convert native AdErrorCode to platform interface -/// AdErrorCode. -extension NativeAdErrorCodeConverter on ima.AdErrorCode { - /// Converts [ima.AdErrorCode] to [AdErrorCode]. - AdErrorCode asInterfaceErrorCode() { - return switch (this) { - ima.AdErrorCode.adsPlayerWasNotProvided => - AdErrorCode.adsPlayerNotProvided, - ima.AdErrorCode.adsRequestNetworkError => - AdErrorCode.adsRequestNetworkError, - ima.AdErrorCode.companionAdLoadingFailed => - AdErrorCode.companionAdLoadingFailed, - ima.AdErrorCode.failedToRequestAds => AdErrorCode.failedToRequestAds, - ima.AdErrorCode.internalError => AdErrorCode.internalError, - ima.AdErrorCode.invalidArguments => AdErrorCode.invalidArguments, - ima.AdErrorCode.overlayAdLoadingFailed => - AdErrorCode.overlayAdLoadingFailed, - ima.AdErrorCode.overlayAdPlayingFailed => - AdErrorCode.overlayAdPlayingFailed, - ima.AdErrorCode.playlistNoContentTracking => - AdErrorCode.playlistNoContentTracking, - ima.AdErrorCode.unexpectedAdsLoadedEvent => - AdErrorCode.unexpectedAdsLoadedEvent, - ima.AdErrorCode.unknownAdResponse => AdErrorCode.unknownAdResponse, - ima.AdErrorCode.unknownError => AdErrorCode.unknownError, - ima.AdErrorCode.vastAssetNotFound => AdErrorCode.vastAssetNotFound, - ima.AdErrorCode.vastEmptyResponse => AdErrorCode.vastEmptyResponse, - ima.AdErrorCode.vastLinearAssetMismatch => - AdErrorCode.vastLinearAssetMismatch, - ima.AdErrorCode.vastLoadTimeout => AdErrorCode.vastLoadTimeout, - ima.AdErrorCode.vastMalformedResponse => - AdErrorCode.vastMalformedResponse, - ima.AdErrorCode.vastMediaLoadTimeout => AdErrorCode.vastMediaLoadTimeout, - ima.AdErrorCode.vastNonlinearAssetMismatch => - AdErrorCode.vastNonlinearAssetMismatch, - ima.AdErrorCode.vastNoAdsAfterWrapper => - AdErrorCode.vastNoAdsAfterWrapper, - ima.AdErrorCode.vastTooManyRedirects => AdErrorCode.vastTooManyRedirects, - ima.AdErrorCode.vastTraffickingError => AdErrorCode.vastTraffickingError, - ima.AdErrorCode.videoPlayError => AdErrorCode.videoPlayError, - ima.AdErrorCode.unknown => AdErrorCode.unknownError, - }; - } -} diff --git a/packages/interactive_media_ads/lib/src/android/enum_converter_utils.dart b/packages/interactive_media_ads/lib/src/android/enum_converter_utils.dart new file mode 100644 index 0000000000000..75882b93e2b18 --- /dev/null +++ b/packages/interactive_media_ads/lib/src/android/enum_converter_utils.dart @@ -0,0 +1,69 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../platform_interface/platform_interface.dart'; +import 'interactive_media_ads.g.dart' as ima; + +/// Converts [ima.AdErrorType] to [AdErrorType]. +AdErrorType toInterfaceErrorType(ima.AdErrorType type) { + return switch (type) { + ima.AdErrorType.load => AdErrorType.loading, + ima.AdErrorType.play => AdErrorType.playing, + ima.AdErrorType.unknown => AdErrorType.unknown, + }; +} + +/// Attempts to convert an [ima.AdEventType] to [AdEventType]. +/// +/// Returns null is the type is not supported by the platform interface. +AdEventType? toInterfaceEventType(ima.AdEventType type) { + return switch (type) { + ima.AdEventType.allAdsCompleted => AdEventType.allAdsCompleted, + ima.AdEventType.completed => AdEventType.complete, + ima.AdEventType.contentPauseRequested => AdEventType.contentPauseRequested, + ima.AdEventType.contentResumeRequested => + AdEventType.contentResumeRequested, + ima.AdEventType.loaded => AdEventType.loaded, + ima.AdEventType.clicked => AdEventType.clicked, + _ => null, + }; +} + +/// Converts [ima.AdErrorCode] to [AdErrorCode]. +AdErrorCode toInterfaceErrorCode(ima.AdErrorCode code) { + return switch (code) { + ima.AdErrorCode.adsPlayerWasNotProvided => AdErrorCode.adsPlayerNotProvided, + ima.AdErrorCode.adsRequestNetworkError => + AdErrorCode.adsRequestNetworkError, + ima.AdErrorCode.companionAdLoadingFailed => + AdErrorCode.companionAdLoadingFailed, + ima.AdErrorCode.failedToRequestAds => AdErrorCode.failedToRequestAds, + ima.AdErrorCode.internalError => AdErrorCode.internalError, + ima.AdErrorCode.invalidArguments => AdErrorCode.invalidArguments, + ima.AdErrorCode.overlayAdLoadingFailed => + AdErrorCode.overlayAdLoadingFailed, + ima.AdErrorCode.overlayAdPlayingFailed => + AdErrorCode.overlayAdPlayingFailed, + ima.AdErrorCode.playlistNoContentTracking => + AdErrorCode.playlistNoContentTracking, + ima.AdErrorCode.unexpectedAdsLoadedEvent => + AdErrorCode.unexpectedAdsLoadedEvent, + ima.AdErrorCode.unknownAdResponse => AdErrorCode.unknownAdResponse, + ima.AdErrorCode.unknownError => AdErrorCode.unknownError, + ima.AdErrorCode.vastAssetNotFound => AdErrorCode.vastAssetNotFound, + ima.AdErrorCode.vastEmptyResponse => AdErrorCode.vastEmptyResponse, + ima.AdErrorCode.vastLinearAssetMismatch => + AdErrorCode.vastLinearAssetMismatch, + ima.AdErrorCode.vastLoadTimeout => AdErrorCode.vastLoadTimeout, + ima.AdErrorCode.vastMalformedResponse => AdErrorCode.vastMalformedResponse, + ima.AdErrorCode.vastMediaLoadTimeout => AdErrorCode.vastMediaLoadTimeout, + ima.AdErrorCode.vastNonlinearAssetMismatch => + AdErrorCode.vastNonlinearAssetMismatch, + ima.AdErrorCode.vastNoAdsAfterWrapper => AdErrorCode.vastNoAdsAfterWrapper, + ima.AdErrorCode.vastTooManyRedirects => AdErrorCode.vastTooManyRedirects, + ima.AdErrorCode.vastTraffickingError => AdErrorCode.vastTraffickingError, + ima.AdErrorCode.videoPlayError => AdErrorCode.videoPlayError, + ima.AdErrorCode.unknown => AdErrorCode.unknownError, + }; +} diff --git a/packages/interactive_media_ads/lib/src/ios/enum_converter_utils.dart b/packages/interactive_media_ads/lib/src/ios/enum_converter_utils.dart new file mode 100644 index 0000000000000..6ce8f06b1f66a --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/enum_converter_utils.dart @@ -0,0 +1,64 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../platform_interface/platform_interface.dart'; +import 'interactive_media_ads.g.dart' as ima; + +/// Converts [ima.AdErrorType] to [AdErrorType]. +AdErrorType toInterfaceErrorType(ima.AdErrorType type) { + return switch (type) { + ima.AdErrorType.loadingFailed => AdErrorType.loading, + ima.AdErrorType.adPlayingFailed => AdErrorType.playing, + ima.AdErrorType.unknown => AdErrorType.unknown, + }; +} + +/// Attempts to convert an [ima.AdEventType] to [AdEventType]. +/// +/// Returns null is the type is not supported by the platform interface. +AdEventType? toInterfaceEventType(ima.AdEventType type) { + return switch (type) { + ima.AdEventType.allAdsCompleted => AdEventType.allAdsCompleted, + ima.AdEventType.completed => AdEventType.complete, + ima.AdEventType.loaded => AdEventType.loaded, + ima.AdEventType.clicked => AdEventType.clicked, + _ => null, + }; +} + +/// Converts [ima.AdErrorCode] to [AdErrorCode]. +AdErrorCode toInterfaceErrorCode(ima.AdErrorCode code) { + return switch (code) { + ima.AdErrorCode.companionAdLoadingFailed => + AdErrorCode.companionAdLoadingFailed, + ima.AdErrorCode.failedToRequestAds => AdErrorCode.failedToRequestAds, + ima.AdErrorCode.invalidArguments => AdErrorCode.invalidArguments, + ima.AdErrorCode.unknownError => AdErrorCode.unknownError, + ima.AdErrorCode.vastAssetNotFound => AdErrorCode.vastAssetNotFound, + ima.AdErrorCode.vastEmptyResponse => AdErrorCode.vastEmptyResponse, + ima.AdErrorCode.vastLinearAssetMismatch => + AdErrorCode.vastLinearAssetMismatch, + ima.AdErrorCode.vastLoadTimeout => AdErrorCode.vastLoadTimeout, + ima.AdErrorCode.vastMalformedResponse => AdErrorCode.vastMalformedResponse, + ima.AdErrorCode.vastMediaLoadTimeout => AdErrorCode.vastMediaLoadTimeout, + ima.AdErrorCode.vastTooManyRedirects => AdErrorCode.vastTooManyRedirects, + ima.AdErrorCode.vastTraffickingError => AdErrorCode.vastTraffickingError, + ima.AdErrorCode.videoPlayError => AdErrorCode.videoPlayError, + ima.AdErrorCode.adslotNotVisible => AdErrorCode.adslotNotVisible, + ima.AdErrorCode.apiError => AdErrorCode.apiError, + ima.AdErrorCode.contentPlayheadMissing => + AdErrorCode.contentPlayheadMissing, + ima.AdErrorCode.failedLoadingAd => AdErrorCode.failedLoadingAd, + ima.AdErrorCode.osRuntimeTooOld => AdErrorCode.osRuntimeTooOld, + ima.AdErrorCode.playlistMalformedResponse => + AdErrorCode.playlistMalformedResponse, + ima.AdErrorCode.requiredListenersNotAdded => + AdErrorCode.requiredListenersNotAdded, + ima.AdErrorCode.streamInitializationFailed => + AdErrorCode.streamInitializationFailed, + ima.AdErrorCode.vastInvalidUrl => AdErrorCode.vastInvalidUrl, + ima.AdErrorCode.videoElementUsed => AdErrorCode.videoElementUsed, + ima.AdErrorCode.videoElementRequired => AdErrorCode.videoElementRequired, + }; +} diff --git a/packages/interactive_media_ads/lib/src/ios/interactive_media_ads.g.dart b/packages/interactive_media_ads/lib/src/ios/interactive_media_ads.g.dart new file mode 100644 index 0000000000000..77e9f90cf4e92 --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/interactive_media_ads.g.dart @@ -0,0 +1,3051 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v21.2.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, immutable, protected; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + +/// An immutable object that serves as the base class for all ProxyApis and +/// can provide functional copies of itself. +/// +/// All implementers are expected to be [immutable] as defined by the annotation +/// and override [pigeon_copy] returning an instance of itself. +@immutable +abstract class PigeonProxyApiBaseClass { + /// Construct a [PigeonProxyApiBaseClass]. + PigeonProxyApiBaseClass({ + this.pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) : pigeon_instanceManager = + pigeon_instanceManager ?? PigeonInstanceManager.instance; + + /// Sends and receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used, which routes to + /// the host platform. + @protected + final BinaryMessenger? pigeon_binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + @protected + final PigeonInstanceManager pigeon_instanceManager; + + /// Instantiates and returns a functionally identical object to oneself. + /// + /// Outside of tests, this method should only ever be called by + /// [PigeonInstanceManager]. + /// + /// Subclasses should always override their parent's implementation of this + /// method. + @protected + PigeonProxyApiBaseClass pigeon_copy(); +} + +/// Maintains instances used to communicate with the native objects they +/// represent. +/// +/// Added instances are stored as weak references and their copies are stored +/// as strong references to maintain access to their variables and callback +/// methods. Both are stored with the same identifier. +/// +/// When a weak referenced instance becomes inaccessible, +/// [onWeakReferenceRemoved] is called with its associated identifier. +/// +/// If an instance is retrieved and has the possibility to be used, +/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference +/// is added as a weak reference with the same identifier. This prevents a +/// scenario where the weak referenced instance was released and then later +/// returned by the host platform. +class PigeonInstanceManager { + /// Constructs a [PigeonInstanceManager]. + PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { + this.onWeakReferenceRemoved = (int identifier) { + _weakInstances.remove(identifier); + onWeakReferenceRemoved(identifier); + }; + _finalizer = Finalizer(this.onWeakReferenceRemoved); + } + + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously by the host platform. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + static const int _maxDartCreatedIdentifier = 65536; + + /// The default [PigeonInstanceManager] used by ProxyApis. + /// + /// On creation, this manager makes a call to clear the native + /// InstanceManager. This is to prevent identifier conflicts after a host + /// restart. + static final PigeonInstanceManager instance = _initInstance(); + + // Expando is used because it doesn't prevent its keys from becoming + // inaccessible. This allows the manager to efficiently retrieve an identifier + // of an instance without holding a strong reference to that instance. + // + // It also doesn't use `==` to search for identifiers, which would lead to an + // infinite loop when comparing an object to its copy. (i.e. which was caused + // by calling instanceManager.getIdentifier() inside of `==` while this was a + // HashMap). + final Expando _identifiers = Expando(); + final Map> _weakInstances = + >{}; + final Map _strongInstances = + {}; + late final Finalizer _finalizer; + int _nextIdentifier = 0; + + /// Called when a weak referenced instance is removed by [removeWeakReference] + /// or becomes inaccessible. + late final void Function(int) onWeakReferenceRemoved; + + static PigeonInstanceManager _initInstance() { + WidgetsFlutterBinding.ensureInitialized(); + final _PigeonInstanceManagerApi api = _PigeonInstanceManagerApi(); + // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. + api.clear(); + final PigeonInstanceManager instanceManager = PigeonInstanceManager( + onWeakReferenceRemoved: (int identifier) { + api.removeStrongReference(identifier); + }, + ); + _PigeonInstanceManagerApi.setUpMessageHandlers( + instanceManager: instanceManager); + IMAAdDisplayContainer.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + UIView.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + UIViewController.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAContentPlayhead.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdsLoader.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMASettings.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdsRequest.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdsLoaderDelegate.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdsLoadedData.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdLoadingErrorData.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdError.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdsManager.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdsManagerDelegate.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdEvent.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + IMAAdsRenderingSettings.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + NSObject.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); + return instanceManager; + } + + /// Adds a new instance that was instantiated by Dart. + /// + /// In other words, Dart wants to add a new instance that will represent + /// an object that will be instantiated on the host platform. + /// + /// Throws assertion error if the instance has already been added. + /// + /// Returns the randomly generated id of the [instance] added. + int addDartCreatedInstance(PigeonProxyApiBaseClass instance) { + final int identifier = _nextUniqueIdentifier(); + _addInstanceWithIdentifier(instance, identifier); + return identifier; + } + + /// Removes the instance, if present, and call [onWeakReferenceRemoved] with + /// its identifier. + /// + /// Returns the identifier associated with the removed instance. Otherwise, + /// `null` if the instance was not found in this manager. + /// + /// This does not remove the strong referenced instance associated with + /// [instance]. This can be done with [remove]. + int? removeWeakReference(PigeonProxyApiBaseClass instance) { + final int? identifier = getIdentifier(instance); + if (identifier == null) { + return null; + } + + _identifiers[instance] = null; + _finalizer.detach(instance); + onWeakReferenceRemoved(identifier); + + return identifier; + } + + /// Removes [identifier] and its associated strongly referenced instance, if + /// present, from the manager. + /// + /// Returns the strong referenced instance associated with [identifier] before + /// it was removed. Returns `null` if [identifier] was not associated with + /// any strong reference. + /// + /// This does not remove the weak referenced instance associated with + /// [identifier]. This can be done with [removeWeakReference]. + T? remove(int identifier) { + return _strongInstances.remove(identifier) as T?; + } + + /// Retrieves the instance associated with identifier. + /// + /// The value returned is chosen from the following order: + /// + /// 1. A weakly referenced instance associated with identifier. + /// 2. If the only instance associated with identifier is a strongly + /// referenced instance, a copy of the instance is added as a weak reference + /// with the same identifier. Returning the newly created copy. + /// 3. If no instance is associated with identifier, returns null. + /// + /// This method also expects the host `InstanceManager` to have a strong + /// reference to the instance the identifier is associated with. + T? getInstanceWithWeakReference( + int identifier) { + final PigeonProxyApiBaseClass? weakInstance = + _weakInstances[identifier]?.target; + + if (weakInstance == null) { + final PigeonProxyApiBaseClass? strongInstance = + _strongInstances[identifier]; + if (strongInstance != null) { + final PigeonProxyApiBaseClass copy = strongInstance.pigeon_copy(); + _identifiers[copy] = identifier; + _weakInstances[identifier] = + WeakReference(copy); + _finalizer.attach(copy, identifier, detach: copy); + return copy as T; + } + return strongInstance as T?; + } + + return weakInstance as T; + } + + /// Retrieves the identifier associated with instance. + int? getIdentifier(PigeonProxyApiBaseClass instance) { + return _identifiers[instance]; + } + + /// Adds a new instance that was instantiated by the host platform. + /// + /// In other words, the host platform wants to add a new instance that + /// represents an object on the host platform. Stored with [identifier]. + /// + /// Throws assertion error if the instance or its identifier has already been + /// added. + /// + /// Returns unique identifier of the [instance] added. + void addHostCreatedInstance( + PigeonProxyApiBaseClass instance, int identifier) { + _addInstanceWithIdentifier(instance, identifier); + } + + void _addInstanceWithIdentifier( + PigeonProxyApiBaseClass instance, int identifier) { + assert(!containsIdentifier(identifier)); + assert(getIdentifier(instance) == null); + assert(identifier >= 0); + + _identifiers[instance] = identifier; + _weakInstances[identifier] = + WeakReference(instance); + _finalizer.attach(instance, identifier, detach: instance); + + final PigeonProxyApiBaseClass copy = instance.pigeon_copy(); + _identifiers[copy] = identifier; + _strongInstances[identifier] = copy; + } + + /// Whether this manager contains the given [identifier]. + bool containsIdentifier(int identifier) { + return _weakInstances.containsKey(identifier) || + _strongInstances.containsKey(identifier); + } + + int _nextUniqueIdentifier() { + late int identifier; + do { + identifier = _nextIdentifier; + _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; + } while (containsIdentifier(identifier)); + return identifier; + } +} + +/// Generated API for managing the Dart and native `PigeonInstanceManager`s. +class _PigeonInstanceManagerApi { + /// Constructor for [_PigeonInstanceManagerApi]. + _PigeonInstanceManagerApi({BinaryMessenger? binaryMessenger}) + : __pigeon_binaryMessenger = binaryMessenger; + + final BinaryMessenger? __pigeon_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = + StandardMessageCodec(); + + static void setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? binaryMessenger, + PigeonInstanceManager? instanceManager, + }) { + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.removeStrongReference was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.removeStrongReference was null, expected non-null int.'); + try { + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + Future removeStrongReference(int identifier) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.removeStrongReference'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([identifier]) 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; + } + } + + /// Clear the native `PigeonInstanceManager`. + /// + /// This is typically called after a hot restart. + Future clear() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.PigeonInstanceManagerApi.clear'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + 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) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } +} + +class _PigeonProxyApiBaseCodec extends _PigeonCodec { + const _PigeonProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// Possible error types while loading or playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAErrorType.html. +enum AdErrorType { + /// An error occurred while loading the ads. + loadingFailed, + + /// An error occurred while playing the ads. + adPlayingFailed, + + /// An unexpected error occurred while loading or playing the ads. + /// + /// This may mean that the SDK wasn’t loaded properly or the wrapper doesn't + /// recognize this value. + unknown, +} + +/// Possible error codes raised while loading or playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAErrorCode.html. +enum AdErrorCode { + /// The ad slot is not visible on the page. + adslotNotVisible, + + /// Generic invalid usage of the API. + apiError, + + /// A companion ad failed to load or render. + companionAdLoadingFailed, + + /// Content playhead was not passed in, but list of ads has been returned from + /// the server. + contentPlayheadMissing, + + /// There was an error loading the ad. + failedLoadingAd, + + /// There was a problem requesting ads from the server. + failedToRequestAds, + + /// Invalid arguments were provided to SDK methods. + invalidArguments, + + /// The version of the runtime is too old. + osRuntimeTooOld, + + /// Ads list response was malformed. + playlistMalformedResponse, + + /// Listener for at least one of the required vast events was not added. + requiredListenersNotAdded, + + /// There was an error initializing the stream. + streamInitializationFailed, + + /// An unexpected error occurred and the cause is not known. + unknownError, + + /// No assets were found in the VAST ad response. + vastAssetNotFound, + + /// A VAST response containing a single `` tag with no child tags. + vastEmptyResponse, + + /// At least one VAST wrapper loaded and a subsequent wrapper or inline ad + /// load has resulted in a 404 response code. + vastInvalidUrl, + + /// Assets were found in the VAST ad response for a linear ad, but none of + /// them matched the video player's capabilities. + vastLinearAssetMismatch, + + /// The VAST URI provided, or a VAST URI provided in a subsequent Wrapper + /// element, was either unavailable or reached a timeout, as defined by the + /// video player. + vastLoadTimeout, + + /// The ad response was not recognized as a valid VAST ad. + vastMalformedResponse, + + /// Failed to load media assets from a VAST response. + vastMediaLoadTimeout, + + /// The maximum number of VAST wrapper redirects has been reached. + vastTooManyRedirects, + + /// Trafficking error. + /// + /// Video player received an ad type that it was not expecting and/or cannot + /// display. + vastTraffickingError, + + /// Another VideoAdsManager is still using the video. + videoElementUsed, + + /// A video element was not specified where it was required. + videoElementRequired, + + /// There was an error playing the video ad. + videoPlayError, +} + +/// Different event types sent by the IMAAdsManager to its delegate. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAAdEventType.html. +enum AdEventType { + /// Fired the first time each ad break ends. + adBreakEnded, + + /// Fired when an ad break will not play back any ads. + adBreakFetchError, + + /// Fired when an ad break is ready. + adBreakReady, + + /// Fired first time each ad break begins playback. + adBreakStarted, + + /// Fired every time the stream switches from advertising or slate to content. + adPeriodEnded, + + /// Fired every time the stream switches from content to advertising or slate. + adPeriodStarted, + + /// All valid ads managed by the ads manager have completed or the ad response + /// did not return any valid ads. + allAdsCompleted, + + /// Fired when an ad is clicked. + clicked, + + /// Single ad has finished. + completed, + + /// Cuepoints changed for VOD stream (only used for dynamic ad insertion). + cuepointsChanged, + + /// First quartile of a linear ad was reached. + firstQuartile, + + /// The user has closed the icon fallback image dialog. + iconFallbackImageClosed, + + /// The user has tapped an ad icon. + iconTapped, + + /// An ad was loaded. + loaded, + + /// A log event for the ads being played. + log, + + /// Midpoint of a linear ad was reached. + midpoint, + + /// Ad paused. + pause, + + /// Ad resumed. + resume, + + /// Fired when an ad was skipped. + skipped, + + /// Fired when an ad starts playing. + started, + + /// Stream request has loaded (only used for dynamic ad insertion). + streamLoaded, + + /// Stream has started playing (only used for dynamic ad insertion). + streamStarted, + + /// Ad tapped. + tapped, + + /// Third quartile of a linear ad was reached.. + thirdQuartile, + + /// The event type is not recognized by this wrapper. + unknown, +} + +/// The values that can be returned in a change dictionary. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvalueobservingoptions?language=objc. +enum KeyValueObservingOptions { + /// Indicates that the change dictionary should provide the new attribute + /// value, if applicable. + newValue, + + /// Indicates that the change dictionary should contain the old attribute + /// value, if applicable. + oldValue, + + /// If specified, a notification should be sent to the observer immediately, + /// before the observer registration method even returns. + initialValue, + + /// Whether separate notifications should be sent to the observer before and + /// after each change, instead of a single notification after the change. + priorNotification, +} + +/// The kinds of changes that can be observed.. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvaluechange?language=objc. +enum KeyValueChange { + /// Indicates that the value of the observed key path was set to a new value. + setting, + + /// Indicates that an object has been inserted into the to-many relationship + /// that is being observed. + insertion, + + /// Indicates that an object has been removed from the to-many relationship + /// that is being observed. + removal, + + /// Indicates that an object has been replaced in the to-many relationship + /// that is being observed. + replacement, +} + +/// The keys that can appear in the change dictionary.. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvaluechangekey?language=objc. +enum KeyValueChangeKey { + /// If the value of the kindKey entry is NSKeyValueChange.insertion, + /// NSKeyValueChange.removal, or NSKeyValueChange.replacement, the value of + /// this key is an NSIndexSet object that contains the indexes of the + /// inserted, removed, or replaced objects. + indexes, + + /// An NSNumber object that contains a value corresponding to one of the + /// NSKeyValueChange enums, indicating what sort of change has occurred. + kind, + + /// If the value of the kindKey entry is NSKeyValueChange.setting, and new was + /// specified when the observer was registered, the value of this key is the + /// new value for the attribute. + newValue, + + /// If the prior option was specified when the observer was registered this + /// notification is sent prior to a change. + notificationIsPrior, + + /// If the value of the kindKey entry is NSKeyValueChange.setting, and old was + /// specified when the observer was registered, the value of this key is the + /// value before the attribute was changed. + oldValue, + + /// The key is not recognized by this wrapper. + unknown, +} + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is AdErrorType) { + buffer.putUint8(129); + writeValue(buffer, value.index); + } else if (value is AdErrorCode) { + buffer.putUint8(130); + writeValue(buffer, value.index); + } else if (value is AdEventType) { + buffer.putUint8(131); + writeValue(buffer, value.index); + } else if (value is KeyValueObservingOptions) { + buffer.putUint8(132); + writeValue(buffer, value.index); + } else if (value is KeyValueChange) { + buffer.putUint8(133); + writeValue(buffer, value.index); + } else if (value is KeyValueChangeKey) { + buffer.putUint8(134); + writeValue(buffer, value.index); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 129: + final int? value = readValue(buffer) as int?; + return value == null ? null : AdErrorType.values[value]; + case 130: + final int? value = readValue(buffer) as int?; + return value == null ? null : AdErrorCode.values[value]; + case 131: + final int? value = readValue(buffer) as int?; + return value == null ? null : AdEventType.values[value]; + case 132: + final int? value = readValue(buffer) as int?; + return value == null ? null : KeyValueObservingOptions.values[value]; + case 133: + final int? value = readValue(buffer) as int?; + return value == null ? null : KeyValueChange.values[value]; + case 134: + final int? value = readValue(buffer) as int?; + return value == null ? null : KeyValueChangeKey.values[value]; + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// The `IMAAdDisplayContainer` is responsible for managing the ad container +/// view and companion ad slots used for ad playback. +/// +/// See https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/ios/reference/Classes/IMAAdDisplayContainer. +class IMAAdDisplayContainer extends NSObject { + IMAAdDisplayContainer({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required UIView adContainer, + UIViewController? adContainerViewController, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdDisplayContainer; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdDisplayContainer.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([ + __pigeon_instanceIdentifier, + adContainer, + adContainerViewController + ]) 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; + } + }(); + } + + /// Constructs [IMAAdDisplayContainer] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdDisplayContainer.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAAdDisplayContainer = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdDisplayContainer Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdDisplayContainer.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdDisplayContainer.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdDisplayContainer.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + IMAAdDisplayContainer.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdDisplayContainer pigeon_copy() { + return IMAAdDisplayContainer.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// An object that manages the content for a rectangular area on the screen. +/// +/// See https://developer.apple.com/documentation/uikit/uiview. +class UIView extends NSObject { + /// Constructs [UIView] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + UIView.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + UIView Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.UIView.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.UIView.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.UIView.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + UIView.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + UIView pigeon_copy() { + return UIView.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// An object that manages a view hierarchy for your UIKit app. +/// +/// See https://developer.apple.com/documentation/uikit/uiviewcontroller. +class UIViewController extends NSObject { + UIViewController({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + this.viewDidAppear, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecUIViewController; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.UIViewController.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([__pigeon_instanceIdentifier]) 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; + } + }(); + } + + /// Constructs [UIViewController] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + UIViewController.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + this.viewDidAppear, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecUIViewController = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + /// Notifies the view controller that its view was added to a view hierarchy. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final UIViewController instance = UIViewController( + /// viewDidAppear: (UIViewController pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function( + UIViewController pigeon_instance, + bool animated, + )? viewDidAppear; + + /// Retrieves the view that the controller manages. + /// + /// For convenience this is a `final` attached field despite this being + /// settable. Since this is not a part of the IMA SDK this is slightly changed + /// for convenience. Note that this wrapper should not add the ability to set + /// this property as it should not be needed anyways. + late final UIView view = __pigeon_view(); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + UIViewController Function()? pigeon_newInstance, + void Function( + UIViewController pigeon_instance, + bool animated, + )? viewDidAppear, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.UIViewController.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.UIViewController.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.UIViewController.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + UIViewController.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.UIViewController.viewDidAppear', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.UIViewController.viewDidAppear was null.'); + final List args = (message as List?)!; + final UIViewController? arg_pigeon_instance = + (args[0] as UIViewController?); + assert(arg_pigeon_instance != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.UIViewController.viewDidAppear was null, expected non-null UIViewController.'); + final bool? arg_animated = (args[1] as bool?); + assert(arg_animated != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.UIViewController.viewDidAppear was null, expected non-null bool.'); + try { + (viewDidAppear ?? arg_pigeon_instance!.viewDidAppear) + ?.call(arg_pigeon_instance!, arg_animated!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + UIView __pigeon_view() { + final UIView __pigeon_instance = UIView.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecUIViewController; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(__pigeon_instance); + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.UIViewController.view'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([this, __pigeon_instanceIdentifier]) 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; + } + }(); + return __pigeon_instance; + } + + @override + UIViewController pigeon_copy() { + return UIViewController.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + viewDidAppear: viewDidAppear, + ); + } +} + +/// Defines an interface for a class that tracks video content progress and +/// exposes a key value observable property |currentTime|. +/// +/// See https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/ios/reference/Protocols/IMAContentPlayhead. +class IMAContentPlayhead extends NSObject { + IMAContentPlayhead({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAContentPlayhead; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([__pigeon_instanceIdentifier]) 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; + } + }(); + } + + /// Constructs [IMAContentPlayhead] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAContentPlayhead.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAContentPlayhead = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAContentPlayhead Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + IMAContentPlayhead.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + /// Reflects the current playback time in seconds for the content. + Future setCurrentTime(double timeInterval) async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAContentPlayhead; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAContentPlayhead.setCurrentTime'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([this, timeInterval]) 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; + } + } + + @override + IMAContentPlayhead pigeon_copy() { + return IMAContentPlayhead.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// Allows the requesting of ads from the ad server. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsLoader. +class IMAAdsLoader extends NSObject { + IMAAdsLoader({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + IMASettings? settings, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsLoader; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([__pigeon_instanceIdentifier, settings]) + 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; + } + }(); + } + + /// Constructs [IMAAdsLoader] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdsLoader.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAAdsLoader = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdsLoader Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + IMAAdsLoader.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + /// Signal to the SDK that the content has completed. + Future contentComplete() async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsLoader; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.contentComplete'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this]) 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; + } + } + + /// Request ads from the ad server. + Future requestAds(IMAAdsRequest request) async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsLoader; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.requestAds'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this, request]) 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; + } + } + + /// Delegate that receives `IMAAdsLoaderDelegate` callbacks. + /// + /// Note that this sets to a `weak` property in Swift. + Future setDelegate(IMAAdsLoaderDelegate? delegate) async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsLoader; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoader.setDelegate'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([this, delegate]) 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; + } + } + + @override + IMAAdsLoader pigeon_copy() { + return IMAAdsLoader.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// The IMASettings class stores SDK wide settings. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMASettings.html. +class IMASettings extends NSObject { + /// Constructs [IMASettings] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMASettings.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMASettings Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMASettings.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMASettings.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMASettings.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + IMASettings.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMASettings pigeon_copy() { + return IMASettings.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// Data class describing the ad request. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsRequest. +class IMAAdsRequest extends NSObject { + /// Initializes an ads request instance with the given ad tag URL and ad + /// display container. + IMAAdsRequest({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required String adTagUrl, + required IMAAdDisplayContainer adDisplayContainer, + IMAContentPlayhead? contentPlayhead, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsRequest; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsRequest.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([ + __pigeon_instanceIdentifier, + adTagUrl, + adDisplayContainer, + contentPlayhead + ]) 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; + } + }(); + } + + /// Constructs [IMAAdsRequest] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdsRequest.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAAdsRequest = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdsRequest Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsRequest.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsRequest.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsRequest.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + IMAAdsRequest.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdsRequest pigeon_copy() { + return IMAAdsRequest.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// Delegate object that receives state change callbacks from `IMAAdsLoader`. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Protocols/IMAAdsLoaderDelegate.html. +class IMAAdsLoaderDelegate extends NSObject { + IMAAdsLoaderDelegate({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.adLoaderLoadedWith, + required this.adsLoaderFailedWithErrorData, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsLoaderDelegate; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([__pigeon_instanceIdentifier]) 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; + } + }(); + } + + /// Constructs [IMAAdsLoaderDelegate] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdsLoaderDelegate.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.adLoaderLoadedWith, + required this.adsLoaderFailedWithErrorData, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAAdsLoaderDelegate = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + /// Called when ads are successfully loaded from the ad servers by the loader. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final IMAAdsLoaderDelegate instance = IMAAdsLoaderDelegate( + /// adLoaderLoadedWith: (IMAAdsLoaderDelegate pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function( + IMAAdsLoaderDelegate pigeon_instance, + IMAAdsLoader loader, + IMAAdsLoadedData adsLoadedData, + ) adLoaderLoadedWith; + + /// Error reported by the ads loader when loading or requesting an ad fails. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final IMAAdsLoaderDelegate instance = IMAAdsLoaderDelegate( + /// adsLoaderFailedWithErrorData: (IMAAdsLoaderDelegate pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function( + IMAAdsLoaderDelegate pigeon_instance, + IMAAdsLoader loader, + IMAAdLoadingErrorData adErrorData, + ) adsLoaderFailedWithErrorData; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + void Function( + IMAAdsLoaderDelegate pigeon_instance, + IMAAdsLoader loader, + IMAAdsLoadedData adsLoadedData, + )? adLoaderLoadedWith, + void Function( + IMAAdsLoaderDelegate pigeon_instance, + IMAAdsLoader loader, + IMAAdLoadingErrorData adErrorData, + )? adsLoaderFailedWithErrorData, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adLoaderLoadedWith', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adLoaderLoadedWith was null.'); + final List args = (message as List?)!; + final IMAAdsLoaderDelegate? arg_pigeon_instance = + (args[0] as IMAAdsLoaderDelegate?); + assert(arg_pigeon_instance != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adLoaderLoadedWith was null, expected non-null IMAAdsLoaderDelegate.'); + final IMAAdsLoader? arg_loader = (args[1] as IMAAdsLoader?); + assert(arg_loader != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adLoaderLoadedWith was null, expected non-null IMAAdsLoader.'); + final IMAAdsLoadedData? arg_adsLoadedData = + (args[2] as IMAAdsLoadedData?); + assert(arg_adsLoadedData != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adLoaderLoadedWith was null, expected non-null IMAAdsLoadedData.'); + try { + (adLoaderLoadedWith ?? arg_pigeon_instance!.adLoaderLoadedWith) + .call(arg_pigeon_instance!, arg_loader!, arg_adsLoadedData!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adsLoaderFailedWithErrorData', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adsLoaderFailedWithErrorData was null.'); + final List args = (message as List?)!; + final IMAAdsLoaderDelegate? arg_pigeon_instance = + (args[0] as IMAAdsLoaderDelegate?); + assert(arg_pigeon_instance != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adsLoaderFailedWithErrorData was null, expected non-null IMAAdsLoaderDelegate.'); + final IMAAdsLoader? arg_loader = (args[1] as IMAAdsLoader?); + assert(arg_loader != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adsLoaderFailedWithErrorData was null, expected non-null IMAAdsLoader.'); + final IMAAdLoadingErrorData? arg_adErrorData = + (args[2] as IMAAdLoadingErrorData?); + assert(arg_adErrorData != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoaderDelegate.adsLoaderFailedWithErrorData was null, expected non-null IMAAdLoadingErrorData.'); + try { + (adsLoaderFailedWithErrorData ?? + arg_pigeon_instance!.adsLoaderFailedWithErrorData) + .call(arg_pigeon_instance!, arg_loader!, arg_adErrorData!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdsLoaderDelegate pigeon_copy() { + return IMAAdsLoaderDelegate.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + adLoaderLoadedWith: adLoaderLoadedWith, + adsLoaderFailedWithErrorData: adsLoaderFailedWithErrorData, + ); + } +} + +/// Ad data that is returned when the ads loader loads the ad. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsLoadedData.html. +class IMAAdsLoadedData extends NSObject { + /// Constructs [IMAAdsLoadedData] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdsLoadedData.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + this.adsManager, + }) : super.pigeon_detached(); + + /// The ads manager instance created by the ads loader. + /// + /// Will be null when using dynamic ad insertion. + final IMAAdsManager? adsManager; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdsLoadedData Function(IMAAdsManager? adsManager)? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsLoadedData.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoadedData.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsLoadedData.pigeon_newInstance was null, expected non-null int.'); + final IMAAdsManager? arg_adsManager = (args[1] as IMAAdsManager?); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call(arg_adsManager) ?? + IMAAdsLoadedData.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + adsManager: arg_adsManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdsLoadedData pigeon_copy() { + return IMAAdsLoadedData.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + adsManager: adsManager, + ); + } +} + +/// Ad error data that is returned when the ads loader fails to load the ad. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdLoadingErrorData.html. +class IMAAdLoadingErrorData extends NSObject { + /// Constructs [IMAAdLoadingErrorData] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdLoadingErrorData.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.adError, + }) : super.pigeon_detached(); + + /// The ad error that occurred while loading the ad. + final IMAAdError adError; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdLoadingErrorData Function(IMAAdError adError)? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdLoadingErrorData.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdLoadingErrorData.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdLoadingErrorData.pigeon_newInstance was null, expected non-null int.'); + final IMAAdError? arg_adError = (args[1] as IMAAdError?); + assert(arg_adError != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdLoadingErrorData.pigeon_newInstance was null, expected non-null IMAAdError.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call(arg_adError!) ?? + IMAAdLoadingErrorData.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + adError: arg_adError!, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdLoadingErrorData pigeon_copy() { + return IMAAdLoadingErrorData.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + adError: adError, + ); + } +} + +/// Surfaces an error that occurred during ad loading or playing. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdError.html. +class IMAAdError extends NSObject { + /// Constructs [IMAAdError] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdError.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.type, + required this.code, + this.message, + }) : super.pigeon_detached(); + + /// The type of error that occurred during ad loading or ad playing. + final AdErrorType type; + + /// The error code for obtaining more specific information about the error. + final AdErrorCode code; + + /// A brief description about the error. + final String? message; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdError Function( + AdErrorType type, + AdErrorCode code, + String? message, + )? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdError.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdError.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdError.pigeon_newInstance was null, expected non-null int.'); + final AdErrorType? arg_type = (args[1] as AdErrorType?); + assert(arg_type != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdError.pigeon_newInstance was null, expected non-null AdErrorType.'); + final AdErrorCode? arg_code = (args[2] as AdErrorCode?); + assert(arg_code != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdError.pigeon_newInstance was null, expected non-null AdErrorCode.'); + final String? arg_message = (args[3] as String?); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call(arg_type!, arg_code!, arg_message) ?? + IMAAdError.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + type: arg_type!, + code: arg_code!, + message: arg_message, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdError pigeon_copy() { + return IMAAdError.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + type: type, + code: code, + message: message, + ); + } +} + +/// Responsible for playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsManager.html. +class IMAAdsManager extends NSObject { + /// Constructs [IMAAdsManager] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdsManager.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAAdsManager = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdsManager Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + IMAAdsManager.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + /// The `IMAAdsManagerDelegate` to notify with events during ad playback. + Future setDelegate(IMAAdsManagerDelegate? delegate) async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.setDelegate'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([this, delegate]) 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; + } + } + + /// Initializes and loads the ad. + Future initialize(IMAAdsRenderingSettings? adsRenderingSettings) async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.initialize'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([this, adsRenderingSettings]) 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; + } + } + + /// Starts advertisement playback. + Future start() async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.start'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this]) 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; + } + } + + /// Pauses advertisement. + Future pause() async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pause'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this]) 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; + } + } + + /// Resumes the current ad. + Future resume() async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.resume'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this]) 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; + } + } + + /// Skips the advertisement if the ad is skippable and the skip offset has + /// been reached. + Future skip() async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.skip'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this]) 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; + } + } + + /// If an ad break is currently playing, discard it and resume content. + Future discardAdBreak() async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.discardAdBreak'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this]) 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; + } + } + + /// Causes the ads manager to stop the ad and clean its internal state. + Future destroy() async { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManager; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.destroy'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([this]) 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; + } + } + + @override + IMAAdsManager pigeon_copy() { + return IMAAdsManager.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// A callback protocol for IMAAdsManager. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Protocols/IMAAdsManagerDelegate.html. +class IMAAdsManagerDelegate extends NSObject { + IMAAdsManagerDelegate({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.didReceiveAdEvent, + required this.didReceiveAdError, + required this.didRequestContentPause, + required this.didRequestContentResume, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsManagerDelegate; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([__pigeon_instanceIdentifier]) 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; + } + }(); + } + + /// Constructs [IMAAdsManagerDelegate] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdsManagerDelegate.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.didReceiveAdEvent, + required this.didReceiveAdError, + required this.didRequestContentPause, + required this.didRequestContentResume, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAAdsManagerDelegate = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + /// Called when there is an IMAAdEvent. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final IMAAdsManagerDelegate instance = IMAAdsManagerDelegate( + /// didReceiveAdEvent: (IMAAdsManagerDelegate pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + IMAAdEvent event, + ) didReceiveAdEvent; + + /// Called when there was an error playing the ad. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final IMAAdsManagerDelegate instance = IMAAdsManagerDelegate( + /// didReceiveAdError: (IMAAdsManagerDelegate pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + IMAAdError error, + ) didReceiveAdError; + + /// Called when an ad is ready to play. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final IMAAdsManagerDelegate instance = IMAAdsManagerDelegate( + /// didRequestContentPause: (IMAAdsManagerDelegate pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + ) didRequestContentPause; + + /// Called when an ad has finished or an error occurred during the playback. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final IMAAdsManagerDelegate instance = IMAAdsManagerDelegate( + /// didRequestContentResume: (IMAAdsManagerDelegate pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + ) didRequestContentResume; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + IMAAdEvent event, + )? didReceiveAdEvent, + void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + IMAAdError error, + )? didReceiveAdError, + void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + )? didRequestContentPause, + void Function( + IMAAdsManagerDelegate pigeon_instance, + IMAAdsManager adsManager, + )? didRequestContentResume, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdEvent', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdEvent was null.'); + final List args = (message as List?)!; + final IMAAdsManagerDelegate? arg_pigeon_instance = + (args[0] as IMAAdsManagerDelegate?); + assert(arg_pigeon_instance != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdEvent was null, expected non-null IMAAdsManagerDelegate.'); + final IMAAdsManager? arg_adsManager = (args[1] as IMAAdsManager?); + assert(arg_adsManager != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdEvent was null, expected non-null IMAAdsManager.'); + final IMAAdEvent? arg_event = (args[2] as IMAAdEvent?); + assert(arg_event != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdEvent was null, expected non-null IMAAdEvent.'); + try { + (didReceiveAdEvent ?? arg_pigeon_instance!.didReceiveAdEvent) + .call(arg_pigeon_instance!, arg_adsManager!, arg_event!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdError', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdError was null.'); + final List args = (message as List?)!; + final IMAAdsManagerDelegate? arg_pigeon_instance = + (args[0] as IMAAdsManagerDelegate?); + assert(arg_pigeon_instance != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdError was null, expected non-null IMAAdsManagerDelegate.'); + final IMAAdsManager? arg_adsManager = (args[1] as IMAAdsManager?); + assert(arg_adsManager != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdError was null, expected non-null IMAAdsManager.'); + final IMAAdError? arg_error = (args[2] as IMAAdError?); + assert(arg_error != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didReceiveAdError was null, expected non-null IMAAdError.'); + try { + (didReceiveAdError ?? arg_pigeon_instance!.didReceiveAdError) + .call(arg_pigeon_instance!, arg_adsManager!, arg_error!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentPause', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentPause was null.'); + final List args = (message as List?)!; + final IMAAdsManagerDelegate? arg_pigeon_instance = + (args[0] as IMAAdsManagerDelegate?); + assert(arg_pigeon_instance != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentPause was null, expected non-null IMAAdsManagerDelegate.'); + final IMAAdsManager? arg_adsManager = (args[1] as IMAAdsManager?); + assert(arg_adsManager != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentPause was null, expected non-null IMAAdsManager.'); + try { + (didRequestContentPause ?? + arg_pigeon_instance!.didRequestContentPause) + .call(arg_pigeon_instance!, arg_adsManager!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentResume', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentResume was null.'); + final List args = (message as List?)!; + final IMAAdsManagerDelegate? arg_pigeon_instance = + (args[0] as IMAAdsManagerDelegate?); + assert(arg_pigeon_instance != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentResume was null, expected non-null IMAAdsManagerDelegate.'); + final IMAAdsManager? arg_adsManager = (args[1] as IMAAdsManager?); + assert(arg_adsManager != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManagerDelegate.didRequestContentResume was null, expected non-null IMAAdsManager.'); + try { + (didRequestContentResume ?? + arg_pigeon_instance!.didRequestContentResume) + .call(arg_pigeon_instance!, arg_adsManager!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdsManagerDelegate pigeon_copy() { + return IMAAdsManagerDelegate.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + didReceiveAdEvent: didReceiveAdEvent, + didReceiveAdError: didReceiveAdError, + didRequestContentPause: didRequestContentPause, + didRequestContentResume: didRequestContentResume, + ); + } +} + +/// Simple data class used to transport ad playback information. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdEvent.html. +class IMAAdEvent extends NSObject { + /// Constructs [IMAAdEvent] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdEvent.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.type, + required this.typeString, + }) : super.pigeon_detached(); + + /// Type of the event. + final AdEventType type; + + /// Stringified type of the event. + final String typeString; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdEvent Function( + AdEventType type, + String typeString, + )? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdEvent.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdEvent.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdEvent.pigeon_newInstance was null, expected non-null int.'); + final AdEventType? arg_type = (args[1] as AdEventType?); + assert(arg_type != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdEvent.pigeon_newInstance was null, expected non-null AdEventType.'); + final String? arg_typeString = (args[2] as String?); + assert(arg_typeString != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdEvent.pigeon_newInstance was null, expected non-null String.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call(arg_type!, arg_typeString!) ?? + IMAAdEvent.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + type: arg_type!, + typeString: arg_typeString!, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdEvent pigeon_copy() { + return IMAAdEvent.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + type: type, + typeString: typeString, + ); + } +} + +/// Set of properties that influence how ads are rendered. +/// +/// See https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/ios/reference/Classes/IMAAdsRenderingSettings. +class IMAAdsRenderingSettings extends NSObject { + IMAAdsRenderingSettings({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached() { + final int __pigeon_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + __pigeon_codecIMAAdsRenderingSettings; + final BinaryMessenger? __pigeon_binaryMessenger = pigeon_binaryMessenger; + () async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsRenderingSettings.pigeon_defaultConstructor'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([__pigeon_instanceIdentifier]) 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; + } + }(); + } + + /// Constructs [IMAAdsRenderingSettings] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + IMAAdsRenderingSettings.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) : super.pigeon_detached(); + + late final _PigeonProxyApiBaseCodec __pigeon_codecIMAAdsRenderingSettings = + _PigeonProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + IMAAdsRenderingSettings Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.IMAAdsRenderingSettings.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsRenderingSettings.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsRenderingSettings.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + IMAAdsRenderingSettings.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + IMAAdsRenderingSettings pigeon_copy() { + return IMAAdsRenderingSettings.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +/// The root class of most Objective-C class hierarchies, from which subclasses +/// inherit a basic interface to the runtime system and the ability to behave as +/// Objective-C objects. +/// +/// See https://developer.apple.com/documentation/objectivec/nsobject. +class NSObject extends PigeonProxyApiBaseClass { + /// Constructs [NSObject] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + NSObject.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + NSObject Function()? pigeon_newInstance, + }) { + final _PigeonProxyApiBaseCodec pigeonChannelCodec = + _PigeonProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.interactive_media_ads.NSObject.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.NSObject.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.interactive_media_ads.NSObject.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + NSObject.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + NSObject pigeon_copy() { + return NSObject.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} diff --git a/packages/interactive_media_ads/lib/src/ios/interactive_media_ads_proxy.dart b/packages/interactive_media_ads/lib/src/ios/interactive_media_ads_proxy.dart new file mode 100644 index 0000000000000..29600d0b617cc --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/interactive_media_ads_proxy.dart @@ -0,0 +1,71 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'interactive_media_ads.g.dart'; + +/// Handles constructing objects and calling static methods for the iOS +/// Interactive Media Ads native library. +/// +/// This class provides dependency injection for the implementations of the +/// platform interface classes. Improving the ease of unit testing and/or +/// overriding the underlying iOS classes. +class InteractiveMediaAdsProxy { + /// Constructs an [InteractiveMediaAdsProxy]. + const InteractiveMediaAdsProxy({ + this.newIMAAdDisplayContainer = IMAAdDisplayContainer.new, + this.newUIViewController = UIViewController.new, + this.newIMAAdsLoader = IMAAdsLoader.new, + this.newIMAAdsRequest = IMAAdsRequest.new, + this.newIMAAdsLoaderDelegate = IMAAdsLoaderDelegate.new, + this.newIMAAdsManagerDelegate = IMAAdsManagerDelegate.new, + this.newIMAAdsRenderingSettings = IMAAdsRenderingSettings.new, + }); + + /// Constructs [IMAAdDisplayContainer]. + final IMAAdDisplayContainer Function({ + required UIView adContainer, + UIViewController? adContainerViewController, + }) newIMAAdDisplayContainer; + + /// Constructs [UIViewController]. + final UIViewController Function({ + void Function(UIViewController, bool)? viewDidAppear, + }) newUIViewController; + + /// Constructs [IMAAdsLoader]. + final IMAAdsLoader Function({IMASettings? settings}) newIMAAdsLoader; + + /// Constructs [IMAAdsRequest]. + final IMAAdsRequest Function({ + required String adTagUrl, + required IMAAdDisplayContainer adDisplayContainer, + IMAContentPlayhead? contentPlayhead, + }) newIMAAdsRequest; + + /// Constructs [IMAAdsLoaderDelegate]. + final IMAAdsLoaderDelegate Function({ + required void Function(IMAAdsLoaderDelegate, IMAAdsLoader, IMAAdsLoadedData) + adLoaderLoadedWith, + required void Function( + IMAAdsLoaderDelegate, + IMAAdsLoader, + IMAAdLoadingErrorData, + ) adsLoaderFailedWithErrorData, + }) newIMAAdsLoaderDelegate; + + /// Constructs [IMAAdsManagerDelegate]. + final IMAAdsManagerDelegate Function({ + required void Function(IMAAdsManagerDelegate, IMAAdsManager, IMAAdEvent) + didReceiveAdEvent, + required void Function(IMAAdsManagerDelegate, IMAAdsManager, IMAAdError) + didReceiveAdError, + required void Function(IMAAdsManagerDelegate, IMAAdsManager) + didRequestContentPause, + required void Function(IMAAdsManagerDelegate, IMAAdsManager) + didRequestContentResume, + }) newIMAAdsManagerDelegate; + + /// Constructs [IMAAdsRenderingSettings]. + final IMAAdsRenderingSettings Function() newIMAAdsRenderingSettings; +} diff --git a/packages/interactive_media_ads/lib/src/ios/ios_ad_display_container.dart b/packages/interactive_media_ads/lib/src/ios/ios_ad_display_container.dart new file mode 100644 index 0000000000000..4bdd8fa461338 --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/ios_ad_display_container.dart @@ -0,0 +1,104 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; + +import '../platform_interface/platform_interface.dart'; +import 'interactive_media_ads.g.dart'; +import 'interactive_media_ads_proxy.dart'; + +/// Implementation of [PlatformAdDisplayContainerCreationParams] for iOS. +final class IOSAdDisplayContainerCreationParams + extends PlatformAdDisplayContainerCreationParams { + /// Constructs a [IOSAdDisplayContainerCreationParams]. + const IOSAdDisplayContainerCreationParams({ + super.key, + required super.onContainerAdded, + @visibleForTesting InteractiveMediaAdsProxy? imaProxy, + }) : _imaProxy = imaProxy ?? const InteractiveMediaAdsProxy(), + super(); + + /// Creates a [IOSAdDisplayContainerCreationParams] from an instance of + /// [PlatformAdDisplayContainerCreationParams]. + factory IOSAdDisplayContainerCreationParams.fromPlatformAdDisplayContainerCreationParams( + PlatformAdDisplayContainerCreationParams params, { + @visibleForTesting InteractiveMediaAdsProxy? imaProxy, + }) { + return IOSAdDisplayContainerCreationParams( + key: params.key, + onContainerAdded: params.onContainerAdded, + imaProxy: imaProxy, + ); + } + + final InteractiveMediaAdsProxy _imaProxy; +} + +/// Implementation of [PlatformAdDisplayContainer] for iOS. +base class IOSAdDisplayContainer extends PlatformAdDisplayContainer { + /// Constructs an [IOSAdDisplayContainer]. + IOSAdDisplayContainer(super.params) : super.implementation(); + + // The `UIViewController` used to create the native `IMAAdDisplayContainer`. + late final UIViewController _controller = _createViewController( + WeakReference(this), + ); + + final Completer _viewDidAppearCompleter = Completer(); + + /// The native iOS IMAAdDisplayContainer. + /// + /// Created with the `UIView` that handles playing an ad. + @internal + late final IMAAdDisplayContainer? adDisplayContainer; + + late final IOSAdDisplayContainerCreationParams _iosParams = + params is IOSAdDisplayContainerCreationParams + ? params as IOSAdDisplayContainerCreationParams + : IOSAdDisplayContainerCreationParams + .fromPlatformAdDisplayContainerCreationParams(params); + + @override + Widget build(BuildContext context) { + return UiKitView( + key: _iosParams.key, + viewType: 'interactive_media_ads.packages.flutter.dev/view', + onPlatformViewCreated: (_) async { + adDisplayContainer = _iosParams._imaProxy.newIMAAdDisplayContainer( + adContainer: _controller.view, + adContainerViewController: _controller, + ); + await _viewDidAppearCompleter.future; + params.onContainerAdded(this); + }, + layoutDirection: params.layoutDirection, + creationParams: + // ignore: invalid_use_of_protected_member + _controller.view.pigeon_instanceManager + .getIdentifier(_controller.view), + creationParamsCodec: const StandardMessageCodec(), + ); + } + + // This value is created in a static method because the callback methods for + // any wrapped classes must not reference the encapsulating object. This is to + // prevent a circular reference that prevents garbage collection. + static UIViewController _createViewController( + WeakReference interfaceContainer, + ) { + return interfaceContainer.target!._iosParams._imaProxy.newUIViewController( + viewDidAppear: (_, bool animated) { + final IOSAdDisplayContainer? container = interfaceContainer.target; + if (container != null && + !container._viewDidAppearCompleter.isCompleted) { + container._viewDidAppearCompleter.complete(); + } + }, + ); + } +} diff --git a/packages/interactive_media_ads/lib/src/ios/ios_ads_loader.dart b/packages/interactive_media_ads/lib/src/ios/ios_ads_loader.dart new file mode 100644 index 0000000000000..d0f68646570d3 --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/ios_ads_loader.dart @@ -0,0 +1,110 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +import '../platform_interface/platform_interface.dart'; +import 'enum_converter_utils.dart'; +import 'interactive_media_ads.g.dart'; +import 'interactive_media_ads_proxy.dart'; +import 'ios_ad_display_container.dart'; +import 'ios_ads_manager.dart'; + +/// Implementation of [PlatformAdsLoaderCreationParams] for iOS. +final class IOSAdsLoaderCreationParams extends PlatformAdsLoaderCreationParams { + /// Constructs a [IOSAdsLoaderCreationParams]. + const IOSAdsLoaderCreationParams({ + required super.container, + required super.onAdsLoaded, + required super.onAdsLoadError, + @visibleForTesting InteractiveMediaAdsProxy? proxy, + }) : _proxy = proxy ?? const InteractiveMediaAdsProxy(), + super(); + + /// Creates a [IOSAdsLoaderCreationParams] from an instance of + /// [PlatformAdsLoaderCreationParams]. + factory IOSAdsLoaderCreationParams.fromPlatformAdsLoaderCreationParams( + PlatformAdsLoaderCreationParams params, { + @visibleForTesting InteractiveMediaAdsProxy? proxy, + }) { + return IOSAdsLoaderCreationParams( + container: params.container, + onAdsLoaded: params.onAdsLoaded, + onAdsLoadError: params.onAdsLoadError, + proxy: proxy, + ); + } + + final InteractiveMediaAdsProxy _proxy; +} + +/// Implementation of [PlatformAdsLoader] for iOS. +base class IOSAdsLoader extends PlatformAdsLoader { + /// Constructs an [IOSAdsLoader]. + IOSAdsLoader(super.params) + : assert(params.container is IOSAdDisplayContainer), + assert( + (params.container as IOSAdDisplayContainer).adDisplayContainer != + null, + 'Ensure the AdDisplayContainer has been added to the Widget tree before creating an AdsLoader.', + ), + super.implementation() { + _adsLoader = _iosParams._proxy.newIMAAdsLoader(); + _adsLoader.setDelegate(_delegate); + } + + late final IMAAdsLoader _adsLoader; + late final IMAAdsLoaderDelegate _delegate = _createAdsLoaderDelegate( + WeakReference(this), + ); + + late final IOSAdsLoaderCreationParams _iosParams = params + is IOSAdsLoaderCreationParams + ? params as IOSAdsLoaderCreationParams + : IOSAdsLoaderCreationParams.fromPlatformAdsLoaderCreationParams(params); + + @override + Future contentComplete() { + return _adsLoader.contentComplete(); + } + + @override + Future requestAds(AdsRequest request) async { + return _adsLoader.requestAds(_iosParams._proxy.newIMAAdsRequest( + adTagUrl: request.adTagUrl, + adDisplayContainer: + (_iosParams.container as IOSAdDisplayContainer).adDisplayContainer!, + )); + } + + // This value is created in a static method because the callback methods for + // any wrapped classes must not reference the encapsulating object. This is to + // prevent a circular reference that prevents garbage collection. + static IMAAdsLoaderDelegate _createAdsLoaderDelegate( + WeakReference interfaceLoader, + ) { + return interfaceLoader.target!._iosParams._proxy.newIMAAdsLoaderDelegate( + adLoaderLoadedWith: (_, __, IMAAdsLoadedData adsLoadedData) { + interfaceLoader.target?._iosParams.onAdsLoaded( + PlatformOnAdsLoadedData( + manager: IOSAdsManager(adsLoadedData.adsManager!), + ), + ); + }, + adsLoaderFailedWithErrorData: (_, __, IMAAdLoadingErrorData adErrorData) { + interfaceLoader.target?._iosParams.onAdsLoadError( + AdsLoadErrorData( + error: AdError( + type: toInterfaceErrorType(adErrorData.adError.type), + code: toInterfaceErrorCode(adErrorData.adError.code), + message: adErrorData.adError.message, + ), + ), + ); + }, + ); + } +} diff --git a/packages/interactive_media_ads/lib/src/ios/ios_ads_manager.dart b/packages/interactive_media_ads/lib/src/ios/ios_ads_manager.dart new file mode 100644 index 0000000000000..595ccf5730628 --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/ios_ads_manager.dart @@ -0,0 +1,51 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:meta/meta.dart'; + +import '../platform_interface/platform_interface.dart'; +import 'interactive_media_ads.g.dart'; +import 'ios_ads_manager_delegate.dart'; + +/// Implementation of [PlatformAdsManager] for iOS. +class IOSAdsManager extends PlatformAdsManager { + /// Constructs an [IOSAdsManager]. + @internal + IOSAdsManager(IMAAdsManager manager) : _manager = manager; + + final IMAAdsManager _manager; + + // This must maintain a reference to the delegate because the native + // `IMAAdsManagerDelegate.delegate` property is only a weak reference. + // Therefore, this would be garbage collected without this explicit reference. + // ignore: unused_field + late IOSAdsManagerDelegate _delegate; + + @override + Future destroy() { + return _manager.destroy(); + } + + @override + Future init(AdsManagerInitParams params) { + return _manager.initialize(null); + } + + @override + Future setAdsManagerDelegate(PlatformAdsManagerDelegate delegate) { + final IOSAdsManagerDelegate platformDelegate = + delegate is IOSAdsManagerDelegate + ? delegate + : IOSAdsManagerDelegate(delegate.params); + _delegate = platformDelegate; + return _manager.setDelegate(platformDelegate.delegate); + } + + @override + Future start(AdsManagerStartParams params) { + return _manager.start(); + } +} diff --git a/packages/interactive_media_ads/lib/src/ios/ios_ads_manager_delegate.dart b/packages/interactive_media_ads/lib/src/ios/ios_ads_manager_delegate.dart new file mode 100644 index 0000000000000..438d8c9d8a186 --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/ios_ads_manager_delegate.dart @@ -0,0 +1,98 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:meta/meta.dart'; + +import '../platform_interface/platform_interface.dart'; +import 'enum_converter_utils.dart'; +import 'interactive_media_ads.g.dart' as ima; +import 'interactive_media_ads_proxy.dart'; + +/// Implementation of [PlatformAdsManagerDelegateCreationParams] for iOS. +final class IOSAdsManagerDelegateCreationParams + extends PlatformAdsManagerDelegateCreationParams { + /// Constructs an [IOSAdsManagerDelegateCreationParams]. + const IOSAdsManagerDelegateCreationParams({ + super.onAdEvent, + super.onAdErrorEvent, + @visibleForTesting InteractiveMediaAdsProxy? proxy, + }) : _proxy = proxy ?? const InteractiveMediaAdsProxy(), + super(); + + /// Creates an [IOSAdsManagerDelegateCreationParams] from an instance of + /// [PlatformAdsManagerDelegateCreationParams]. + factory IOSAdsManagerDelegateCreationParams.fromPlatformAdsManagerDelegateCreationParams( + PlatformAdsManagerDelegateCreationParams params, { + @visibleForTesting InteractiveMediaAdsProxy? proxy, + }) { + return IOSAdsManagerDelegateCreationParams( + onAdEvent: params.onAdEvent, + onAdErrorEvent: params.onAdErrorEvent, + proxy: proxy, + ); + } + + final InteractiveMediaAdsProxy _proxy; +} + +/// Implementation of [PlatformAdsManagerDelegate] for iOS. +final class IOSAdsManagerDelegate extends PlatformAdsManagerDelegate { + /// Constructs an [IOSAdsManagerDelegate]. + IOSAdsManagerDelegate(super.params) : super.implementation(); + + /// The native iOS `IMAAdsManagerDelegate`. + /// + /// This handles ad events and errors that occur during ad or stream + /// initialization and playback. + @internal + late final ima.IMAAdsManagerDelegate delegate = _createAdsManagerDelegate( + WeakReference(this), + ); + + late final IOSAdsManagerDelegateCreationParams _iosParams = + params is IOSAdsManagerDelegateCreationParams + ? params as IOSAdsManagerDelegateCreationParams + : IOSAdsManagerDelegateCreationParams + .fromPlatformAdsManagerDelegateCreationParams(params); + + // This value is created in a static method because the callback methods for + // any wrapped classes must not reference the encapsulating object. This is to + // prevent a circular reference that prevents garbage collection. + static ima.IMAAdsManagerDelegate _createAdsManagerDelegate( + WeakReference interfaceDelegate, + ) { + return interfaceDelegate.target!._iosParams._proxy.newIMAAdsManagerDelegate( + didReceiveAdEvent: (_, __, ima.IMAAdEvent event) { + late final AdEventType? eventType = toInterfaceEventType(event.type); + if (eventType == null) { + return; + } + + interfaceDelegate.target?.params.onAdEvent + ?.call(AdEvent(type: eventType)); + }, + didReceiveAdError: (_, __, ima.IMAAdError event) { + interfaceDelegate.target?.params.onAdErrorEvent?.call( + AdErrorEvent( + error: AdError( + type: toInterfaceErrorType(event.type), + code: toInterfaceErrorCode(event.code), + message: event.message, + ), + ), + ); + }, + didRequestContentPause: (_, __) { + interfaceDelegate.target?.params.onAdEvent?.call( + const AdEvent(type: AdEventType.contentPauseRequested), + ); + }, + didRequestContentResume: (_, __) { + interfaceDelegate.target?.params.onAdEvent?.call( + const AdEvent(type: AdEventType.contentResumeRequested), + ); + }, + ); + } +} diff --git a/packages/interactive_media_ads/lib/src/ios/ios_interactive_media_ads.dart b/packages/interactive_media_ads/lib/src/ios/ios_interactive_media_ads.dart new file mode 100644 index 0000000000000..013f66451eb00 --- /dev/null +++ b/packages/interactive_media_ads/lib/src/ios/ios_interactive_media_ads.dart @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../platform_interface/interactive_media_ads_platform.dart'; +import '../platform_interface/platform_ad_display_container.dart'; +import '../platform_interface/platform_ads_loader.dart'; +import '../platform_interface/platform_ads_manager_delegate.dart'; +import 'ios_ad_display_container.dart'; +import 'ios_ads_loader.dart'; +import 'ios_ads_manager_delegate.dart'; + +/// Implementation of [InteractiveMediaAdsPlatform] for iOS. +final class IOSInteractiveMediaAds extends InteractiveMediaAdsPlatform { + /// Registers this class as the default instance of [InteractiveMediaAdsPlatform]. + static void registerWith() { + InteractiveMediaAdsPlatform.instance = IOSInteractiveMediaAds(); + } + + @override + IOSAdDisplayContainer createPlatformAdDisplayContainer( + PlatformAdDisplayContainerCreationParams params, + ) { + return IOSAdDisplayContainer(params); + } + + @override + IOSAdsLoader createPlatformAdsLoader(PlatformAdsLoaderCreationParams params) { + return IOSAdsLoader(params); + } + + @override + IOSAdsManagerDelegate createPlatformAdsManagerDelegate( + PlatformAdsManagerDelegateCreationParams params, + ) { + return IOSAdsManagerDelegate(params); + } +} diff --git a/packages/interactive_media_ads/lib/src/platform_interface/platform_ad_display_container.dart b/packages/interactive_media_ads/lib/src/platform_interface/platform_ad_display_container.dart index 075706f393079..2f961f9a7cc7f 100644 --- a/packages/interactive_media_ads/lib/src/platform_interface/platform_ad_display_container.dart +++ b/packages/interactive_media_ads/lib/src/platform_interface/platform_ad_display_container.dart @@ -45,6 +45,7 @@ base class PlatformAdDisplayContainerCreationParams { const PlatformAdDisplayContainerCreationParams({ this.key, required this.onContainerAdded, + this.layoutDirection = TextDirection.ltr, }); /// Controls how one widget replaces another widget in the tree. @@ -56,6 +57,9 @@ base class PlatformAdDisplayContainerCreationParams { /// Invoked when the View that contains the ad has been added to the platform /// view hierarchy. final void Function(PlatformAdDisplayContainer container) onContainerAdded; + + /// The layout direction to use for the embedded AdDisplayContainer. + final TextDirection layoutDirection; } /// The interface for a platform implementation for a container in which to diff --git a/packages/interactive_media_ads/pigeons/interactive_media_ads_ios.dart b/packages/interactive_media_ads/pigeons/interactive_media_ads_ios.dart new file mode 100644 index 0000000000000..934518843645b --- /dev/null +++ b/packages/interactive_media_ads/pigeons/interactive_media_ads_ios.dart @@ -0,0 +1,508 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO(bparrishMines): Uncomment this file once +// https://github.com/flutter/packages/pull/6602 lands. This file uses the +// Swift ProxyApi feature from pigeon. +// ignore_for_file: avoid_unused_constructor_parameters + +/* +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + copyrightHeader: 'pigeons/copyright.txt', + dartOut: 'lib/src/ios/interactive_media_ads.g.dart', + swiftOut: + 'ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsLibrary.g.swift', + ), +) + +/// Possible error types while loading or playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAErrorType.html. +enum AdErrorType { + /// An error occurred while loading the ads. + loadingFailed, + + /// An error occurred while playing the ads. + adPlayingFailed, + + /// An unexpected error occurred while loading or playing the ads. + /// + /// This may mean that the SDK wasn’t loaded properly or the wrapper doesn't + /// recognize this value. + unknown, +} + +/// Possible error codes raised while loading or playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAErrorCode.html. +enum AdErrorCode { + /// The ad slot is not visible on the page. + adslotNotVisible, + + /// Generic invalid usage of the API. + apiError, + + /// A companion ad failed to load or render. + companionAdLoadingFailed, + + /// Content playhead was not passed in, but list of ads has been returned from + /// the server. + contentPlayheadMissing, + + /// There was an error loading the ad. + failedLoadingAd, + + /// There was a problem requesting ads from the server. + failedToRequestAds, + + /// Invalid arguments were provided to SDK methods. + invalidArguments, + + /// The version of the runtime is too old. + osRuntimeTooOld, + + /// Ads list response was malformed. + playlistMalformedResponse, + + /// Listener for at least one of the required vast events was not added. + requiredListenersNotAdded, + + /// There was an error initializing the stream. + streamInitializationFailed, + + /// An unexpected error occurred and the cause is not known. + unknownError, + + /// No assets were found in the VAST ad response. + vastAssetNotFound, + + /// A VAST response containing a single `` tag with no child tags. + vastEmptyResponse, + + /// At least one VAST wrapper loaded and a subsequent wrapper or inline ad + /// load has resulted in a 404 response code. + vastInvalidUrl, + + /// Assets were found in the VAST ad response for a linear ad, but none of + /// them matched the video player's capabilities. + vastLinearAssetMismatch, + + /// The VAST URI provided, or a VAST URI provided in a subsequent Wrapper + /// element, was either unavailable or reached a timeout, as defined by the + /// video player. + vastLoadTimeout, + + /// The ad response was not recognized as a valid VAST ad. + vastMalformedResponse, + + /// Failed to load media assets from a VAST response. + vastMediaLoadTimeout, + + /// The maximum number of VAST wrapper redirects has been reached. + vastTooManyRedirects, + + /// Trafficking error. + /// + /// Video player received an ad type that it was not expecting and/or cannot + /// display. + vastTraffickingError, + + /// Another VideoAdsManager is still using the video. + videoElementUsed, + + /// A video element was not specified where it was required. + videoElementRequired, + + /// There was an error playing the video ad. + videoPlayError, +} + +/// Different event types sent by the IMAAdsManager to its delegate. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAAdEventType.html. +enum AdEventType { + /// Fired the first time each ad break ends. + adBreakEnded, + + /// Fired when an ad break will not play back any ads. + adBreakFetchError, + + /// Fired when an ad break is ready. + adBreakReady, + + /// Fired first time each ad break begins playback. + adBreakStarted, + + /// Fired every time the stream switches from advertising or slate to content. + adPeriodEnded, + + /// Fired every time the stream switches from content to advertising or slate. + adPeriodStarted, + + /// All valid ads managed by the ads manager have completed or the ad response + /// did not return any valid ads. + allAdsCompleted, + + /// Fired when an ad is clicked. + clicked, + + /// Single ad has finished. + completed, + + /// Cuepoints changed for VOD stream (only used for dynamic ad insertion). + cuepointsChanged, + + /// First quartile of a linear ad was reached. + firstQuartile, + + /// The user has closed the icon fallback image dialog. + iconFallbackImageClosed, + + /// The user has tapped an ad icon. + iconTapped, + + /// An ad was loaded. + loaded, + + /// A log event for the ads being played. + log, + + /// Midpoint of a linear ad was reached. + midpoint, + + /// Ad paused. + pause, + + /// Ad resumed. + resume, + + /// Fired when an ad was skipped. + skipped, + + /// Fired when an ad starts playing. + started, + + /// Stream request has loaded (only used for dynamic ad insertion). + streamLoaded, + + /// Stream has started playing (only used for dynamic ad insertion). + streamStarted, + + /// Ad tapped. + tapped, + + /// Third quartile of a linear ad was reached.. + thirdQuartile, + + /// The event type is not recognized by this wrapper. + unknown, +} + +/// The values that can be returned in a change dictionary. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvalueobservingoptions?language=objc. +enum KeyValueObservingOptions { + /// Indicates that the change dictionary should provide the new attribute + /// value, if applicable. + newValue, + + /// Indicates that the change dictionary should contain the old attribute + /// value, if applicable. + oldValue, + + /// If specified, a notification should be sent to the observer immediately, + /// before the observer registration method even returns. + initialValue, + + /// Whether separate notifications should be sent to the observer before and + /// after each change, instead of a single notification after the change. + priorNotification, +} + +/// The kinds of changes that can be observed.. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvaluechange?language=objc. +enum KeyValueChange { + /// Indicates that the value of the observed key path was set to a new value. + setting, + + /// Indicates that an object has been inserted into the to-many relationship + /// that is being observed. + insertion, + + /// Indicates that an object has been removed from the to-many relationship + /// that is being observed. + removal, + + /// Indicates that an object has been replaced in the to-many relationship + /// that is being observed. + replacement, +} + +/// The keys that can appear in the change dictionary.. +/// +/// See https://developer.apple.com/documentation/foundation/nskeyvaluechangekey?language=objc. +enum KeyValueChangeKey { + /// If the value of the kindKey entry is NSKeyValueChange.insertion, + /// NSKeyValueChange.removal, or NSKeyValueChange.replacement, the value of + /// this key is an NSIndexSet object that contains the indexes of the + /// inserted, removed, or replaced objects. + indexes, + + /// An NSNumber object that contains a value corresponding to one of the + /// NSKeyValueChange enums, indicating what sort of change has occurred. + kind, + + /// If the value of the kindKey entry is NSKeyValueChange.setting, and new was + /// specified when the observer was registered, the value of this key is the + /// new value for the attribute. + newValue, + + /// If the prior option was specified when the observer was registered this + /// notification is sent prior to a change. + notificationIsPrior, + + /// If the value of the kindKey entry is NSKeyValueChange.setting, and old was + /// specified when the observer was registered, the value of this key is the + /// value before the attribute was changed. + oldValue, + + /// The key is not recognized by this wrapper. + unknown, +} + +/// The `IMAAdDisplayContainer` is responsible for managing the ad container +/// view and companion ad slots used for ad playback. +/// +/// See https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/ios/reference/Classes/IMAAdDisplayContainer. +@ProxyApi( + swiftOptions: SwiftProxyApiOptions(import: 'GoogleInteractiveMediaAds'), +) +abstract class IMAAdDisplayContainer extends NSObject { + IMAAdDisplayContainer( + UIView adContainer, + UIViewController? adContainerViewController, + ); +} + +/// An object that manages the content for a rectangular area on the screen. +/// +/// See https://developer.apple.com/documentation/uikit/uiview. +@ProxyApi(swiftOptions: SwiftProxyApiOptions(import: 'UIKit')) +abstract class UIView extends NSObject {} + +/// An object that manages a view hierarchy for your UIKit app. +/// +/// See https://developer.apple.com/documentation/uikit/uiviewcontroller. +@ProxyApi() +abstract class UIViewController extends NSObject { + UIViewController(); + + /// Notifies the view controller that its view was added to a view hierarchy. + late void Function(bool animated)? viewDidAppear; + + /// Retrieves the view that the controller manages. + /// + /// For convenience this is a `final` attached field despite this being + /// settable. Since this is not a part of the IMA SDK this is slightly changed + /// for convenience. Note that this wrapper should not add the ability to set + /// this property as it should not be needed anyways. + @attached + late final UIView view; +} + +/// Defines an interface for a class that tracks video content progress and +/// exposes a key value observable property |currentTime|. +/// +/// See https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/ios/reference/Protocols/IMAContentPlayhead. +@ProxyApi() +abstract class IMAContentPlayhead extends NSObject { + IMAContentPlayhead(); + + /// Reflects the current playback time in seconds for the content. + void setCurrentTime(double timeInterval); +} + +/// Allows the requesting of ads from the ad server. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsLoader. +@ProxyApi() +abstract class IMAAdsLoader extends NSObject { + IMAAdsLoader(IMASettings? settings); + + /// Signal to the SDK that the content has completed. + void contentComplete(); + + /// Request ads from the ad server. + void requestAds(IMAAdsRequest request); + + /// Delegate that receives `IMAAdsLoaderDelegate` callbacks. + /// + /// Note that this sets to a `weak` property in Swift. + void setDelegate(IMAAdsLoaderDelegate? delegate); +} + +/// The IMASettings class stores SDK wide settings. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMASettings.html. +@ProxyApi() +abstract class IMASettings extends NSObject {} + +/// Data class describing the ad request. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsRequest. +@ProxyApi() +abstract class IMAAdsRequest extends NSObject { + /// Initializes an ads request instance with the given ad tag URL and ad + /// display container. + IMAAdsRequest( + String adTagUrl, + IMAAdDisplayContainer adDisplayContainer, + IMAContentPlayhead? contentPlayhead, + ); +} + +/// Delegate object that receives state change callbacks from `IMAAdsLoader`. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Protocols/IMAAdsLoaderDelegate.html. +@ProxyApi() +abstract class IMAAdsLoaderDelegate extends NSObject { + IMAAdsLoaderDelegate(); + + /// Called when ads are successfully loaded from the ad servers by the loader. + late final void Function( + IMAAdsLoader loader, + IMAAdsLoadedData adsLoadedData, + ) adLoaderLoadedWith; + + /// Error reported by the ads loader when loading or requesting an ad fails. + late final void Function( + IMAAdsLoader loader, + IMAAdLoadingErrorData adErrorData, + ) adsLoaderFailedWithErrorData; +} + +/// Ad data that is returned when the ads loader loads the ad. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsLoadedData.html. +@ProxyApi() +abstract class IMAAdsLoadedData extends NSObject { + /// The ads manager instance created by the ads loader. + /// + /// Will be null when using dynamic ad insertion. + IMAAdsManager? adsManager; +} + +/// Ad error data that is returned when the ads loader fails to load the ad. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdLoadingErrorData.html. +@ProxyApi() +abstract class IMAAdLoadingErrorData extends NSObject { + /// The ad error that occurred while loading the ad. + late final IMAAdError adError; +} + +/// Surfaces an error that occurred during ad loading or playing. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdError.html. +@ProxyApi() +abstract class IMAAdError extends NSObject { + /// The type of error that occurred during ad loading or ad playing. + late final AdErrorType type; + + /// The error code for obtaining more specific information about the error. + late final AdErrorCode code; + + /// A brief description about the error. + late final String? message; +} + +/// Responsible for playing ads. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdsManager.html. +@ProxyApi() +abstract class IMAAdsManager extends NSObject { + /// The `IMAAdsManagerDelegate` to notify with events during ad playback. + void setDelegate(IMAAdsManagerDelegate? delegate); + + /// Initializes and loads the ad. + void initialize(IMAAdsRenderingSettings? adsRenderingSettings); + + /// Starts advertisement playback. + void start(); + + /// Pauses advertisement. + void pause(); + + /// Resumes the current ad. + void resume(); + + /// Skips the advertisement if the ad is skippable and the skip offset has + /// been reached. + void skip(); + + /// If an ad break is currently playing, discard it and resume content. + void discardAdBreak(); + + /// Causes the ads manager to stop the ad and clean its internal state. + void destroy(); +} + +/// A callback protocol for IMAAdsManager. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Protocols/IMAAdsManagerDelegate.html. +@ProxyApi() +abstract class IMAAdsManagerDelegate extends NSObject { + IMAAdsManagerDelegate(); + + /// Called when there is an IMAAdEvent. + late final void Function( + IMAAdsManager adsManager, + IMAAdEvent event, + ) didReceiveAdEvent; + + /// Called when there was an error playing the ad. + late final void Function( + IMAAdsManager adsManager, + IMAAdError error, + ) didReceiveAdError; + + /// Called when an ad is ready to play. + late final void Function(IMAAdsManager adsManager) didRequestContentPause; + + /// Called when an ad has finished or an error occurred during the playback. + late final void Function(IMAAdsManager adsManager) didRequestContentResume; +} + +/// Simple data class used to transport ad playback information. +/// +/// See https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes/IMAAdEvent.html. +@ProxyApi() +abstract class IMAAdEvent extends NSObject { + /// Type of the event. + late final AdEventType type; + + /// Stringified type of the event. + late final String typeString; +} + +/// Set of properties that influence how ads are rendered. +/// +/// See https://developers.google.com/ad-manager/dynamic-ad-insertion/sdk/ios/reference/Classes/IMAAdsRenderingSettings. +@ProxyApi() +abstract class IMAAdsRenderingSettings extends NSObject { + IMAAdsRenderingSettings(); +} + +/// The root class of most Objective-C class hierarchies, from which subclasses +/// inherit a basic interface to the runtime system and the ability to behave as +/// Objective-C objects. +/// +/// See https://developer.apple.com/documentation/objectivec/nsobject. +@ProxyApi() +abstract class NSObject {} +*/ diff --git a/packages/interactive_media_ads/pubspec.yaml b/packages/interactive_media_ads/pubspec.yaml index 0e17f79376de6..a304c951bb378 100644 --- a/packages/interactive_media_ads/pubspec.yaml +++ b/packages/interactive_media_ads/pubspec.yaml @@ -2,7 +2,9 @@ name: interactive_media_ads description: A Flutter plugin for using the Interactive Media Ads SDKs on Android and iOS. repository: https://github.com/flutter/packages/tree/main/packages/interactive_media_ads issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+interactive_media_ads%22 -version: 0.1.0+2 # This must match the version in `android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt` +version: 0.1.1 # This must match the version in + # `android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt` and + # `ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift` environment: sdk: ^3.2.3 @@ -17,6 +19,7 @@ flutter: dartPluginClass: AndroidInteractiveMediaAds ios: pluginClass: InteractiveMediaAdsPlugin + dartPluginClass: IOSInteractiveMediaAds dependencies: flutter: diff --git a/packages/interactive_media_ads/test/ios/ad_display_container_test.dart b/packages/interactive_media_ads/test/ios/ad_display_container_test.dart new file mode 100644 index 0000000000000..b3eb09356394f --- /dev/null +++ b/packages/interactive_media_ads/test/ios/ad_display_container_test.dart @@ -0,0 +1,94 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:interactive_media_ads/src/ios/interactive_media_ads.g.dart'; +import 'package:interactive_media_ads/src/ios/interactive_media_ads_proxy.dart'; +import 'package:interactive_media_ads/src/ios/ios_ad_display_container.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'ad_display_container_test.mocks.dart'; + +@GenerateNiceMocks(>[ + MockSpec(), + MockSpec(), + MockSpec(), +]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('IOSAdDisplayContainer', () { + testWidgets('build with key', (WidgetTester tester) async { + final IOSAdDisplayContainer container = IOSAdDisplayContainer( + IOSAdDisplayContainerCreationParams( + key: const Key('testKey'), + onContainerAdded: (_) {}, + ), + ); + + await tester.pumpWidget(Builder( + builder: (BuildContext context) => container.build(context), + )); + + expect(find.byType(UiKitView), findsOneWidget); + expect(find.byKey(const Key('testKey')), findsOneWidget); + }); + + testWidgets('onContainerAdded is called', (WidgetTester tester) async { + late final void Function(UIViewController, bool) viewDidAppearCallback; + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newUIViewController: ({ + void Function(UIViewController, bool)? viewDidAppear, + }) { + viewDidAppearCallback = viewDidAppear!; + + final PigeonInstanceManager instanceManager = PigeonInstanceManager( + onWeakReferenceRemoved: (_) {}, + ); + final UIView view = + UIView.pigeon_detached(pigeon_instanceManager: instanceManager); + instanceManager.addDartCreatedInstance(view); + + final MockUIViewController mockController = MockUIViewController(); + when(mockController.view).thenReturn(view); + return mockController; + }, + newIMAAdDisplayContainer: ({ + required UIView adContainer, + UIViewController? adContainerViewController, + }) => + MockIMAAdDisplayContainer(), + ); + + final Completer onContainerAddedCompleter = Completer(); + + final IOSAdDisplayContainer container = IOSAdDisplayContainer( + IOSAdDisplayContainerCreationParams( + onContainerAdded: (_) => onContainerAddedCompleter.complete(), + imaProxy: imaProxy, + ), + ); + + await tester.pumpWidget(Builder( + builder: (BuildContext context) => container.build(context), + )); + + final UiKitView view = + find.byType(UiKitView).evaluate().single.widget as UiKitView; + view.onPlatformViewCreated!.call(0); + + // Ensure onContainerAdded is not called until viewDidAppear is called. + expect(onContainerAddedCompleter.isCompleted, isFalse); + + viewDidAppearCallback(MockUIViewController(), true); + await tester.pumpAndSettle(); + + expect(onContainerAddedCompleter.isCompleted, isTrue); + }); + }); +} diff --git a/packages/interactive_media_ads/test/ios/ad_display_container_test.mocks.dart b/packages/interactive_media_ads/test/ios/ad_display_container_test.mocks.dart new file mode 100644 index 0000000000000..6d07b9fcad238 --- /dev/null +++ b/packages/interactive_media_ads/test/ios/ad_display_container_test.mocks.dart @@ -0,0 +1,198 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in interactive_media_ads/test/ios/ad_display_container_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:interactive_media_ads/src/ios/interactive_media_ads.g.dart' + as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIMAAdDisplayContainer_1 extends _i1.SmartFake + implements _i2.IMAAdDisplayContainer { + _FakeIMAAdDisplayContainer_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUIView_2 extends _i1.SmartFake implements _i2.UIView { + _FakeUIView_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUIViewController_3 extends _i1.SmartFake + implements _i2.UIViewController { + _FakeUIViewController_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [IMAAdDisplayContainer]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIMAAdDisplayContainer extends _i1.Mock + implements _i2.IMAAdDisplayContainer { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.IMAAdDisplayContainer pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeIMAAdDisplayContainer_1( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeIMAAdDisplayContainer_1( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.IMAAdDisplayContainer); +} + +/// A class which mocks [UIView]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUIView extends _i1.Mock implements _i2.UIView { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.UIView pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeUIView_2( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeUIView_2( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.UIView); +} + +/// A class which mocks [UIViewController]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUIViewController extends _i1.Mock implements _i2.UIViewController { + @override + _i2.UIView get view => (super.noSuchMethod( + Invocation.getter(#view), + returnValue: _FakeUIView_2( + this, + Invocation.getter(#view), + ), + returnValueForMissingStub: _FakeUIView_2( + this, + Invocation.getter(#view), + ), + ) as _i2.UIView); + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.UIViewController pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeUIViewController_3( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeUIViewController_3( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.UIViewController); +} diff --git a/packages/interactive_media_ads/test/ios/ads_loader_test.dart b/packages/interactive_media_ads/test/ios/ads_loader_test.dart new file mode 100644 index 0000000000000..04ea706d21286 --- /dev/null +++ b/packages/interactive_media_ads/test/ios/ads_loader_test.dart @@ -0,0 +1,248 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:interactive_media_ads/src/ios/interactive_media_ads.g.dart' + as ima; +import 'package:interactive_media_ads/src/ios/interactive_media_ads_proxy.dart'; +import 'package:interactive_media_ads/src/ios/ios_ad_display_container.dart'; +import 'package:interactive_media_ads/src/ios/ios_ads_loader.dart'; +import 'package:interactive_media_ads/src/platform_interface/platform_interface.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'ads_loader_test.mocks.dart'; + +@GenerateNiceMocks(>[ + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), +]) +void main() { + group('IOSAdsLoader', () { + testWidgets('instantiate IOSAdsLoader', (WidgetTester tester) async { + final IOSAdDisplayContainer container = + await _pumpAdDisplayContainer(tester); + + IOSAdsLoader( + IOSAdsLoaderCreationParams( + container: container, + onAdsLoaded: (PlatformOnAdsLoadedData data) {}, + onAdsLoadError: (AdsLoadErrorData data) {}, + ), + ); + }); + + testWidgets('contentComplete', (WidgetTester tester) async { + final IOSAdDisplayContainer container = await _pumpAdDisplayContainer( + tester, + ); + + final MockIMAAdsLoader mockLoader = MockIMAAdsLoader(); + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsLoader: ({ima.IMASettings? settings}) => mockLoader, + ); + + final IOSAdsLoader loader = IOSAdsLoader( + IOSAdsLoaderCreationParams( + container: container, + onAdsLoaded: (PlatformOnAdsLoadedData data) {}, + onAdsLoadError: (AdsLoadErrorData data) {}, + proxy: imaProxy, + ), + ); + + await loader.contentComplete(); + verify(mockLoader.contentComplete()); + }); + + testWidgets('requestAds', (WidgetTester tester) async { + final IOSAdDisplayContainer container = await _pumpAdDisplayContainer( + tester, + ); + + const String adTag = 'myAdTag'; + + final MockIMAAdsLoader mockLoader = MockIMAAdsLoader(); + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsLoader: ({ima.IMASettings? settings}) => mockLoader, + newIMAAdsRequest: ({ + required String adTagUrl, + required ima.IMAAdDisplayContainer adDisplayContainer, + ima.IMAContentPlayhead? contentPlayhead, + }) { + expect(adTagUrl, adTag); + expect(adDisplayContainer, container.adDisplayContainer); + return MockIMAAdsRequest(); + }, + ); + + final IOSAdsLoader loader = IOSAdsLoader( + IOSAdsLoaderCreationParams( + container: container, + onAdsLoaded: (PlatformOnAdsLoadedData data) {}, + onAdsLoadError: (AdsLoadErrorData data) {}, + proxy: imaProxy, + ), + ); + + await loader.requestAds(AdsRequest(adTagUrl: adTag)); + + verify(mockLoader.requestAds(any)); + }); + + testWidgets('onAdsLoaded', (WidgetTester tester) async { + final IOSAdDisplayContainer container = + await _pumpAdDisplayContainer(tester); + + late final void Function( + ima.IMAAdsLoaderDelegate, + ima.IMAAdsLoader, + ima.IMAAdsLoadedData, + ) adLoaderLoadedWithCallback; + + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsLoader: ({ima.IMASettings? settings}) => MockIMAAdsLoader(), + newIMAAdsLoaderDelegate: ({ + required void Function( + ima.IMAAdsLoaderDelegate, + ima.IMAAdsLoader, + ima.IMAAdsLoadedData, + ) adLoaderLoadedWith, + required dynamic adsLoaderFailedWithErrorData, + }) { + adLoaderLoadedWithCallback = adLoaderLoadedWith; + return MockIMAAdsLoaderDelegate(); + }, + ); + + IOSAdsLoader( + IOSAdsLoaderCreationParams( + container: container, + onAdsLoaded: expectAsync1((_) {}), + onAdsLoadError: (AdsLoadErrorData data) {}, + proxy: imaProxy, + ), + ); + + adLoaderLoadedWithCallback( + MockIMAAdsLoaderDelegate(), + MockIMAAdsLoader(), + ima.IMAAdsLoadedData.pigeon_detached( + adsManager: MockIMAAdsManager(), + pigeon_instanceManager: ima.PigeonInstanceManager( + onWeakReferenceRemoved: (_) {}, + ), + ), + ); + }); + + testWidgets('onAdsLoadError', (WidgetTester tester) async { + final IOSAdDisplayContainer container = + await _pumpAdDisplayContainer(tester); + + late final void Function( + ima.IMAAdsLoaderDelegate, + ima.IMAAdsLoader, + ima.IMAAdLoadingErrorData, + ) adsLoaderFailedWithErrorDataCallback; + + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsLoader: ({ima.IMASettings? settings}) => MockIMAAdsLoader(), + newIMAAdsLoaderDelegate: ({ + required dynamic adLoaderLoadedWith, + required void Function( + ima.IMAAdsLoaderDelegate, + ima.IMAAdsLoader, + ima.IMAAdLoadingErrorData, + ) adsLoaderFailedWithErrorData, + }) { + adsLoaderFailedWithErrorDataCallback = adsLoaderFailedWithErrorData; + return MockIMAAdsLoaderDelegate(); + }, + ); + + IOSAdsLoader( + IOSAdsLoaderCreationParams( + container: container, + onAdsLoaded: (PlatformOnAdsLoadedData data) {}, + onAdsLoadError: expectAsync1((AdsLoadErrorData data) { + expect(data.error.type, AdErrorType.loading); + expect(data.error.code, AdErrorCode.apiError); + }), + proxy: imaProxy, + ), + ); + + final ima.PigeonInstanceManager instanceManager = + ima.PigeonInstanceManager( + onWeakReferenceRemoved: (_) {}, + ); + + adsLoaderFailedWithErrorDataCallback( + MockIMAAdsLoaderDelegate(), + MockIMAAdsLoader(), + ima.IMAAdLoadingErrorData.pigeon_detached( + adError: ima.IMAAdError.pigeon_detached( + type: ima.AdErrorType.loadingFailed, + code: ima.AdErrorCode.apiError, + pigeon_instanceManager: instanceManager, + ), + pigeon_instanceManager: instanceManager, + ), + ); + }); + }); +} + +Future _pumpAdDisplayContainer( + WidgetTester tester) async { + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newUIViewController: ({ + void Function(ima.UIViewController, bool)? viewDidAppear, + }) { + final ima.PigeonInstanceManager instanceManager = + ima.PigeonInstanceManager( + onWeakReferenceRemoved: (_) {}, + ); + final ima.UIView view = + ima.UIView.pigeon_detached(pigeon_instanceManager: instanceManager); + instanceManager.addDartCreatedInstance(view); + + final MockUIViewController mockController = MockUIViewController(); + viewDidAppear!.call(mockController, true); + when(mockController.view).thenReturn(view); + return mockController; + }, + newIMAAdDisplayContainer: ({ + required ima.UIView adContainer, + ima.UIViewController? adContainerViewController, + }) => + MockIMAAdDisplayContainer(), + ); + + final IOSAdDisplayContainer container = IOSAdDisplayContainer( + IOSAdDisplayContainerCreationParams( + onContainerAdded: expectAsync1((_) {}), + imaProxy: imaProxy, + ), + ); + + await tester.pumpWidget(Builder( + builder: (BuildContext context) => container.build(context), + )); + + final UiKitView view = + find.byType(UiKitView).evaluate().single.widget as UiKitView; + view.onPlatformViewCreated!.call(0); + + await tester.pumpAndSettle(const Duration(seconds: 1)); + + return container; +} diff --git a/packages/interactive_media_ads/test/ios/ads_loader_test.mocks.dart b/packages/interactive_media_ads/test/ios/ads_loader_test.mocks.dart new file mode 100644 index 0000000000000..64c4de9ed3143 --- /dev/null +++ b/packages/interactive_media_ads/test/ios/ads_loader_test.mocks.dart @@ -0,0 +1,523 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in interactive_media_ads/test/ios/ads_loader_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:interactive_media_ads/src/ios/interactive_media_ads.g.dart' + as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIMAAdDisplayContainer_1 extends _i1.SmartFake + implements _i2.IMAAdDisplayContainer { + _FakeIMAAdDisplayContainer_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIMAAdsLoader_2 extends _i1.SmartFake implements _i2.IMAAdsLoader { + _FakeIMAAdsLoader_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIMAAdsLoaderDelegate_3 extends _i1.SmartFake + implements _i2.IMAAdsLoaderDelegate { + _FakeIMAAdsLoaderDelegate_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIMAAdsManager_4 extends _i1.SmartFake implements _i2.IMAAdsManager { + _FakeIMAAdsManager_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIMAAdsRequest_5 extends _i1.SmartFake implements _i2.IMAAdsRequest { + _FakeIMAAdsRequest_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUIView_6 extends _i1.SmartFake implements _i2.UIView { + _FakeUIView_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUIViewController_7 extends _i1.SmartFake + implements _i2.UIViewController { + _FakeUIViewController_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [IMAAdDisplayContainer]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIMAAdDisplayContainer extends _i1.Mock + implements _i2.IMAAdDisplayContainer { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.IMAAdDisplayContainer pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeIMAAdDisplayContainer_1( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeIMAAdDisplayContainer_1( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.IMAAdDisplayContainer); +} + +/// A class which mocks [IMAAdsLoader]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIMAAdsLoader extends _i1.Mock implements _i2.IMAAdsLoader { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i3.Future contentComplete() => (super.noSuchMethod( + Invocation.method( + #contentComplete, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future requestAds(_i2.IMAAdsRequest? request) => + (super.noSuchMethod( + Invocation.method( + #requestAds, + [request], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future setDelegate(_i2.IMAAdsLoaderDelegate? delegate) => + (super.noSuchMethod( + Invocation.method( + #setDelegate, + [delegate], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i2.IMAAdsLoader pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeIMAAdsLoader_2( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeIMAAdsLoader_2( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.IMAAdsLoader); +} + +/// A class which mocks [IMAAdsLoaderDelegate]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIMAAdsLoaderDelegate extends _i1.Mock + implements _i2.IMAAdsLoaderDelegate { + @override + void Function( + _i2.IMAAdsLoaderDelegate, + _i2.IMAAdsLoader, + _i2.IMAAdsLoadedData, + ) get adLoaderLoadedWith => (super.noSuchMethod( + Invocation.getter(#adLoaderLoadedWith), + returnValue: ( + _i2.IMAAdsLoaderDelegate pigeon_instance, + _i2.IMAAdsLoader loader, + _i2.IMAAdsLoadedData adsLoadedData, + ) {}, + returnValueForMissingStub: ( + _i2.IMAAdsLoaderDelegate pigeon_instance, + _i2.IMAAdsLoader loader, + _i2.IMAAdsLoadedData adsLoadedData, + ) {}, + ) as void Function( + _i2.IMAAdsLoaderDelegate, + _i2.IMAAdsLoader, + _i2.IMAAdsLoadedData, + )); + + @override + void Function( + _i2.IMAAdsLoaderDelegate, + _i2.IMAAdsLoader, + _i2.IMAAdLoadingErrorData, + ) get adsLoaderFailedWithErrorData => (super.noSuchMethod( + Invocation.getter(#adsLoaderFailedWithErrorData), + returnValue: ( + _i2.IMAAdsLoaderDelegate pigeon_instance, + _i2.IMAAdsLoader loader, + _i2.IMAAdLoadingErrorData adErrorData, + ) {}, + returnValueForMissingStub: ( + _i2.IMAAdsLoaderDelegate pigeon_instance, + _i2.IMAAdsLoader loader, + _i2.IMAAdLoadingErrorData adErrorData, + ) {}, + ) as void Function( + _i2.IMAAdsLoaderDelegate, + _i2.IMAAdsLoader, + _i2.IMAAdLoadingErrorData, + )); + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.IMAAdsLoaderDelegate pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeIMAAdsLoaderDelegate_3( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeIMAAdsLoaderDelegate_3( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.IMAAdsLoaderDelegate); +} + +/// A class which mocks [IMAAdsManager]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIMAAdsManager extends _i1.Mock implements _i2.IMAAdsManager { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i3.Future setDelegate(_i2.IMAAdsManagerDelegate? delegate) => + (super.noSuchMethod( + Invocation.method( + #setDelegate, + [delegate], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future initialize( + _i2.IMAAdsRenderingSettings? adsRenderingSettings) => + (super.noSuchMethod( + Invocation.method( + #initialize, + [adsRenderingSettings], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future start() => (super.noSuchMethod( + Invocation.method( + #start, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future destroy() => (super.noSuchMethod( + Invocation.method( + #destroy, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i2.IMAAdsManager pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeIMAAdsManager_4( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeIMAAdsManager_4( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.IMAAdsManager); +} + +/// A class which mocks [IMAAdsRequest]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIMAAdsRequest extends _i1.Mock implements _i2.IMAAdsRequest { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.IMAAdsRequest pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeIMAAdsRequest_5( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeIMAAdsRequest_5( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.IMAAdsRequest); +} + +/// A class which mocks [UIView]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUIView extends _i1.Mock implements _i2.UIView { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.UIView pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeUIView_6( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeUIView_6( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.UIView); +} + +/// A class which mocks [UIViewController]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUIViewController extends _i1.Mock implements _i2.UIViewController { + @override + _i2.UIView get view => (super.noSuchMethod( + Invocation.getter(#view), + returnValue: _FakeUIView_6( + this, + Invocation.getter(#view), + ), + returnValueForMissingStub: _FakeUIView_6( + this, + Invocation.getter(#view), + ), + ) as _i2.UIView); + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i2.UIViewController pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeUIViewController_7( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeUIViewController_7( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.UIViewController); +} diff --git a/packages/interactive_media_ads/test/ios/ads_manager_delegate_tests.dart b/packages/interactive_media_ads/test/ios/ads_manager_delegate_tests.dart new file mode 100644 index 0000000000000..398d8600e0583 --- /dev/null +++ b/packages/interactive_media_ads/test/ios/ads_manager_delegate_tests.dart @@ -0,0 +1,267 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:interactive_media_ads/src/ios/interactive_media_ads.g.dart' + as ima; +import 'package:interactive_media_ads/src/ios/interactive_media_ads_proxy.dart'; +import 'package:interactive_media_ads/src/ios/ios_ads_manager_delegate.dart'; +import 'package:interactive_media_ads/src/platform_interface/platform_interface.dart'; +import 'package:mockito/annotations.dart'; + +@GenerateNiceMocks(>[MockSpec()]) +void main() { + group('IOSAdsManagerDelegate', () { + test('didReceiveAdEvent calls onAdEvent', () { + final ima.PigeonInstanceManager instanceManager = + ima.PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + + late final void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdEvent, + ) didReceiveAdEventCallback; + + late final ima.IMAAdsManagerDelegate delegate; + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsManagerDelegate: ({ + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdEvent, + ) didReceiveAdEvent, + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdError, + ) didReceiveAdError, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentPause, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentResume, + }) { + didReceiveAdEventCallback = didReceiveAdEvent; + delegate = ima.IMAAdsManagerDelegate.pigeon_detached( + didReceiveAdEvent: didReceiveAdEvent, + didReceiveAdError: didReceiveAdError, + didRequestContentPause: didRequestContentPause, + didRequestContentResume: didRequestContentResume, + pigeon_instanceManager: instanceManager, + ); + return delegate; + }, + ); + + final IOSAdsManagerDelegate adsManagerDelegate = IOSAdsManagerDelegate( + IOSAdsManagerDelegateCreationParams( + onAdEvent: expectAsync1((AdEvent event) { + expect(event.type, AdEventType.allAdsCompleted); + }), + proxy: imaProxy, + ), + ); + + // Calls the field because the value is instantiated lazily. + // ignore: unnecessary_statements + adsManagerDelegate.delegate; + + didReceiveAdEventCallback( + delegate, + ima.IMAAdsManager.pigeon_detached( + pigeon_instanceManager: instanceManager, + ), + ima.IMAAdEvent.pigeon_detached( + type: ima.AdEventType.allAdsCompleted, + typeString: 'typeString', + pigeon_instanceManager: instanceManager, + ), + ); + }); + + test('didRequestContentPause calls onAdEvent', () { + final ima.PigeonInstanceManager instanceManager = + ima.PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + + late final void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentPauseCallback; + + late final ima.IMAAdsManagerDelegate delegate; + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsManagerDelegate: ({ + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdEvent, + ) didReceiveAdEvent, + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdError, + ) didReceiveAdError, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentPause, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentResume, + }) { + didRequestContentPauseCallback = didRequestContentPause; + delegate = ima.IMAAdsManagerDelegate.pigeon_detached( + didReceiveAdEvent: didReceiveAdEvent, + didReceiveAdError: didReceiveAdError, + didRequestContentPause: didRequestContentPause, + didRequestContentResume: didRequestContentResume, + pigeon_instanceManager: instanceManager, + ); + return delegate; + }, + ); + + final IOSAdsManagerDelegate adsManagerDelegate = IOSAdsManagerDelegate( + IOSAdsManagerDelegateCreationParams( + onAdEvent: expectAsync1((AdEvent event) { + expect(event.type, AdEventType.contentPauseRequested); + }), + proxy: imaProxy, + ), + ); + + // Calls the field because the value is instantiated lazily. + // ignore: unnecessary_statements + adsManagerDelegate.delegate; + + didRequestContentPauseCallback( + delegate, + ima.IMAAdsManager.pigeon_detached( + pigeon_instanceManager: instanceManager, + ), + ); + }); + + test('didRequestContentResume calls onAdEvent', () { + final ima.PigeonInstanceManager instanceManager = + ima.PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + + late final void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentResumeCallback; + + late final ima.IMAAdsManagerDelegate delegate; + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsManagerDelegate: ({ + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdEvent, + ) didReceiveAdEvent, + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdError, + ) didReceiveAdError, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentPause, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentResume, + }) { + didRequestContentResumeCallback = didRequestContentResume; + delegate = ima.IMAAdsManagerDelegate.pigeon_detached( + didReceiveAdEvent: didReceiveAdEvent, + didReceiveAdError: didReceiveAdError, + didRequestContentPause: didRequestContentPause, + didRequestContentResume: didRequestContentResume, + pigeon_instanceManager: instanceManager, + ); + return delegate; + }, + ); + + final IOSAdsManagerDelegate adsManagerDelegate = IOSAdsManagerDelegate( + IOSAdsManagerDelegateCreationParams( + onAdEvent: expectAsync1((AdEvent event) { + expect(event.type, AdEventType.contentResumeRequested); + }), + proxy: imaProxy, + ), + ); + + // Calls the field because the value is instantiated lazily. + // ignore: unnecessary_statements + adsManagerDelegate.delegate; + + didRequestContentResumeCallback( + delegate, + ima.IMAAdsManager.pigeon_detached( + pigeon_instanceManager: instanceManager, + ), + ); + }); + + test('didReceiveAdError calls onAdErrorEvent', () { + final ima.PigeonInstanceManager instanceManager = + ima.PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + + late final void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdError, + ) didReceiveAdErrorCallback; + + late final ima.IMAAdsManagerDelegate delegate; + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsManagerDelegate: ({ + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdEvent, + ) didReceiveAdEvent, + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdError, + ) didReceiveAdError, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentPause, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentResume, + }) { + didReceiveAdErrorCallback = didReceiveAdError; + delegate = ima.IMAAdsManagerDelegate.pigeon_detached( + didReceiveAdEvent: didReceiveAdEvent, + didReceiveAdError: didReceiveAdError, + didRequestContentPause: didRequestContentPause, + didRequestContentResume: didRequestContentResume, + pigeon_instanceManager: instanceManager, + ); + return delegate; + }, + ); + + final IOSAdsManagerDelegate adsManagerDelegate = IOSAdsManagerDelegate( + IOSAdsManagerDelegateCreationParams( + onAdErrorEvent: expectAsync1((AdErrorEvent event) { + expect(event.error.type, AdErrorType.loading); + expect(event.error.code, AdErrorCode.apiError); + expect(event.error.message, 'error message'); + }), + proxy: imaProxy, + ), + ); + + // Calls the field because the value is instantiated lazily. + // ignore: unnecessary_statements + adsManagerDelegate.delegate; + + didReceiveAdErrorCallback( + delegate, + ima.IMAAdsManager.pigeon_detached( + pigeon_instanceManager: instanceManager, + ), + ima.IMAAdError.pigeon_detached( + type: ima.AdErrorType.loadingFailed, + code: ima.AdErrorCode.apiError, + message: 'error message', + pigeon_instanceManager: instanceManager, + ), + ); + }); + }); +} diff --git a/packages/interactive_media_ads/test/ios/ads_manager_tests.dart b/packages/interactive_media_ads/test/ios/ads_manager_tests.dart new file mode 100644 index 0000000000000..a46fa1b91d943 --- /dev/null +++ b/packages/interactive_media_ads/test/ios/ads_manager_tests.dart @@ -0,0 +1,86 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:interactive_media_ads/src/ios/interactive_media_ads.g.dart' + as ima; +import 'package:interactive_media_ads/src/ios/interactive_media_ads_proxy.dart'; +import 'package:interactive_media_ads/src/ios/ios_ads_manager.dart'; +import 'package:interactive_media_ads/src/ios/ios_ads_manager_delegate.dart'; +import 'package:interactive_media_ads/src/platform_interface/platform_interface.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'ads_manager_tests.mocks.dart'; + +@GenerateNiceMocks(>[MockSpec()]) +void main() { + group('IOSAdsManager', () { + test('destroy', () { + final MockIMAAdsManager mockAdsManager = MockIMAAdsManager(); + final IOSAdsManager adsManager = IOSAdsManager(mockAdsManager); + adsManager.destroy(); + + verify(mockAdsManager.destroy()); + }); + + test('init', () { + final MockIMAAdsManager mockAdsManager = MockIMAAdsManager(); + final IOSAdsManager adsManager = IOSAdsManager(mockAdsManager); + adsManager.init(AdsManagerInitParams()); + + verify(mockAdsManager.initialize(null)); + }); + + test('start', () { + final MockIMAAdsManager mockAdsManager = MockIMAAdsManager(); + final IOSAdsManager adsManager = IOSAdsManager(mockAdsManager); + adsManager.start(AdsManagerStartParams()); + + verify(mockAdsManager.start()); + }); + + test('setAdsManagerDelegate', () { + final MockIMAAdsManager mockAdsManager = MockIMAAdsManager(); + final IOSAdsManager adsManager = IOSAdsManager(mockAdsManager); + + late final ima.IMAAdsManagerDelegate delegate; + final InteractiveMediaAdsProxy imaProxy = InteractiveMediaAdsProxy( + newIMAAdsManagerDelegate: ({ + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdEvent, + ) didReceiveAdEvent, + required void Function( + ima.IMAAdsManagerDelegate, + ima.IMAAdsManager, + ima.IMAAdError, + ) didReceiveAdError, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentPause, + required void Function(ima.IMAAdsManagerDelegate, ima.IMAAdsManager) + didRequestContentResume, + }) { + delegate = ima.IMAAdsManagerDelegate.pigeon_detached( + didReceiveAdEvent: didReceiveAdEvent, + didReceiveAdError: didReceiveAdError, + didRequestContentPause: didRequestContentPause, + didRequestContentResume: didRequestContentResume, + pigeon_instanceManager: ima.PigeonInstanceManager( + onWeakReferenceRemoved: (_) {}, + ), + ); + return delegate; + }, + ); + + adsManager.setAdsManagerDelegate(IOSAdsManagerDelegate( + IOSAdsManagerDelegateCreationParams(proxy: imaProxy), + )); + + verify(mockAdsManager.setDelegate(delegate)); + }); + }); +} diff --git a/packages/interactive_media_ads/test/ios/ads_manager_tests.mocks.dart b/packages/interactive_media_ads/test/ios/ads_manager_tests.mocks.dart new file mode 100644 index 0000000000000..54b13f521920d --- /dev/null +++ b/packages/interactive_media_ads/test/ios/ads_manager_tests.mocks.dart @@ -0,0 +1,127 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in interactive_media_ads/test/ios/ads_manager_tests.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:interactive_media_ads/src/ios/interactive_media_ads.g.dart' + as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIMAAdsManager_1 extends _i1.SmartFake implements _i2.IMAAdsManager { + _FakeIMAAdsManager_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [IMAAdsManager]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIMAAdsManager extends _i1.Mock implements _i2.IMAAdsManager { + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + returnValueForMissingStub: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) as _i2.PigeonInstanceManager); + + @override + _i3.Future setDelegate(_i2.IMAAdsManagerDelegate? delegate) => + (super.noSuchMethod( + Invocation.method( + #setDelegate, + [delegate], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future initialize( + _i2.IMAAdsRenderingSettings? adsRenderingSettings) => + (super.noSuchMethod( + Invocation.method( + #initialize, + [adsRenderingSettings], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future start() => (super.noSuchMethod( + Invocation.method( + #start, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future destroy() => (super.noSuchMethod( + Invocation.method( + #destroy, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i2.IMAAdsManager pigeon_copy() => (super.noSuchMethod( + Invocation.method( + #pigeon_copy, + [], + ), + returnValue: _FakeIMAAdsManager_1( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + returnValueForMissingStub: _FakeIMAAdsManager_1( + this, + Invocation.method( + #pigeon_copy, + [], + ), + ), + ) as _i2.IMAAdsManager); +} diff --git a/packages/interactive_media_ads/test/version_test.dart b/packages/interactive_media_ads/test/version_test.dart index 0bd444e995ba9..a04edc460620e 100644 --- a/packages/interactive_media_ads/test/version_test.dart +++ b/packages/interactive_media_ads/test/version_test.dart @@ -8,11 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; void main() { test('AdsRequestProxyApi.pluginVersion matches pubspec version', () { - final String pubspecPath = '${Directory.current.path}/pubspec.yaml'; - final String pubspec = File(pubspecPath).readAsStringSync(); - final RegExp regex = RegExp(r'version:\s*(.*?) #'); - final RegExpMatch? match = regex.firstMatch(pubspec); - final String pubspecVersion = match!.group(1)!.trim(); + final String pubspecVersion = _getPubspecVersion(); final String adsRequestProxyApiPath = '${Directory.current.path}/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt'; @@ -24,4 +20,28 @@ void main() { contains('const val pluginVersion = "$pubspecVersion"'), ); }); + + test('AdsRequestProxyAPIDelegate.pluginVersion matches pubspec version', () { + final String pubspecVersion = _getPubspecVersion(); + + final String adsRequestProxyApiDelegatePath = + '${Directory.current.path}/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift'; + final String apiFileAsString = + File(adsRequestProxyApiDelegatePath).readAsStringSync(); + + expect( + apiFileAsString, + contains('static let pluginVersion = "$pubspecVersion"'), + ); + }); +} + +String _getPubspecVersion() { + final String pubspecPath = '${Directory.current.path}/pubspec.yaml'; + final String pubspec = File(pubspecPath).readAsStringSync(); + + final RegExp regex = RegExp(r'version:\s*(.*?) #'); + final RegExpMatch? match = regex.firstMatch(pubspec); + + return match!.group(1)!.trim(); }