Skip to content
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

[interactive_media_ads] Adds initial iOS implementation #7063

Open
wants to merge 72 commits into
base: main
Choose a base branch
from

Conversation

bparrishMines
Copy link
Contributor

@bparrishMines bparrishMines commented Jul 5, 2024

iOS implementation for flutter/flutter#134228

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@bparrishMines
Copy link
Contributor Author

@stuartmorgan @jmagman I'm getting an error when importing the IMA SDK on iOS. How should I handle importing the SDK so the that it works with apps using and not using Swift Package Manager. I currently have it included in the podspec and Package.swift. Should I only have it in one or both?

Also here are the iOS docs for importing the IMA SDK for reference: https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side

The error:

Building for: iOS


BUILDING interactive_media_ads/example for iOS
Running command: "flutter build ios --no-codesign" in /Volumes/Work/s/w/ir/x/w/packages/packages/interactive_media_ads/example
Warning: Building for device with codesigning disabled. You will have to manually codesign before deploying to device.
Building dev.flutter.packages.interactiveMediaAdsExample for device (ios-release)...
Adding Swift Package Manager integration...                        11.8s
An error occurred when adding Swift Package Manager integration:
  Error: Unable to get Xcode project information:
 2024-07-05 12:59:11.342 xcodebuild[48157:453818] Writing error result bundle to /var/folders/cs/cqkgmb4n27n6k5bhvx0_34d00000gp/T/ResultBundle_2024-05-07_12-59-0011.xcresult
xcodebuild: error: Could not resolve package dependencies:
  unknown dependency 'GoogleInteractiveMediaAds' in target 'interactive_media_ads'; valid dependencies are: 'swift-package-manager-google-interactive-media-ads-ios'
  unknown dependency 'GoogleInteractiveMediaAds' in target 'interactive_media_ads'; valid dependencies are: 'swift-package-manager-google-interactive-media-ads-ios'
  exhausted attempts to resolve the dependencies graph, with 'interactive_media_ads fileSystem /Volumes/Work/s/w/ir/x/w/packages/packages/interactive_media_ads/ios/interactive_media_ads' unresolved.



Swift Package Manager is currently an experimental feature, please file a bug at
  https://github.com/flutter/flutter/issues/new?template=1_activation.yml 
Consider including a copy of the following files in your bug report:
  ios/Runner.xcodeproj/project.pbxproj
  ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (or the scheme for the flavor used)

To avoid this failure, disable Flutter Swift Package Manager integration for the project
by adding the following in the project's pubspec.yaml under the "flutter" section:
  "disable-swift-package-manager: true"
Alternatively, disable Flutter Swift Package Manager integration globally with the
following command:
  "flutter config --no-enable-swift-package-manager"


[packages/interactive_media_ads completed in 0m 30s]

dependencies: [
.package(
url: "https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios",
from: "3.23.0")
Copy link
Member

Choose a reason for hiding this comment

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

Do we want upToNextMajor instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does the iOS team already have policy on this? On Android, I think we only use pinned versions because gradle lacked the equivalent of a Podfile.lock or pubspec.lock. Should we be consistent with Android or should iOS implementations generally use upToNextMajor if possible?

cc @stuartmorgan

Copy link
Contributor

Choose a reason for hiding this comment

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

Pinning is sort of a myth on Android because of optimistic upgrades. For CocoaPods we've generally allowed major version ranges for dependencies with an authoritative/trusted source (e.g., the vendor of the thing the plugin is wrapping).

@jmagman
Copy link
Member

jmagman commented Jul 9, 2024

I'm getting an error when importing the IMA SDK on iOS. How should I handle importing the SDK so the that it works with apps using and not using Swift Package Manager.

I added a comment to Package.swift, does that fix it?

cc @loic-sharma

@bparrishMines bparrishMines marked this pull request as ready for review July 10, 2024 18:44
@bparrishMines bparrishMines changed the title Ima ios [interactive_media_ads] Adds initial iOS implementation Jul 10, 2024
@@ -37,6 37,7 @@ class AdDisplayContainer extends StatelessWidget {
AdDisplayContainer({
Key? key,
required void Function(AdDisplayContainer container) onContainerAdded,
TextDirection layoutDirection = TextDirection.ltr,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This value is required for UIKitView, so I added to the interface.

class TestBinaryMessenger<T>: NSObject, FlutterBinaryMessenger {
let codec: FlutterMessageCodec
var result: T?
private(set) var handlers: [String: FlutterBinaryMessageHandler] = [:]
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we ever actually need the functionality provided by all these ivars? I would expect that any real test would use a fake Pigeon API instance, not a fake messenger, since tests shouldn't be relying on Pigeon internals, so this functionality seems like a potential footgun.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I think I originally was planning on using the handles, but ending up not. I removed all this code.

contentPlayhead: IMAContentPlayhead?
) throws -> IMAAdsRequest {
let adTagWithRequestAgent =
"\(adTagUrl)&request_agent=Flutter-IMA-\(AdsRequestProxyAPIDelegate.pluginVersion)"
Copy link
Contributor

Choose a reason for hiding this comment

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

What guarantees that this concatenation is valid? E.g., if adTagUrl doesn't have a ?, or has a #, this wouldn't work.


/// Adds a method to convert native AdErrorType to platform interface
/// AdErrorType.
extension NativeAdErrorTypeConverter on ima.AdErrorType {
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did this for Android as well. I'll update that as well

// A delay is added since this callback only indicates when the View is
// created, but not when it has been added to the native View hierarchy.
// See https://github.com/flutter/flutter/issues/150802
await Future<void>.delayed(const Duration(seconds: 1));
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we think this is going to always be enough time?

final IOSAdsManagerDelegate adsManagerDelegate = IOSAdsManagerDelegate(
IOSAdsManagerDelegateCreationParams(
onAdEvent: expectAsync1((AdEvent event) {
expect(event.type, AdEventType.allAdsCompleted);
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like these tests only expect within the callback, in which case failing to call the callback wouldn't fail the test. If that's the case, these should all have a completer declared up front, and completed with the expectation, so the end of the test can also assert that the completer completes (and thus the test did call the callback).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants