Skip to content
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
5 changes: 5 additions & 0 deletions packages/interactive_media_ads/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.2.7

* Adds support to retrieve content time offsets at which ad breaks are scheduled. See
`AdsManager.adCuePoints`

## 0.2.6+7

* Updates Android `PlatformAdDisplayContainer` implementation to support preloading ads.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AdsManagerProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) :
pigeon_instance.start()
}

override fun getAdCuePoints(pigeon_instance: AdsManager): List<Double> {
override fun adCuePoints(pigeon_instance: AdsManager): List<Double> {
return pigeon_instance.adCuePoints.map { it.toDouble() }
}

Expand Down
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.2.6+7"
const val pluginVersion = "0.2.7"
}

override fun setAdTagUrl(pigeon_instance: AdsRequest, adTagUrl: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2074,6 +2074,15 @@ abstract class PigeonApiContentProgressProvider(
abstract class PigeonApiAdsManager(
open val pigeonRegistrar: InteractiveMediaAdsLibraryPigeonProxyApiRegistrar
) {
/**
* List of content time offsets in seconds at which ad breaks are scheduled.
*
* The list will be empty if no ad breaks are scheduled.
*/
abstract fun adCuePoints(
pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsManager
): List<Double>

/** Discards current ad break and resumes content. */
abstract fun discardAdBreak(pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsManager)

Expand All @@ -2083,15 +2092,6 @@ abstract class PigeonApiAdsManager(
/** Starts playing the ads. */
abstract fun start(pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsManager)

/**
* List of content time offsets in seconds at which ad breaks are scheduled.
*
* The list will be empty if no ad breaks are scheduled.
*/
abstract fun getAdCuePoints(
pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsManager
): List<Double>

/** Resumes the current ad. */
abstract fun resume(pigeon_instance: com.google.ads.interactivemedia.v3.api.AdsManager)

Expand Down Expand Up @@ -2171,28 +2171,6 @@ abstract class PigeonApiAdsManager(
channel.setMessageHandler(null)
}
}
run {
val channel =
BasicMessageChannel<Any?>(
binaryMessenger,
"dev.flutter.pigeon.interactive_media_ads.AdsManager.getAdCuePoints",
codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val pigeon_instanceArg = args[0] as com.google.ads.interactivemedia.v3.api.AdsManager
val wrapped: List<Any?> =
try {
listOf(api.getAdCuePoints(pigeon_instanceArg))
} catch (exception: Throwable) {
InteractiveMediaAdsLibraryPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel =
BasicMessageChannel<Any?>(
Expand Down Expand Up @@ -2255,11 +2233,12 @@ abstract class PigeonApiAdsManager(
} else {
val pigeon_identifierArg =
pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg)
val adCuePointsArg = adCuePoints(pigeon_instanceArg)
val binaryMessenger = pigeonRegistrar.binaryMessenger
val codec = pigeonRegistrar.codec
val channelName = "dev.flutter.pigeon.interactive_media_ads.AdsManager.pigeon_newInstance"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(pigeon_identifierArg)) {
channel.send(listOf(pigeon_identifierArg, adCuePointsArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ class AdsManagerProxyApiTest {
}

@Test
fun getAdCuePoints() {
fun adCuePoints() {
val api = TestProxyApiRegistrar().getPigeonApiAdsManager()

val instance = mock<AdsManager>()
val value = listOf(1.0)
whenever(instance.adCuePoints).thenReturn(listOf(1.0f))

assertEquals(value, api.getAdCuePoints(instance))
assertEquals(value, api.adCuePoints(instance))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ final class AdsManagerTests: XCTestCase {

XCTAssertTrue(instance.destroyCalled)
}

func testAdCuePoints() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiIMAAdsManager(registrar)

let instance = TestAdsManager.customInit()

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

XCTAssertEqual(value, [2.2, 3.3])
}
}

class TestAdsManager: IMAAdsManager {
Expand Down Expand Up @@ -146,4 +157,8 @@ class TestAdsManager: IMAAdsManager {
override func destroy() {
destroyCalled = true
}

override var adCuePoints: [Any] {
return [2.2, 3.3]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class _VideoAdExampleScreenState extends State<VideoAdExampleScreen>
_adsLoader = AdsLoader(
container: container,
onAdsLoaded: (OnAdsLoadedData data) {
debugPrint('OnAdsLoaded: (cuePoints: ${data.manager.adCuePoints})');
final AdsManager manager = data.manager;
_adsManager = data.manager;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,12 @@ class AdsManagerProxyAPIDelegate: PigeonApiDelegateIMAAdsManager {
func destroy(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws {
pigeonInstance.destroy()
}

func adCuePoints(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws
-> [Double]
{
return pigeonInstance.adCuePoints.map { cuePoint -> Double in
return (cuePoint as! NSNumber).doubleValue
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an easy way for us to file an issue about the fact that this array should be an NSArray<NSNumber*> instead of an NSArray?

(Not to block this PR, of course, it's just weird that this is handled via documentation rather than the actual type system.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
}
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.2.6+7"
static let pluginVersion = "0.2.7"

func pigeonDefaultConstructor(
pigeonApi: PigeonApiIMAAdsRequest, adTagUrl: String, adDisplayContainer: IMAAdDisplayContainer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3157,6 +3157,12 @@ final class PigeonApiIMAAdError: PigeonApiProtocolIMAAdError {
}
}
protocol PigeonApiDelegateIMAAdsManager {
/// List of content time offsets at which ad breaks are scheduled.
///
/// List of double values in seconds. Empty list for single ads or if no ad
/// breaks are scheduled.
func adCuePoints(pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager) throws
-> [Double]
/// The `IMAAdsManagerDelegate` to notify with events during ad playback.
func setDelegate(
pigeonApi: PigeonApiIMAAdsManager, pigeonInstance: IMAAdsManager,
Expand Down Expand Up @@ -3365,13 +3371,15 @@ final class PigeonApiIMAAdsManager: PigeonApiProtocolIMAAdsManager {
} else {
let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(
pigeonInstance as AnyObject)
let adCuePointsArg = try! pigeonDelegate.adCuePoints(
pigeonApi: self, pigeonInstance: pigeonInstance)
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
channel.sendMessage([pigeonIdentifierArg, adCuePointsArg] as [Any?]) { response in
guard let listResponse = response as? [Any?] else {
completion(.failure(createConnectionError(withChannelName: channelName)))
return
Expand Down
5 changes: 5 additions & 0 deletions packages/interactive_media_ads/lib/src/ads_loader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ class AdsManager {
/// Implementation of [PlatformAdsManager] for the current platform.
final PlatformAdsManager platform;

/// List of content time offsets at which ad breaks are scheduled.
///
/// The list will be empty for single ads or if no ad breaks are scheduled.
List<Duration> get adCuePoints => platform.adCuePoints;

/// Initializes the ad experience using default rendering settings.
Future<void> init({AdsRenderingSettings? settings}) {
return platform.init(settings: settings?.platform);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ base class AndroidAdDisplayContainer extends PlatformAdDisplayContainer {
}

// Resets the state to before an ad is loaded and releases references to all
// ads and allbacks.
// ads and callbacks.
void _release() {
_resetStateForNextAd();
_loadedAdMediaInfoQueue.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@ class AndroidAdsManager extends PlatformAdsManager {
@internal
AndroidAdsManager(ima.AdsManager manager, {InteractiveMediaAdsProxy? proxy})
: _manager = manager,
_proxy = proxy ?? const InteractiveMediaAdsProxy();
_proxy = proxy ?? const InteractiveMediaAdsProxy(),
super(
adCuePoints: List<Duration>.unmodifiable(
manager.adCuePoints.map((double seconds) {
return Duration(
milliseconds: (seconds * Duration.millisecondsPerSecond).round(),
);
}),
),
);

final ima.AdsManager _manager;
final InteractiveMediaAdsProxy _proxy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2250,16 +2250,22 @@ class AdsManager extends BaseManager {
AdsManager.pigeon_detached({
super.pigeon_binaryMessenger,
super.pigeon_instanceManager,
required this.adCuePoints,
}) : super.pigeon_detached();

late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAdsManager =
_PigeonInternalProxyApiBaseCodec(pigeon_instanceManager);

/// List of content time offsets in seconds at which ad breaks are scheduled.
///
/// The list will be empty if no ad breaks are scheduled.
final List<double> adCuePoints;

static void pigeon_setUpMessageHandlers({
bool pigeon_clearHandlers = false,
BinaryMessenger? pigeon_binaryMessenger,
PigeonInstanceManager? pigeon_instanceManager,
AdsManager Function()? pigeon_newInstance,
AdsManager Function(List<double> adCuePoints)? pigeon_newInstance,
}) {
final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec =
_PigeonInternalProxyApiBaseCodec(
Expand Down Expand Up @@ -2287,13 +2293,20 @@ class AdsManager extends BaseManager {
arg_pigeon_instanceIdentifier != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdsManager.pigeon_newInstance was null, expected non-null int.',
);
final List<double>? arg_adCuePoints =
(args[1] as List<Object?>?)?.cast<double>();
assert(
arg_adCuePoints != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.AdsManager.pigeon_newInstance was null, expected non-null List<double>.',
);
try {
(pigeon_instanceManager ?? PigeonInstanceManager.instance)
.addHostCreatedInstance(
pigeon_newInstance?.call() ??
pigeon_newInstance?.call(arg_adCuePoints!) ??
AdsManager.pigeon_detached(
pigeon_binaryMessenger: pigeon_binaryMessenger,
pigeon_instanceManager: pigeon_instanceManager,
adCuePoints: arg_adCuePoints!,
),
arg_pigeon_instanceIdentifier!,
);
Expand Down Expand Up @@ -2403,44 +2416,6 @@ class AdsManager extends BaseManager {
}
}

/// List of content time offsets in seconds at which ad breaks are scheduled.
///
/// The list will be empty if no ad breaks are scheduled.
Future<List<double>> getAdCuePoints() async {
final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec =
_pigeonVar_codecAdsManager;
final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger;
const String pigeonVar_channelName =
'dev.flutter.pigeon.interactive_media_ads.AdsManager.getAdCuePoints';
final BasicMessageChannel<Object?> pigeonVar_channel =
BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
<Object?>[this],
);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<double>();
}
}

/// Resumes the current ad.
Future<void> resume() async {
final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec =
Expand Down Expand Up @@ -2511,6 +2486,7 @@ class AdsManager extends BaseManager {
return AdsManager.pigeon_detached(
pigeon_binaryMessenger: pigeon_binaryMessenger,
pigeon_instanceManager: pigeon_instanceManager,
adCuePoints: adCuePoints,
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3855,16 +3855,23 @@ class IMAAdsManager extends NSObject {
IMAAdsManager.pigeon_detached({
super.pigeon_binaryMessenger,
super.pigeon_instanceManager,
required this.adCuePoints,
}) : super.pigeon_detached();

late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecIMAAdsManager =
_PigeonInternalProxyApiBaseCodec(pigeon_instanceManager);

/// List of content time offsets at which ad breaks are scheduled.
///
/// List of double values in seconds. Empty list for single ads or if no ad
/// breaks are scheduled.
final List<double> adCuePoints;

static void pigeon_setUpMessageHandlers({
bool pigeon_clearHandlers = false,
BinaryMessenger? pigeon_binaryMessenger,
PigeonInstanceManager? pigeon_instanceManager,
IMAAdsManager Function()? pigeon_newInstance,
IMAAdsManager Function(List<double> adCuePoints)? pigeon_newInstance,
}) {
final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec =
_PigeonInternalProxyApiBaseCodec(
Expand Down Expand Up @@ -3892,13 +3899,20 @@ class IMAAdsManager extends NSObject {
arg_pigeon_instanceIdentifier != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pigeon_newInstance was null, expected non-null int.',
);
final List<double>? arg_adCuePoints =
(args[1] as List<Object?>?)?.cast<double>();
assert(
arg_adCuePoints != null,
'Argument for dev.flutter.pigeon.interactive_media_ads.IMAAdsManager.pigeon_newInstance was null, expected non-null List<double>.',
);
try {
(pigeon_instanceManager ?? PigeonInstanceManager.instance)
.addHostCreatedInstance(
pigeon_newInstance?.call() ??
pigeon_newInstance?.call(arg_adCuePoints!) ??
IMAAdsManager.pigeon_detached(
pigeon_binaryMessenger: pigeon_binaryMessenger,
pigeon_instanceManager: pigeon_instanceManager,
adCuePoints: arg_adCuePoints!,
),
arg_pigeon_instanceIdentifier!,
);
Expand Down Expand Up @@ -4169,6 +4183,7 @@ class IMAAdsManager extends NSObject {
return IMAAdsManager.pigeon_detached(
pigeon_binaryMessenger: pigeon_binaryMessenger,
pigeon_instanceManager: pigeon_instanceManager,
adCuePoints: adCuePoints,
);
}
}
Expand Down
Loading