Skip to content

[interactive_media_ads] Adds support for all AdEventTypes and ad data #7287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/interactive_media_ads/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 0.1.2

* Adds support for all `AdEventType`s and ad data. See `AdEvent.adData`.
* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.

## 0.1.1+1
Expand Down
3 changes: 2 additions & 1 deletion packages/interactive_media_ads/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ Future<void> _requestAds(AdDisplayContainer container) {

manager.setAdsManagerDelegate(AdsManagerDelegate(
onAdEvent: (AdEvent event) {
debugPrint('OnAdEvent: ${event.type}');
debugPrint('OnAdEvent: ${event.type} => ${event.adData}');
switch (event.type) {
case AdEventType.loaded:
manager.start();
Expand All @@ -216,6 +216,7 @@ Future<void> _requestAds(AdDisplayContainer container) {
_adsManager = null;
case AdEventType.clicked:
case AdEventType.complete:
case _:
}
},
onAdErrorEvent: (AdErrorEvent event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ class AdEventProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) :
else -> AdEventType.UNKNOWN
}
}

override fun adData(pigeon_instance: AdEvent): Map<String, String>? {
return pigeon_instance.adData
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class AdsRequestProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) :
*
* This must match the version in pubspec.yaml.
*/
const val pluginVersion = "0.1.1+1"
const val pluginVersion = "0.1.2"
}

override fun setAdTagUrl(pigeon_instance: AdsRequest, adTagUrl: String) {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class InteractiveMediaAdsPlugin : FlutterPlugin, ActivityAware {
}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
registrar.ignoreCallsToDart = true
registrar.tearDown()
registrar.instanceManager.clear()
}
Expand All @@ -52,8 +53,9 @@ class InteractiveMediaAdsPlugin : FlutterPlugin, ActivityAware {
}
}

