Skip to content

Commit 7c95aa6

Browse files
[interactive_media_ads] Adds a contribution doc (flutter#7460)
1 parent ee0ad75 commit 7c95aa6

File tree

6 files changed

+252
-5
lines changed

6 files changed

+252
-5
lines changed

packages/interactive_media_ads/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.1.2+3
2+
3+
* Adds a contribution guide. See `CONTRIBUTING.md`.
4+
15
## 0.1.2+2
26

37
* Removes dependency on org.jetbrains.kotlin:kotlin-bom.
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# Contributing to `interactive_media_ads`
2+
3+
Please start by taking a look at the general guide to contributing to the `flutter/packages` repo:
4+
https://github.com/flutter/packages/blob/main/CONTRIBUTING.md
5+
6+
## Package Structure
7+
8+
The structure of this plugin is similar to a [federated plugin](https://docs.flutter.dev/packages-and-plugins/developing-packages#federated-plugins),
9+
except the code for each package (platform interface, platform implementations, and app-facing
10+
interface) are maintained in this single plugin. The sections below will provide an overview of how
11+
this plugin implements each portion.
12+
13+
If you are familiar with [changing federated plugin](https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins)
14+
in the `flutter/packages` repo, the process is similar except that all changes are made in this
15+
plugin. Therefore, it is not necessary to run the script that makes dependencies path based.
16+
17+
### Quick Overview
18+
19+
This plugin uses the native [IMA SDKs] for Android and iOS. The API for the SDK of both platforms
20+
are relatively similar, so this plugin attempts to maintain an interface that is similar to the
21+
native SDKs.
22+
23+
The app-facing interface uses delegation to interact with the underlying platform implementations.
24+
Therefore, the platform interface is similar to the app-facing interface with the differences being
25+
explained in the sections below. Many app-facing interface classes will contain a `platform` field
26+
that is used to forward handling to the platform implementation:
27+
28+
```dart
29+
// App-facing class used by apps
30+
class AdsLoader {
31+
AdsLoader.fromPlatform(this.platform);
32+
33+
final PlatformAdsLoader platform;
34+
35+
Future<void> requestAds(AdsRequest request) {
36+
return platform.requestAds(request);
37+
}
38+
}
39+
40+
// Platform interface class implemented by each platform
41+
abstract base class PlatformAdsLoader {
42+
Future<void> requestAds(AdsRequest request);
43+
}
44+
```
45+
46+
The `platform` variable should also be used to provide access to platform specific methods or
47+
platform specific creation parameters:
48+
49+
```dart
50+
final AdsLoader loader = AdsLoader();
51+
(loader.platform as AndroidAdsLoader).callAndroidSpecificMethod();
52+
```
53+
54+
The other classes/enums included in the app-facing interface are typically exported from the
55+
platform interface. A data class being a good example of a class that is exported.
56+
57+
### Platform Interface
58+
59+
Code location: `lib/src/platform_interface/`.
60+
61+
This declares an interface that each platform must implement to be supported by the app-facing
62+
interface.
63+
64+
The design of the platform interface should prioritize:
65+
* Minimizing the chances of needing a breaking change when adding a new feature.
66+
* Allowing platform implementations to easily add platform specific features.
67+
* Being straight-forward to write unit tests.
68+
69+
Each platform creates a subclass of the central [InteractiveMediaAdsPlatform](lib/src/platform_interface/interactive_media_ads_platform.dart)
70+
class. A platform implementation is set by setting `InteractiveMediaAdsPlatform.instance` to an
71+
instance of a platform implementation of `InteractiveMediaAdsPlatform`.
72+
73+
### Platform Interface Class Types
74+
75+
Below are some of the types of classes in the interface.
76+
77+
#### Delegate Platform Class
78+
79+
These are classes where the app-facing interface needs to delegate handling to the platform
80+
implementation. These classes are typically prefixed with `Platform`.
81+
82+
If the corresponding app-facing class can be instantiated by the app (e.g. [AdsLoader]),
83+
the `InteractiveMediaAdsPlatform.instance` field should be used in a factory to instantiate the
84+
correct platform implementation. See [PlatformAdsLoader] as an example. This class should should
85+
also take a creation params class as the only constructor parameter.
86+
87+
If the corresponding app-facing class can't be instantiated by the app (e.g. `AdsManager`), the
88+
class should only have a single protected constructor. See [PlatformAdsManager].
89+
90+
If the corresponding app-facing class needs to be a `Widget` (e.g. [AdDisplayContainer]), this
91+
should follow the same pattern as being instantiable by the app except it should contain a single
92+
method: `Widget build(BuildContext)`. See [PlatformAdDisplayContainer].
93+
94+
**Note**
95+
96+
Every method should contain no more than one parameter. This allows the platform interface and
97+
platform implementations to add new features without requiring a breaking change.
98+
99+
#### Data Classes
100+
101+
These classes contain only fields and no methods. Each data class should be made `@immutable`.
102+
103+
### Platform Implementations
104+
105+
Code location:
106+
* Android: `lib/src/android/`
107+
* iOS: `lib/src/ios/`
108+
109+
The platform implementations create a subclass of `InteractiveMediaAdsPlatform` and implement the
110+
platform classes that are returned by this.
111+
112+
#### SDK Wrappers
113+
114+
The platform implementations use Dart wrappers of their native SDKs. The SDKs are wrapped using
115+
using the `pigeon` package. However, the code that handles generating the wrappers are still in the
116+
process of review, so this plugin must use a git dependency in the pubspec.
117+
118+
The wrappers for the SDK of each platform can be updated and modified by changing the pigeon files:
119+
120+
* Android: `pigeons/interactive_media_ads_android.dart`
121+
* iOS: `pigeons/interactive_media_ads_ios.dart`
122+
123+
The generated files are located:
124+
* Android:
125+
* `lib/src/android/interactive_media_ads.g.dart`
126+
* `android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/InteractiveMediaAdsLibrary.g.kt`
127+
* iOS
128+
* `lib/src/ios/interactive_media_ads.g.dart`
129+
* `ios/interactive_media_ads/Sources/interactive_media_ads/InteractiveMediaAdsLibrary.g.swift`
130+
131+
To update a wrapper for a platform, follow the steps:
132+
133+
##### 1. Ensure the project has been built at least once
134+
135+
* Android: Run `flutter build apk --debug` in `example/`.
136+
* iOS: Run `flutter build ios --simulator` in `example/`
137+
138+
##### 2. Add the correct `pigeon` package to `dev_dependencies` in the `pubspec.yaml` and run `pub upgrade`
139+
140+
Android:
141+
142+
```yaml
143+
pigeon:
144+
git:
145+
url: [email protected]:bparrishMines/packages.git
146+
ref: pigeon_kotlin_split
147+
path: packages/pigeon
148+
```
149+
150+
iOS:
151+
152+
```yaml
153+
pigeon:
154+
git:
155+
url: [email protected]:bparrishMines/packages.git
156+
ref: pigeon_wrapper_swift
157+
path: packages/pigeon
158+
```
159+
160+
##### 3. Uncomment the multiline comments in the pigeon file
161+
162+
* Android: `pigeons/interactive_media_ads_android.dart`
163+
* iOS: `pigeons/interactive_media_ads_ios.dart`
164+
165+
##### 4. Make changes that match the native SDK
166+
167+
* [Android SDK]
168+
* [iOS SDK]
169+
170+
##### 5. Run the code generator from the terminal
171+
172+
* Android: `dart run pigeon --input pigeons/interactive_media_ads_android.dart`
173+
* iOS: `dart run pigeon --input pigeons/interactive_media_ads_ios.dart`
174+
175+
##### 6. Update the generated APIs in native code
176+
177+
Running the `flutter build` step from step 1 again should provide build errors and indicate what
178+
needs to be done. Alternatively, it can be easier to update native code with the platform's specific
179+
IDE:
180+
181+
* Android: Open `example/android/` in a separate Android Studio project.
182+
* iOS: Open `example/ios/` in Xcode.
183+
184+
##### 7. Write API tests
185+
186+
Assuming a non-static method or constructor was added to the native wrapper, a native test will need
187+
to be added.
188+
189+
* Android native tests location: `android/src/test/kotlin/dev/flutter/packages/interactive_media_ads/`
190+
* iOS native tests location `example/ios/RunnerTests/`
191+
192+
#### Dart Unit Testing
193+
194+
Tests for the platform implementations use [mockito] to generate mock objects of the native Dart
195+
wrappers. To generate the mock objects in `test/`, run
196+
`dart run build_runner build --delete-conflicting-outputs`.
197+
198+
### App-facing Interface
199+
200+
Code location: `lib/src/`
201+
202+
The app-facing interface shares the same structure as the platform interface and uses delegation
203+
to forward handling to the platform implementation. Note a few differences from the platform
204+
interface:
205+
206+
* Constructors and methods can contain more than one parameter.
207+
* Platform classes can be instantiated with a platform implementation or creation params of
208+
the corresponding platform interface class. See `AdsLoader.fromPlatform` and
209+
`AdsLoader.fromPlatformCreationParams`.
210+
211+
## Recommended Process for Adding a New Feature
212+
213+
### 1. Create a new feature request issue in the `flutter/flutter` repo.
214+
215+
See https://github.com/flutter/flutter/issues/new?assignees=&labels=&projects=&template=3_feature_request.yml
216+
217+
### 2. In that issue add the specific native classes/methods that this feature requires for each platform:
218+
219+
* [Android SDK]
220+
* [iOS SDK]
221+
222+
Add a note if this feature only exist for a single platform.
223+
224+
### 3. Add a design where the feature can be added to the platform interface and app-facing interface.
225+
226+
If this is only supported on a single platform, add where it can be added in the platform
227+
implementation.
228+
229+
### 4. Work can be started on the feature request or you can wait for feedback from a Flutter contributor.
230+
231+
[IMA SDKs]: https://developers.google.com/interactive-media-ads
232+
[AdsLoader]: lib/src/ads_loader.dart
233+
[AdDisplayContainer]: lib/src/ad_display_container.dart
234+
[PlatformAdsLoader]: lib/src/platform_interface/platform_ads_loader.dart
235+
[PlatformAdsManager]: lib/src/platform_interface/platform_ads_manager.dart
236+
[PlatformAdDisplayContainer]: lib/src/platform_interface/platform_ad_display_container.dart
237+
[Android SDK]: https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/api/reference/com/google/ads/interactivemedia/v3/api/package-summary
238+
[iOS SDK]: https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Classes
239+
[mockito]: https://pub.dev/packages/mockito

packages/interactive_media_ads/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ a separate video player positioned on top of the app's content video player.
1515

1616
**NOTE:**
1717
* The initial release for this package supports linear pre-roll video ads on iOS and Android
18-
* platforms.
18+
platforms.
1919
* Companion ads, Background Audio ads and Google Dynamic Ad Insertion methods are currently not
20-
* supported.
20+
supported.
2121

2222
## IMA client-side overview
2323

@@ -272,6 +272,10 @@ void dispose() {
272272
That's it! You're now requesting and displaying ads with the IMA SDK. To learn about additional SDK
273273
features, see the [API reference](https://pub.dev/documentation/interactive_media_ads/latest/).
274274

275+
## Contributing
276+
277+
For information on contributing to this plugin, see [`CONTRIBUTING.md`](CONTRIBUTING.md).
278+
275279
[1]: https://developers.google.com/interactive-media-ads
276280
[2]: https://www.iab.com/guidelines/vast/
277281
[3]: https://pub.dev/documentation/interactive_media_ads/latest/interactive_media_ads/AdDisplayContainer-class.html

packages/interactive_media_ads/android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class AdsRequestProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) :
2121
*
2222
* This must match the version in pubspec.yaml.
2323
*/
24-
const val pluginVersion = "0.1.2+2"
24+
const val pluginVersion = "0.1.2+3"
2525
}
2626

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

packages/interactive_media_ads/ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class AdsRequestProxyAPIDelegate: PigeonApiDelegateIMAAdsRequest {
1313
/// The current version of the `interactive_media_ads` plugin.
1414
///
1515
/// This must match the version in pubspec.yaml.
16-
static let pluginVersion = "0.1.2+2"
16+
static let pluginVersion = "0.1.2+3"
1717

1818
func pigeonDefaultConstructor(
1919
pigeonApi: PigeonApiIMAAdsRequest, adTagUrl: String, adDisplayContainer: IMAAdDisplayContainer,

packages/interactive_media_ads/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: interactive_media_ads
22
description: A Flutter plugin for using the Interactive Media Ads SDKs on Android and iOS.
33
repository: https://github.com/flutter/packages/tree/main/packages/interactive_media_ads
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+interactive_media_ads%22
5-
version: 0.1.2+2 # This must match the version in
5+
version: 0.1.2+3 # This must match the version in
66
# `android/src/main/kotlin/dev/flutter/packages/interactive_media_ads/AdsRequestProxyApi.kt` and
77
# `ios/interactive_media_ads/Sources/interactive_media_ads/AdsRequestProxyAPIDelegate.swift`
88

0 commit comments

Comments
 (0)