From e9253e60161b498f2528a76198b6cd57a1a0d252 Mon Sep 17 00:00:00 2001
From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com>
Date: Wed, 18 Sep 2024 12:32:19 -0600
Subject: [PATCH] [interactive_media_ads] Adds internal wrapper for Android
native `AdsRenderingSettings` (#7660)
---
packages/interactive_media_ads/CHANGELOG.md | 4 +
.../AdsRenderingSettingsProxyApi.kt | 91 +++
.../AdsRequestProxyApi.kt | 2 +-
.../InteractiveMediaAdsLibrary.g.kt | 519 ++++++++++++++++++
.../ProxyApiRegistrar.kt | 4 +
.../AdsRenderingSettingsProxyApiTest.kt | 158 ++++++
.../AdsRequestProxyAPIDelegate.swift | 2 +-
.../src/android/interactive_media_ads.g.dart | 515 +++++++++++++++++
.../interactive_media_ads_android.dart | 91 +++
packages/interactive_media_ads/pubspec.yaml | 2 +-
10 files changed, 1385 insertions(+), 3 deletions(-)
create mode 100644 packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApi.kt
create mode 100644 packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApiTest.kt
diff --git a/packages/interactive_media_ads/CHANGELOG.md b/packages/interactive_media_ads/CHANGELOG.md
index 99368f39a03a..6da27d963280 100644
--- a/packages/interactive_media_ads/CHANGELOG.md
+++ b/packages/interactive_media_ads/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.2+2
+
+* Adds internal wrapper for Android native `AdsRenderingSettings`.
+
## 0.2.2+1
* Bumps Android dependency `com.google.ads.interactivemedia.v3:interactivemedia` from `3.34.0` to
diff --git a/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApi.kt b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApi.kt
new file mode 100644
index 000000000000..d924ad43f783
--- /dev/null
+++ b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApi.kt
@@ -0,0 +1,91 @@
+// 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.
+
+package dev.flutter.packages.interactive_media_ads
+
+import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+import com.google.ads.interactivemedia.v3.api.UiElement
+
+/**
+ * ProxyApi implementation for [AdsRenderingSettings].
+ *
+ *
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 AdsRenderingSettingsProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) :
+ PigeonApiAdsRenderingSettings(pigeonRegistrar) {
+ override fun getBitrateKbps(pigeon_instance: AdsRenderingSettings): Long {
+ return pigeon_instance.bitrateKbps.toLong()
+ }
+
+ override fun getEnableCustomTabs(pigeon_instance: AdsRenderingSettings): Boolean {
+ return pigeon_instance.enableCustomTabs
+ }
+
+ override fun getEnablePreloading(pigeon_instance: AdsRenderingSettings): Boolean {
+ return pigeon_instance.enablePreloading
+ }
+
+ override fun getFocusSkipButtonWhenAvailable(pigeon_instance: AdsRenderingSettings): Boolean {
+ return pigeon_instance.focusSkipButtonWhenAvailable
+ }
+
+ override fun getMimeTypes(pigeon_instance: AdsRenderingSettings): List {
+ return pigeon_instance.mimeTypes
+ }
+
+ override fun setBitrateKbps(pigeon_instance: AdsRenderingSettings, bitrate: Long) {
+ pigeon_instance.bitrateKbps = bitrate.toInt()
+ }
+
+ override fun setEnableCustomTabs(
+ pigeon_instance: AdsRenderingSettings,
+ enableCustomTabs: Boolean
+ ) {
+ pigeon_instance.enableCustomTabs = enableCustomTabs
+ }
+
+ override fun setEnablePreloading(
+ pigeon_instance: AdsRenderingSettings,
+ enablePreloading: Boolean
+ ) {
+ pigeon_instance.enablePreloading = enablePreloading
+ }
+
+ override fun setFocusSkipButtonWhenAvailable(
+ pigeon_instance: AdsRenderingSettings,
+ enableFocusSkipButton: Boolean
+ ) {
+ pigeon_instance.focusSkipButtonWhenAvailable = enableFocusSkipButton
+ }
+
+ override fun setLoadVideoTimeout(pigeon_instance: AdsRenderingSettings, loadVideoTimeout: Long) {
+ pigeon_instance.setLoadVideoTimeout(loadVideoTimeout.toInt())
+ }
+
+ override fun setMimeTypes(pigeon_instance: AdsRenderingSettings, mimeTypes: List) {
+ pigeon_instance.mimeTypes = mimeTypes
+ }
+
+ override fun setPlayAdsAfterTime(pigeon_instance: AdsRenderingSettings, time: Double) {
+ pigeon_instance.setPlayAdsAfterTime(time)
+ }
+
+ override fun setUiElements(
+ pigeon_instance: AdsRenderingSettings,
+ uiElements: List
+ ) {
+ val nativeUiElements =
+ uiElements.map {
+ when (it) {
+ dev.flutter.packages.interactive_media_ads.UiElement.AD_ATTRIBUTION ->
+ UiElement.AD_ATTRIBUTION
+ dev.flutter.packages.interactive_media_ads.UiElement.COUNTDOWN -> UiElement.COUNTDOWN
+ dev.flutter.packages.interactive_media_ads.UiElement.UNKNOWN ->
+ throw UnsupportedOperationException("$it is not supported.")
+ }
+ }
+ pigeon_instance.setUiElements(nativeUiElements.toSet())
+ }
+}
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 a09099f54f24..d8c7b41b2943 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,7 +21,7 @@ class AdsRequestProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) :
*
* This must match the version in pubspec.yaml.
*/
- const val pluginVersion = "0.2.2+1"
+ const val pluginVersion = "0.2.2+2"
}
override fun setAdTagUrl(pigeon_instance: AdsRequest, adTagUrl: String) {
diff --git a/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/InteractiveMediaAdsLibrary.g.kt b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/InteractiveMediaAdsLibrary.g.kt
index 4056a3d980b6..7dfd13066256 100644
--- a/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/InteractiveMediaAdsLibrary.g.kt
+++ b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/InteractiveMediaAdsLibrary.g.kt
@@ -537,6 +537,12 @@ abstract class InteractiveMediaAdsLibraryPigeonProxyApiRegistrar(
*/
abstract fun getPigeonApiAdEventListener(): PigeonApiAdEventListener
+ /**
+ * An implementation of [PigeonApiAdsRenderingSettings] used to add a new Dart instance of
+ * `AdsRenderingSettings` to the Dart `InstanceManager`.
+ */
+ abstract fun getPigeonApiAdsRenderingSettings(): PigeonApiAdsRenderingSettings
+
fun setUp() {
InteractiveMediaAdsLibraryPigeonInstanceManagerApi.setUpMessageHandlers(
binaryMessenger, instanceManager)
@@ -560,6 +566,8 @@ abstract class InteractiveMediaAdsLibraryPigeonProxyApiRegistrar(
binaryMessenger, getPigeonApiAdsLoadedListener())
PigeonApiAdErrorListener.setUpMessageHandlers(binaryMessenger, getPigeonApiAdErrorListener())
PigeonApiAdEventListener.setUpMessageHandlers(binaryMessenger, getPigeonApiAdEventListener())
+ PigeonApiAdsRenderingSettings.setUpMessageHandlers(
+ binaryMessenger, getPigeonApiAdsRenderingSettings())
}
fun tearDown() {
@@ -580,6 +588,7 @@ abstract class InteractiveMediaAdsLibraryPigeonProxyApiRegistrar(
PigeonApiAdsLoadedListener.setUpMessageHandlers(binaryMessenger, null)
PigeonApiAdErrorListener.setUpMessageHandlers(binaryMessenger, null)
PigeonApiAdEventListener.setUpMessageHandlers(binaryMessenger, null)
+ PigeonApiAdsRenderingSettings.setUpMessageHandlers(binaryMessenger, null)
}
}
@@ -611,6 +620,7 @@ private class InteractiveMediaAdsLibraryPigeonProxyApiBaseCodec(
value is AdErrorCode ||
value is AdErrorType ||
value is AdEventType ||
+ value is UiElement ||
value == null) {
super.writeValue(stream, value)
return
@@ -669,6 +679,8 @@ private class InteractiveMediaAdsLibraryPigeonProxyApiBaseCodec(
registrar.getPigeonApiAdErrorListener().pigeon_newInstance(value) {}
} else if (value is com.google.ads.interactivemedia.v3.api.AdEvent.AdEventListener) {
registrar.getPigeonApiAdEventListener().pigeon_newInstance(value) {}
+ } else if (value is com.google.ads.interactivemedia.v3.api.AdsRenderingSettings) {
+ registrar.getPigeonApiAdsRenderingSettings().pigeon_newInstance(value) {}
}
when {
@@ -854,6 +866,27 @@ enum class AdEventType(val raw: Int) {
}
}
+/**
+ * Describes an element of the ad UI, to be requested or rendered by the SDK.
+ *
+ * See
+ * https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/api/reference/com/google/ads/interactivemedia/v3/api/UiElement.html.
+ */
+enum class UiElement(val raw: Int) {
+ /** The ad attribution UI element, for example, "Ad". */
+ AD_ATTRIBUTION(0),
+ /** Ad attribution is required for a countdown timer to be displayed. */
+ COUNTDOWN(1),
+ /** The element is not recognized by this wrapper. */
+ UNKNOWN(2);
+
+ companion object {
+ fun ofRaw(raw: Int): UiElement? {
+ return values().firstOrNull { it.raw == raw }
+ }
+ }
+}
+
private open class InteractiveMediaAdsLibraryPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
@@ -866,6 +899,9 @@ private open class InteractiveMediaAdsLibraryPigeonCodec : StandardMessageCodec(
131.toByte() -> {
return (readValue(buffer) as Long?)?.let { AdEventType.ofRaw(it.toInt()) }
}
+ 132.toByte() -> {
+ return (readValue(buffer) as Long?)?.let { UiElement.ofRaw(it.toInt()) }
+ }
else -> super.readValueOfType(type, buffer)
}
}
@@ -884,6 +920,10 @@ private open class InteractiveMediaAdsLibraryPigeonCodec : StandardMessageCodec(
stream.write(131)
writeValue(stream, value.raw)
}
+ is UiElement -> {
+ stream.write(132)
+ writeValue(stream, value.raw)
+ }
else -> super.writeValue(stream, value)
}
}
@@ -4101,3 +4141,482 @@ abstract class PigeonApiAdEventListener(
}
}
}
+/**
+ * Defines parameters that control the rendering of ads.
+ *
+ * See
+ * https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/api/reference/com/google/ads/interactivemedia/v3/api/AdsRenderingSettings.html.
+ */
+@Suppress("UNCHECKED_CAST")
+abstract class PigeonApiAdsRenderingSettings(
+ open val pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar
+) {
+ /** Maximum recommended bitrate. */
+ abstract fun getBitrateKbps(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ ): Long
+
+ /** Returns whether the click-through URL will be opened using Custom Tabs feature. */
+ abstract fun getEnableCustomTabs(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ ): Boolean
+
+ /**
+ * Whether the SDK will instruct the player to load the creative in response to
+ * `BaseManager.init()`.
+ */
+ abstract fun getEnablePreloading(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ ): Boolean
+
+ /**
+ * Whether to focus on the skip button when the skippable ad can be skipped on Android TV.
+ *
+ * This is a no-op on non-Android TV devices.
+ */
+ abstract fun getFocusSkipButtonWhenAvailable(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ ): Boolean
+
+ /** The SDK will prioritize the media with MIME type on the list. */
+ abstract fun getMimeTypes(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ ): List
+
+ /**
+ * Maximum recommended bitrate.
+ *
+ * The value is in kbit/s. Default value, -1, means the bitrate will be selected by the SDK.
+ */
+ abstract fun setBitrateKbps(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ bitrate: Long
+ )
+
+ /**
+ * Notifies the SDK whether to launch the click-through URL using Custom Tabs feature.
+ *
+ * Default is false.
+ */
+ abstract fun setEnableCustomTabs(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ enableCustomTabs: Boolean
+ )
+
+ /**
+ * If set, the SDK will instruct the player to load the creative in response to
+ * `BaseManager.init()`.
+ *
+ * This allows the player to preload the ad at any point before calling `AdsManager.start()`.
+ */
+ abstract fun setEnablePreloading(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ enablePreloading: Boolean
+ )
+
+ /**
+ * Set whether to focus on the skip button when the skippable ad can be skipped on Android TV.
+ *
+ * This is a no-op on non-Android TV devices.
+ *
+ * Default is true.
+ */
+ abstract fun setFocusSkipButtonWhenAvailable(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ enableFocusSkipButton: Boolean
+ )
+
+ /**
+ * Specifies a non-default amount of time to wait for media to load before timing out, in
+ * milliseconds.
+ *
+ * This only applies to the IMA client-side SDK.
+ *
+ * Default time is 8000 ms.
+ */
+ abstract fun setLoadVideoTimeout(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ loadVideoTimeout: Long
+ )
+
+ /** If specified, the SDK will prioritize the media with MIME type on the list. */
+ abstract fun setMimeTypes(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ mimeTypes: List
+ )
+
+ /**
+ * For VMAP and ad rules playlists, only play ad breaks scheduled after this time (in seconds).
+ */
+ abstract fun setPlayAdsAfterTime(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ time: Double
+ )
+
+ /** Sets the ad UI elements to be rendered by the IMA SDK. */
+ abstract fun setUiElements(
+ pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ uiElements: List
+ )
+
+ companion object {
+ @Suppress("LocalVariableName")
+ fun setUpMessageHandlers(
+ binaryMessenger: BinaryMessenger,
+ api: PigeonApiAdsRenderingSettings?
+ ) {
+ val codec = api?.pigeonRegistrar?.codec ?: InteractiveMediaAdsLibraryPigeonCodec()
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.getBitrateKbps",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val wrapped: List =
+ try {
+ listOf(api.getBitrateKbps(pigeon_instanceArg))
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.getEnableCustomTabs",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val wrapped: List =
+ try {
+ listOf(api.getEnableCustomTabs(pigeon_instanceArg))
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.getEnablePreloading",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val wrapped: List =
+ try {
+ listOf(api.getEnablePreloading(pigeon_instanceArg))
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.getFocusSkipButtonWhenAvailable",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val wrapped: List =
+ try {
+ listOf(api.getFocusSkipButtonWhenAvailable(pigeon_instanceArg))
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.getMimeTypes",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val wrapped: List =
+ try {
+ listOf(api.getMimeTypes(pigeon_instanceArg))
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setBitrateKbps",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val bitrateArg = args[1] as Long
+ val wrapped: List =
+ try {
+ api.setBitrateKbps(pigeon_instanceArg, bitrateArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setEnableCustomTabs",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val enableCustomTabsArg = args[1] as Boolean
+ val wrapped: List =
+ try {
+ api.setEnableCustomTabs(pigeon_instanceArg, enableCustomTabsArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setEnablePreloading",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val enablePreloadingArg = args[1] as Boolean
+ val wrapped: List =
+ try {
+ api.setEnablePreloading(pigeon_instanceArg, enablePreloadingArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setFocusSkipButtonWhenAvailable",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val enableFocusSkipButtonArg = args[1] as Boolean
+ val wrapped: List =
+ try {
+ api.setFocusSkipButtonWhenAvailable(pigeon_instanceArg, enableFocusSkipButtonArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setLoadVideoTimeout",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val loadVideoTimeoutArg = args[1] as Long
+ val wrapped: List =
+ try {
+ api.setLoadVideoTimeout(pigeon_instanceArg, loadVideoTimeoutArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setMimeTypes",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val mimeTypesArg = args[1] as List
+ val wrapped: List =
+ try {
+ api.setMimeTypes(pigeon_instanceArg, mimeTypesArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setPlayAdsAfterTime",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val timeArg = args[1] as Double
+ val wrapped: List =
+ try {
+ api.setPlayAdsAfterTime(pigeon_instanceArg, timeArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ run {
+ val channel =
+ BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.setUiElements",
+ codec)
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val pigeon_instanceArg =
+ args[0] as com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+ val uiElementsArg = args[1] as List
+ val wrapped: List =
+ try {
+ api.setUiElements(pigeon_instanceArg, uiElementsArg)
+ listOf(null)
+ } catch (exception: Throwable) {
+ wrapError(exception)
+ }
+ reply.reply(wrapped)
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ }
+ }
+
+ @Suppress("LocalVariableName", "FunctionName")
+ /** Creates a Dart instance of AdsRenderingSettings and attaches it to [pigeon_instanceArg]. */
+ fun pigeon_newInstance(
+ pigeon_instanceArg: com.google.ads.interactivemedia.v3.api.AdsRenderingSettings,
+ callback: (Result) -> Unit
+ ) {
+ if (pigeonRegistrar.ignoreCallsToDart) {
+ callback(
+ Result.failure(
+ FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", "")))
+ return
+ }
+ if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) {
+ Result.success(Unit)
+ return
+ }
+ val pigeon_identifierArg =
+ pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg)
+ val binaryMessenger = pigeonRegistrar.binaryMessenger
+ val codec = pigeonRegistrar.codec
+ val channelName =
+ "dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.pigeon_newInstance"
+ val channel = BasicMessageChannel(binaryMessenger, channelName, codec)
+ channel.send(listOf(pigeon_identifierArg)) {
+ if (it is List<*>) {
+ if (it.size > 1) {
+ callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
+ } else {
+ callback(Result.success(Unit))
+ }
+ } else {
+ callback(Result.failure(createConnectionError(channelName)))
+ }
+ }
+ }
+}
diff --git a/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/ProxyApiRegistrar.kt b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/ProxyApiRegistrar.kt
index ff1190eb9fc7..57667057e68a 100644
--- a/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/ProxyApiRegistrar.kt
+++ b/packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/ProxyApiRegistrar.kt
@@ -125,4 +125,8 @@ open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Cont
override fun getPigeonApiMediaPlayer(): PigeonApiMediaPlayer {
return MediaPlayerProxyApi(this)
}
+
+ override fun getPigeonApiAdsRenderingSettings(): PigeonApiAdsRenderingSettings {
+ return AdsRenderingSettingsProxyApi(this)
+ }
}
diff --git a/packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApiTest.kt b/packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApiTest.kt
new file mode 100644
index 000000000000..f7585858a8e4
--- /dev/null
+++ b/packages/interactive_media_ads/android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/AdsRenderingSettingsProxyApiTest.kt
@@ -0,0 +1,158 @@
+// 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.
+
+package dev.flutter.packages.interactive_media_ads
+
+import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
+import com.google.ads.interactivemedia.v3.api.UiElement
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+class AdsRenderingSettingsProxyApiTest {
+ @Test
+ fun getBitrateKbps() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val value = 0
+ whenever(instance.bitrateKbps).thenReturn(value)
+
+ assertEquals(value.toLong(), api.getBitrateKbps(instance))
+ }
+
+ @Test
+ fun getEnableCustomTabs() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val value = true
+ whenever(instance.enableCustomTabs).thenReturn(value)
+
+ assertEquals(value, api.getEnableCustomTabs(instance))
+ }
+
+ @Test
+ fun getEnablePreloading() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val value = true
+ whenever(instance.enablePreloading).thenReturn(value)
+
+ assertEquals(value, api.getEnablePreloading(instance))
+ }
+
+ @Test
+ fun getFocusSkipButtonWhenAvailable() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val value = true
+ whenever(instance.focusSkipButtonWhenAvailable).thenReturn(value)
+
+ assertEquals(value, api.getFocusSkipButtonWhenAvailable(instance))
+ }
+
+ @Test
+ fun getMimeTypes() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val value = listOf("myString")
+ whenever(instance.mimeTypes).thenReturn(value)
+
+ assertEquals(value, api.getMimeTypes(instance))
+ }
+
+ @Test
+ fun setBitrateKbps() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val bitrate = 0L
+ api.setBitrateKbps(instance, bitrate)
+
+ verify(instance).bitrateKbps = bitrate.toInt()
+ }
+
+ @Test
+ fun setEnableCustomTabs() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val enableCustomTabs = true
+ api.setEnableCustomTabs(instance, enableCustomTabs)
+
+ verify(instance).enableCustomTabs = enableCustomTabs
+ }
+
+ @Test
+ fun setEnablePreloading() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val enablePreloading = true
+ api.setEnablePreloading(instance, enablePreloading)
+
+ verify(instance).enablePreloading = enablePreloading
+ }
+
+ @Test
+ fun setFocusSkipButtonWhenAvailable() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val enableFocusSkipButton = true
+ api.setFocusSkipButtonWhenAvailable(instance, enableFocusSkipButton)
+
+ verify(instance).focusSkipButtonWhenAvailable = enableFocusSkipButton
+ }
+
+ @Test
+ fun setLoadVideoTimeout() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val loadVideoTimeout = 0L
+ api.setLoadVideoTimeout(instance, loadVideoTimeout)
+
+ verify(instance).setLoadVideoTimeout(loadVideoTimeout.toInt())
+ }
+
+ @Test
+ fun setMimeTypes() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val mimeTypes = listOf("myString")
+ api.setMimeTypes(instance, mimeTypes)
+
+ verify(instance).mimeTypes = mimeTypes
+ }
+
+ @Test
+ fun setPlayAdsAfterTime() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val time = 1.0
+ api.setPlayAdsAfterTime(instance, time)
+
+ verify(instance).setPlayAdsAfterTime(time)
+ }
+
+ @Test
+ fun setUiElements() {
+ val api = TestProxyApiRegistrar().getPigeonApiAdsRenderingSettings()
+
+ val instance = mock()
+ val uiElements = listOf(dev.flutter.packages.interactive_media_ads.UiElement.AD_ATTRIBUTION)
+ api.setUiElements(instance, uiElements)
+
+ verify(instance).setUiElements(setOf(UiElement.AD_ATTRIBUTION))
+ }
+}
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
index 9c2dcbd2f1d0..50a4dcd4e307 100644
--- 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
@@ -13,7 +13,7 @@ class AdsRequestProxyAPIDelegate: PigeonApiDelegateIMAAdsRequest {
/// The current version of the `interactive_media_ads` plugin.
///
/// This must match the version in pubspec.yaml.
- static let pluginVersion = "0.2.2+1"
+ static let pluginVersion = "0.2.2+2"
func pigeonDefaultConstructor(
pigeonApi: PigeonApiIMAAdsRequest, adTagUrl: String, adDisplayContainer: IMAAdDisplayContainer,
diff --git a/packages/interactive_media_ads/lib/src/android/interactive_media_ads.g.dart b/packages/interactive_media_ads/lib/src/android/interactive_media_ads.g.dart
index 927161d0bcee..4a1dd1516c5a 100644
--- a/packages/interactive_media_ads/lib/src/android/interactive_media_ads.g.dart
+++ b/packages/interactive_media_ads/lib/src/android/interactive_media_ads.g.dart
@@ -189,6 +189,8 @@ class PigeonInstanceManager {
pigeon_instanceManager: instanceManager);
AdEventListener.pigeon_setUpMessageHandlers(
pigeon_instanceManager: instanceManager);
+ AdsRenderingSettings.pigeon_setUpMessageHandlers(
+ pigeon_instanceManager: instanceManager);
return instanceManager;
}
@@ -639,6 +641,20 @@ enum AdEventType {
unknown,
}
+/// Describes an element of the ad UI, to be requested or rendered by the SDK.
+///
+/// See https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/api/reference/com/google/ads/interactivemedia/v3/api/UiElement.html.
+enum UiElement {
+ /// The ad attribution UI element, for example, "Ad".
+ adAttribution,
+
+ /// Ad attribution is required for a countdown timer to be displayed.
+ countdown,
+
+ /// The element is not recognized by this wrapper.
+ unknown,
+}
+
class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@override
@@ -655,6 +671,9 @@ class _PigeonCodec extends StandardMessageCodec {
} else if (value is AdEventType) {
buffer.putUint8(131);
writeValue(buffer, value.index);
+ } else if (value is UiElement) {
+ buffer.putUint8(132);
+ writeValue(buffer, value.index);
} else {
super.writeValue(buffer, value);
}
@@ -672,6 +691,9 @@ class _PigeonCodec extends StandardMessageCodec {
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 : UiElement.values[value];
default:
return super.readValueOfType(type, buffer);
}
@@ -4975,3 +4997,496 @@ class AdEventListener extends PigeonInternalProxyApiBaseClass {
);
}
}
+
+/// Defines parameters that control the rendering of ads.
+///
+/// See https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/api/reference/com/google/ads/interactivemedia/v3/api/AdsRenderingSettings.html.
+class AdsRenderingSettings extends PigeonInternalProxyApiBaseClass {
+ /// Constructs [AdsRenderingSettings] 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
+ AdsRenderingSettings.pigeon_detached({
+ super.pigeon_binaryMessenger,
+ super.pigeon_instanceManager,
+ });
+
+ late final _PigeonInternalProxyApiBaseCodec
+ _pigeonVar_codecAdsRenderingSettings =
+ _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager);
+
+ static void pigeon_setUpMessageHandlers({
+ bool pigeon_clearHandlers = false,
+ BinaryMessenger? pigeon_binaryMessenger,
+ PigeonInstanceManager? pigeon_instanceManager,
+ AdsRenderingSettings Function()? pigeon_newInstance,
+ }) {
+ final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec =
+ _PigeonInternalProxyApiBaseCodec(
+ pigeon_instanceManager ?? PigeonInstanceManager.instance);
+ final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger;
+ {
+ final BasicMessageChannel<
+ Object?> pigeonVar_channel = BasicMessageChannel<
+ Object?>(
+ 'dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.pigeon_newInstance',
+ pigeonChannelCodec,
+ binaryMessenger: binaryMessenger);
+ if (pigeon_clearHandlers) {
+ pigeonVar_channel.setMessageHandler(null);
+ } else {
+ pigeonVar_channel.setMessageHandler((Object? message) async {
+ assert(message != null,
+ 'Argument for dev.flutter.pigeon.interactive_media_ads.AdsRenderingSettings.pigeon_newInstance was null.');
+ final List