internal class FlutterViewFactory(private val instanceManager: PigeonInstanceManager) :
PlatformViewFactory(StandardMessageCodec.INSTANCE) {
internal class FlutterViewFactory(
private val instanceManager: InteractiveMediaAdsLibraryPigeonInstanceManager
) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {

override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
val identifier =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import android.os.Looper
import io.flutter.plugin.common.BinaryMessenger

/**
* Implementation of [PigeonProxyApiRegistrar] that provides each ProxyApi implementation and any
* additional resources needed by an implementation.
* Implementation of [InteractiveMediaAdsLibraryPigeonProxyApiRegistrar] that provides each ProxyApi
* implementation and any additional resources needed by an implementation.
*/
open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Context) :
PigeonProxyApiRegistrar(binaryMessenger) {
InteractiveMediaAdsLibraryPigeonProxyApiRegistrar(binaryMessenger) {

// Added to be overriden for tests. The test implementation calls `callback` immediately, instead
// of waiting for the main thread to run it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,14 @@ class AdEventProxyApiTest {

assertEquals(AdEventType.PAUSED, api.type(instance))
}

@Test
fun adData() {
val api = TestProxyApiRegistrar().getPigeonApiAdEvent()

val instance = Mockito.mock<AdEvent>()
whenever(instance.adData).thenReturn(mapOf("a" to "b", "c" to "d"))

assertEquals(mapOf("a" to "b", "c" to "d"), api.adData(instance))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ final class AdEventTests: XCTestCase {

XCTAssertEqual(value, "message")
}

func testAdData() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiIMAAdEvent(registrar)

let instance = TestAdEvent.customInit()

let value = try? api.pigeonDelegate.adData(pigeonApi: api, pigeonInstance: instance)

XCTAssertEqual(value as! [String: String], ["my": "string"])
}
}

class TestAdEvent: IMAAdEvent {
Expand All @@ -47,4 +58,8 @@ class TestAdEvent: IMAAdEvent {
override var typeString: String {
return "message"
}

override var adData: [String: Any]? {
return ["my": "string"]
}
}
3 changes: 2 additions & 1 deletion packages/interactive_media_ads/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class _AdExampleWidgetState extends State<AdExampleWidget> {

manager.setAdsManagerDelegate(AdsManagerDelegate(
onAdEvent: (AdEvent event) {
debugPrint('OnAdEvent: ${event.type}');
debugPrint('OnAdEvent: ${event.type} => ${event.adData}');
switch (event.type) {
case AdEventType.loaded:
manager.start();
Expand All @@ -105,6 +105,7 @@ class _AdExampleWidgetState extends State<AdExampleWidget> {
_adsManager = null;
case AdEventType.clicked:
case AdEventType.complete:
case _:
}
},
onAdErrorEvent: (AdErrorEvent event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import GoogleInteractiveMediaAds
/// 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 adData(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> [String: Any]? {
return pigeonInstance.adData
}

func type(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> AdEventType {
switch pigeonInstance.type {
case .AD_BREAK_READY:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.1.1+1"
static let pluginVersion = "0.1.2"

func pigeonDefaultConstructor(
pigeonApi: PigeonApiIMAAdsRequest, adTagUrl: String, adDisplayContainer: IMAAdDisplayContainer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2678,6 +2678,8 @@ protocol PigeonApiDelegateIMAAdEvent {
func type(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> AdEventType
/// Stringified type of the event.
func typeString(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> String
/// Extra data about the ad.
func adData(pigeonApi: PigeonApiIMAAdEvent, pigeonInstance: IMAAdEvent) throws -> [String: Any]?
}

protocol PigeonApiProtocolIMAAdEvent {
Expand Down Expand Up @@ -2719,13 +2721,15 @@ final class PigeonApiIMAAdEvent: PigeonApiProtocolIMAAdEvent {
let typeArg = try! pigeonDelegate.type(pigeonApi: self, pigeonInstance: pigeonInstance)
let typeStringArg = try! pigeonDelegate.typeString(
pigeonApi: self, pigeonInstance: pigeonInstance)
let adDataArg = try! pigeonDelegate.adData(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
channel.sendMessage([pigeonIdentifierArg, typeArg, typeStringArg, adDataArg] as [Any?]) {
response in
guard let listResponse = response as? [Any?] else {
completion(.failure(createConnectionError(withChannelName: channelName)))
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ class AndroidAdsManager extends PlatformAdsManager {
weakThis.target?._manager.addAdEventListener(
proxy.newAdEventListener(
onAdEvent: (_, ima.AdEvent event) {
late final AdEventType? eventType = toInterfaceEventType(event.type);
if (eventType == null) {
return;
}

weakThis.target?._managerDelegate?.params.onAdEvent
?.call(AdEvent(type: eventType));
weakThis.target?._managerDelegate?.params.onAdEvent?.call(
AdEvent(
type: toInterfaceEventType(event.type),
adData:
event.adData?.cast<String, String>() ?? <String, String>{},
),
);
},
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ AdErrorType toInterfaceErrorType(ima.AdErrorType type) {
/// 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) {
AdEventType toInterfaceEventType(ima.AdEventType type) {
return switch (type) {
ima.AdEventType.allAdsCompleted => AdEventType.allAdsCompleted,
ima.AdEventType.completed => AdEventType.complete,
Expand All @@ -26,7 +26,29 @@ AdEventType? toInterfaceEventType(ima.AdEventType type) {
AdEventType.contentResumeRequested,
ima.AdEventType.loaded => AdEventType.loaded,
ima.AdEventType.clicked => AdEventType.clicked,
_ => null,
ima.AdEventType.adBreakEnded => AdEventType.adBreakEnded,
ima.AdEventType.adBreakFetchError => AdEventType.adBreakFetchError,
ima.AdEventType.adBreakReady => AdEventType.adBreakReady,
ima.AdEventType.adBreakStarted => AdEventType.adBreakStarted,
ima.AdEventType.adBuffering => AdEventType.adBuffering,
ima.AdEventType.adPeriodEnded => AdEventType.adPeriodEnded,
ima.AdEventType.adPeriodStarted => AdEventType.adPeriodStarted,
ima.AdEventType.adProgress => AdEventType.adProgress,
ima.AdEventType.cuepointsChanged => AdEventType.cuepointsChanged,
ima.AdEventType.firstQuartile => AdEventType.firstQuartile,
ima.AdEventType.iconFallbackImageClosed =>
AdEventType.iconFallbackImageClosed,
ima.AdEventType.iconTapped => AdEventType.iconTapped,
ima.AdEventType.log => AdEventType.log,
ima.AdEventType.midpoint => AdEventType.midpoint,
ima.AdEventType.paused => AdEventType.paused,
ima.AdEventType.resumed => AdEventType.resumed,
ima.AdEventType.skippableStateChanged => AdEventType.skippableStateChanged,
ima.AdEventType.skipped => AdEventType.skipped,
ima.AdEventType.started => AdEventType.started,
ima.AdEventType.tapped => AdEventType.tapped,
ima.AdEventType.thirdQuartile => AdEventType.thirdQuartile,
ima.AdEventType.unknown => AdEventType.unknown,
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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 (v19.1.0), do not edit directly.
// 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

Expand Down Expand Up @@ -423,7 +423,7 @@ class _PigeonInstanceManagerApi {
}
}

class _PigeonProxyApiBaseCodec extends StandardMessageCodec {
class _PigeonProxyApiBaseCodec extends _PigeonCodec {
const _PigeonProxyApiBaseCodec(this.instanceManager);
final PigeonInstanceManager instanceManager;
@override
Expand Down Expand Up @@ -637,6 +637,42 @@ enum AdEventType {
unknown,
}

class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is AdErrorCode) {
buffer.putUint8(129);
writeValue(buffer, value.index);
} else if (value is AdErrorType) {
buffer.putUint8(130);
writeValue(buffer, value.index);
} else if (value is AdEventType) {
buffer.putUint8(131);
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 : AdErrorCode.values[value];
case 130:
final int? value = readValue(buffer) as int?;
return value == null ? null : AdErrorType.values[value];
case 131:
final int? value = readValue(buffer) as int?;
return value == null ? null : AdEventType.values[value];
default:
return super.readValueOfType(type, buffer);
}
}
}

/// A base class for more specialized container interfaces.
///
/// See https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/api/reference/com/google/ads/interactivemedia/v3/api/BaseDisplayContainer.html.
Expand Down Expand Up @@ -1158,15 +1194,13 @@ class AdError extends PigeonProxyApiBaseClass {
final int? arg_pigeon_instanceIdentifier = (args[0] as int?);
assert(arg_pigeon_instanceIdentifier != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdError.pigeon_newInstance was null, expected non-null int.');
final AdErrorCode? arg_errorCode =
args[1] == null ? null : AdErrorCode.values[args[1]! as int];
final AdErrorCode? arg_errorCode = (args[1] as AdErrorCode?);
assert(arg_errorCode != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdError.pigeon_newInstance was null, expected non-null AdErrorCode.');
final int? arg_errorCodeNumber = (args[2] as int?);
assert(arg_errorCodeNumber != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdError.pigeon_newInstance was null, expected non-null int.');
final AdErrorType? arg_errorType =
args[3] == null ? null : AdErrorType.values[args[3]! as int];
final AdErrorType? arg_errorType = (args[3] as AdErrorType?);
assert(arg_errorType != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdError.pigeon_newInstance was null, expected non-null AdErrorType.');
final String? arg_message = (args[4] as String?);
Expand Down Expand Up @@ -1776,16 +1810,23 @@ class AdEvent extends PigeonProxyApiBaseClass {
super.pigeon_binaryMessenger,
super.pigeon_instanceManager,
required this.type,
this.adData,
});

/// The type of event that occurred.
final AdEventType type;

/// A map containing any extra ad data for the event, if needed.
final Map<String?, String?>? adData;

static void pigeon_setUpMessageHandlers({
bool pigeon_clearHandlers = false,
BinaryMessenger? pigeon_binaryMessenger,
PigeonInstanceManager? pigeon_instanceManager,
AdEvent Function(AdEventType type)? pigeon_newInstance,
AdEvent Function(
AdEventType type,
Map<String?, String?>? adData,
)? pigeon_newInstance,
}) {
final _PigeonProxyApiBaseCodec pigeonChannelCodec =
_PigeonProxyApiBaseCodec(
Expand All @@ -1807,18 +1848,20 @@ class AdEvent extends PigeonProxyApiBaseClass {
final int? arg_pigeon_instanceIdentifier = (args[0] as int?);
assert(arg_pigeon_instanceIdentifier != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdEvent.pigeon_newInstance was null, expected non-null int.');
final AdEventType? arg_type =
args[1] == null ? null : AdEventType.values[args[1]! as int];
final AdEventType? arg_type = (args[1] as AdEventType?);
assert(arg_type != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdEvent.pigeon_newInstance was null, expected non-null AdEventType.');
final Map<String?, String?>? arg_adData =
(args[2] as Map<Object?, Object?>?)?.cast<String?, String?>();
try {
(pigeon_instanceManager ?? PigeonInstanceManager.instance)
.addHostCreatedInstance(
pigeon_newInstance?.call(arg_type!) ??
pigeon_newInstance?.call(arg_type!, arg_adData) ??
AdEvent.pigeon_detached(
pigeon_binaryMessenger: pigeon_binaryMessenger,
pigeon_instanceManager: pigeon_instanceManager,
type: arg_type!,
adData: arg_adData,
),
arg_pigeon_instanceIdentifier!,
);
Expand All @@ -1840,6 +1883,7 @@ class AdEvent extends PigeonProxyApiBaseClass {
pigeon_binaryMessenger: pigeon_binaryMessenger,
pigeon_instanceManager: pigeon_instanceManager,
type: type,
adData: adData,
);
}
}
Expand Down
Loading