@maccesar/titools 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -12
- package/agents/ti-pro.md +4 -0
- package/commands/ti-audit.md +4 -0
- package/lib/config.js +2 -0
- package/package.json +1 -1
- package/skills/purgetss/SKILL.md +4 -4
- package/skills/purgetss/references/EXAMPLES.md +3 -3
- package/skills/purgetss/references/adopting-purgetss.md +2 -2
- package/skills/purgetss/references/animation-advanced.md +2 -2
- package/skills/purgetss/references/arbitrary-values.md +8 -5
- package/skills/purgetss/references/class-categories.md +5 -5
- package/skills/purgetss/references/class-index-properties.md +6 -6
- package/skills/purgetss/references/class-index.md +2 -2
- package/skills/purgetss/references/cli-commands.md +2 -2
- package/skills/purgetss/references/dynamic-component-creation.md +2 -2
- package/skills/purgetss/references/grid-layout.md +1 -1
- package/skills/purgetss/references/migration-guide.md +34 -4
- package/skills/purgetss/references/multi-density-images.md +6 -6
- package/skills/purgetss/references/platform-modifiers.md +21 -0
- package/skills/purgetss/references/ui-ux-design.md +1 -1
- package/skills/purgetss/references/version-history.md +9 -4
- package/skills/ti-admob-unified/SKILL.md +44 -0
- package/skills/ti-admob-unified/agents/openai.yaml +4 -0
- package/skills/ti-admob-unified/assets/example/app.js +1003 -0
- package/skills/ti-admob-unified/assets/example/lib/ads.js +618 -0
- package/skills/ti-admob-unified/assets/example/library-usage.js +104 -0
- package/skills/ti-admob-unified/references/api-reference.md +592 -0
- package/skills/ti-admob-unified/references/banners.md +435 -0
- package/skills/ti-admob-unified/references/contributing.md +228 -0
- package/skills/ti-admob-unified/references/dependencies.md +85 -0
- package/skills/ti-admob-unified/references/fullscreen.md +223 -0
- package/skills/ti-admob-unified/references/game-monetization.md +17 -0
- package/skills/ti-admob-unified/references/getting-started.md +275 -0
- package/skills/ti-admob-unified/references/index.md +30 -0
- package/skills/ti-admob-unified/references/integration.md +85 -0
- package/skills/ti-admob-unified/references/library.md +189 -0
- package/skills/ti-admob-unified/references/mediation.md +132 -0
- package/skills/ti-admob-unified/references/migration.md +255 -0
- package/skills/ti-admob-unified/references/module-changelog.md +54 -0
- package/skills/ti-admob-unified/references/module-license.txt +21 -0
- package/skills/ti-admob-unified/references/privacy.md +254 -0
- package/skills/ti-admob-unified/references/roadmap.md +146 -0
- package/skills/ti-admob-unified/references/source-notes.md +33 -0
- package/skills/ti-admob-unified/references/source-snapshot.json +440 -0
- package/skills/ti-admob-unified/references/third-party-notices.md +22 -0
- package/skills/ti-game/SKILL.md +10 -1
- package/skills/ti-game/references/api.md +10 -2
- package/skills/ti-game/references/debugging-performance.md +6 -0
- package/skills/ti-game/references/examples.md +11 -1
- package/skills/ti-game/references/patterns.md +24 -2
- package/skills/ti-game/references/physics.md +502 -0
- package/skills/ti-game/references/project-setup.md +23 -1
- package/skills/ti-game/references/recipes-action.md +46 -14
- package/skills/ti-game/references/recipes-adventure-effects.md +12 -1
- package/skills/ti-game/references/roadmap.md +2 -2
- package/skills/ti-game/references/tilemaps.md +2 -1
- package/skills/ti-game-assets/SKILL.md +53 -0
- package/skills/ti-game-assets/agents/openai.yaml +4 -0
- package/skills/ti-game-assets/references/alpha.md +26 -0
- package/skills/ti-game-assets/references/art-direction.md +37 -0
- package/skills/ti-game-assets/references/integration.md +49 -0
- package/skills/ti-game-assets/references/manifest.example.json +429 -0
- package/skills/ti-game-assets/references/manifest.md +39 -0
- package/skills/ti-game-assets/references/offline-audio.md +33 -0
- package/skills/ti-game-assets/references/prompts.md +33 -0
- package/skills/ti-game-assets/references/repeating-textures.md +17 -0
- package/skills/ti-game-assets/references/responsible-ads.md +31 -0
- package/skills/ti-game-assets/references/sound-assets.md +42 -0
- package/skills/ti-game-assets/references/vector-sources.md +21 -0
- package/skills/ti-game-assets/scripts/alpha_tools.py +160 -0
- package/skills/ti-game-assets/scripts/requirements.txt +1 -0
- package/skills/ti-game-assets/scripts/validate_manifest.py +267 -0
- package/skills/ti-synthengine/SKILL.md +37 -13
- package/skills/ti-synthengine/references/api.md +397 -31
- package/skills/ti-synthengine/references/audio-engine.md +235 -14
- package/skills/ti-synthengine/references/examples.md +396 -17
- package/skills/ti-synthengine/references/guide.md +331 -12
- package/skills/ti-synthengine/references/recipes.md +212 -22
- package/skills/ti-synthengine/references/recommendations.md +53 -16
- package/skills/ti-synthengine/references/sound-design.md +359 -15
- package/skills/ti-synthengine/references/source-notes.md +121 -0
- package/skills/ti-synthengine/references/source-snapshot.json +105 -0
- package/skills/ti-synthengine/references/stats-performance.json +2992 -0
- package/skills/ti-synthengine/references/stats-performance.md +38 -0
- package/skills/ti-synthengine/references/troubleshooting.md +61 -4
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
> Source snapshot: official ti.admob.unified 1.0.0 documentation at commit `5b4cbf9` (copied 2026-10-11). Relative links rebased for this skill.
|
|
2
|
+
|
|
3
|
+
# Integrating the module
|
|
4
|
+
|
|
5
|
+
The native module manages Google Mobile Ads, UMP, portable proxy behavior and host lifecycle. The consuming application controls navigation and layout, including which screen is visible.
|
|
6
|
+
|
|
7
|
+
## Recommended path
|
|
8
|
+
|
|
9
|
+
Copy [`example/lib/ads.js`](../assets/example/lib/ads.js) into the consuming application's `lib/` directory. It covers every format implemented by version `1.0.0` and supplies the startup, cleanup and placement code shared by applications.
|
|
10
|
+
|
|
11
|
+
See [Copy-ready JavaScript library](library.md) for the API and examples, and [`example/library-usage.js`](../assets/example/library-usage.js) for a compact runnable integration.
|
|
12
|
+
|
|
13
|
+
## Division of responsibility
|
|
14
|
+
|
|
15
|
+
| Responsibility | Owner |
|
|
16
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
17
|
+
| UMP, Google Mobile Ads initialization and native callbacks | Module |
|
|
18
|
+
| Application/activity background and foreground | Module |
|
|
19
|
+
| Automatic banner refresh | Google Mobile Ads SDK, using the ad-unit policy configured in AdMob |
|
|
20
|
+
| Consent → `canRequestAds()` → initialization sequence | Copy-ready library, or the application when using the raw API |
|
|
21
|
+
| Tab/window coverage | Application |
|
|
22
|
+
| Permanent banner host and content inset | Application |
|
|
23
|
+
| Production/test ad-unit selection | Application build configuration |
|
|
24
|
+
| Frequency and natural presentation points for fullscreen ads | Application |
|
|
25
|
+
|
|
26
|
+
## Screen lifecycle
|
|
27
|
+
|
|
28
|
+
Handle screen navigation separately from application backgrounding.
|
|
29
|
+
|
|
30
|
+
The module automatically follows the Android activity and iOS application lifecycle. Do not add duplicate `Ti.App` pause/resume handlers for banners.
|
|
31
|
+
|
|
32
|
+
An Android secondary window backed by another activity is already covered by the automatic lifecycle handling. The application calls `pause()` only when its own navigation hides a placement while the same host lifecycle remains active, such as a custom same-activity overlay:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
banner.pause()
|
|
36
|
+
|
|
37
|
+
const child = Alloy.createController('child').getView()
|
|
38
|
+
child.addEventListener('close', () => banner.resume())
|
|
39
|
+
child.open()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Pausing does not change `visible`, opacity, height, the host, or the loaded creative. Do not destroy/recreate on tab changes, focus/blur, or light/dark appearance changes. Rebuild only for a real configuration or authorization boundary, or after a recoverable failure.
|
|
43
|
+
|
|
44
|
+
On Android, the module handles activity recreation caused by a configuration change. It releases the stale native `AdView`, preserves the JavaScript proxy without emitting `destroyed`, and reloads after Titanium creates the replacement view.
|
|
45
|
+
|
|
46
|
+
## Refresh ownership
|
|
47
|
+
|
|
48
|
+
Call `load()` once when creating a banner. Do not add `setInterval`, `setTimeout`, or a periodic destroy/create loop. Google Mobile Ads reads the refresh policy configured for that ad unit in AdMob and owns subsequent banner requests.
|
|
49
|
+
|
|
50
|
+
The application pauses a placement when navigation hides it. On iOS the module disables native autoload until every pause cause clears. On Android it pauses native ad-view processing; Google also requires the banner to be visible for automatic refresh. Keep a visible banner active even if an internal screen state changes.
|
|
51
|
+
|
|
52
|
+
## Banner layout
|
|
53
|
+
|
|
54
|
+
Reserve the slot when creating the placement. Expanding it after the first creative arrives moves content that is already on screen.
|
|
55
|
+
|
|
56
|
+
Keep these layout values aligned:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
bannerHost.height = dimension
|
|
60
|
+
content.bottom = dimension
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Keep both values unchanged during `pause()` and `resume()` to avoid reflowing lists and scroll views while the same placement remains in use.
|
|
64
|
+
|
|
65
|
+
Adaptive banners report their real `event.height` in dp. Fixed banners should reserve the exact height of the requested size. See [Banner ads](banners.md#reserve-real-layout-space).
|
|
66
|
+
|
|
67
|
+
## Raw API
|
|
68
|
+
|
|
69
|
+
Applications that do not want the copy-ready library can use the module directly. [`example/app.js`](../assets/example/app.js) exercises the low-level API, including:
|
|
70
|
+
|
|
71
|
+
- consent and optional ATT;
|
|
72
|
+
- initialization and mediation diagnostics;
|
|
73
|
+
- standard and adaptive banners;
|
|
74
|
+
- explicit screen-level banner pause/resume;
|
|
75
|
+
- interstitial, rewarded and app-open load/show separation;
|
|
76
|
+
- privacy options and deterministic cleanup.
|
|
77
|
+
|
|
78
|
+
When using the raw API, keep named event callbacks so every listener can be removed before `destroy()`.
|
|
79
|
+
|
|
80
|
+
## Next
|
|
81
|
+
|
|
82
|
+
- [Copy-ready JavaScript library](library.md)
|
|
83
|
+
- [Banner ads](banners.md)
|
|
84
|
+
- [Fullscreen ads](fullscreen.md)
|
|
85
|
+
- [Privacy and initialization](privacy.md)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
> Source snapshot: official ti.admob.unified 1.0.0 documentation at commit `5b4cbf9` (copied 2026-10-11). Relative links rebased for this skill.
|
|
2
|
+
|
|
3
|
+
# Copy-ready JavaScript library
|
|
4
|
+
|
|
5
|
+
The integration library is [`example/lib/ads.js`](../assets/example/lib/ads.js). Copy it unchanged to the appropriate location:
|
|
6
|
+
|
|
7
|
+
- Alloy: `app/lib/ads.js`
|
|
8
|
+
- Classic Titanium: `Resources/lib/ads.js`
|
|
9
|
+
|
|
10
|
+
Then import it with:
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
const Admob = require('ti.admob.unified')
|
|
14
|
+
const ads = require('lib/ads')
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The library handles UMP sequencing, the `canRequestAds()` check, initialization, named-listener cleanup, banner slots, deferred loads, privacy-option reauthorization and terminal cleanup. You can also use the native module directly, as [`example/app.js`](../assets/example/app.js) does while sharing the library’s fullscreen size guard.
|
|
18
|
+
|
|
19
|
+
## What it covers
|
|
20
|
+
|
|
21
|
+
| Format | Library factory | Lifecycle returned |
|
|
22
|
+
| --------------- | ------------------------ | ------------------------------------------------------------------------ |
|
|
23
|
+
| Standard banner | `createBanner()` | `pause()`, `resume()`, `retry()`, `rebuild()`, `isLoaded()`, `destroy()` |
|
|
24
|
+
| Adaptive banner | `createAdaptiveBanner()` | `pause()`, `resume()`, `retry()`, `rebuild()`, `isLoaded()`, `destroy()` |
|
|
25
|
+
| Interstitial | `createInterstitial()` | `load()`, `show()`, `retry()`, `isLoaded()`, `destroy()` |
|
|
26
|
+
| Rewarded | `createRewarded()` | `load()`, `show()`, `retry()`, `isLoaded()`, `destroy()` |
|
|
27
|
+
| App open | `createAppOpen()` | `load()`, `show()`, `retry()`, `isLoaded()`, `destroy()` |
|
|
28
|
+
|
|
29
|
+
Rewarded interstitial and native ads are not included because version `1.0.0` does not implement those factories.
|
|
30
|
+
|
|
31
|
+
## Start once
|
|
32
|
+
|
|
33
|
+
Create placements before or after `start()`. Loads requested before initialization wait until privacy checks and SDK initialization complete.
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
ads.start({
|
|
37
|
+
consent: {
|
|
38
|
+
tagForUnderAgeOfConsent: false
|
|
39
|
+
},
|
|
40
|
+
initialization: {
|
|
41
|
+
testDeviceIds: ['YOUR_TEST_DEVICE_ID']
|
|
42
|
+
}
|
|
43
|
+
}).then(result => {
|
|
44
|
+
if (!result.initialized) {
|
|
45
|
+
Ti.API.warn('Ads are unavailable for this session')
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Set `requestTrackingAuthorization: true` only when the application has a real ATT use case and a valid `NSUserTrackingUsageDescription`. ATT is not another ad-request gate.
|
|
51
|
+
|
|
52
|
+
## Banners
|
|
53
|
+
|
|
54
|
+
A banner needs a permanent host and a positive reservation in dp. The library changes the host height and the adjacent content inset together; it never overlays the content.
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const banner = ads.createAdaptiveBanner({
|
|
58
|
+
host: bannerHost,
|
|
59
|
+
content,
|
|
60
|
+
reservedHeight: 50,
|
|
61
|
+
adUnitId: Admob.TEST_ADAPTIVE_BANNER,
|
|
62
|
+
adaptiveType: Admob.ADAPTIVE_ANCHORED,
|
|
63
|
+
onLoaded: event => Ti.API.info(`Banner: ${event.height}${event.heightUnit}`),
|
|
64
|
+
onFailedToLoad: event => Ti.API.warn(event.error)
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Use `createBanner()` with `adSize` or `customAdSize` for a fixed banner. Use `createAdaptiveBanner()` when Google should choose the height for the available width.
|
|
69
|
+
|
|
70
|
+
Call `pause()` when that placement stops being shown because the application selected another tab or opened another window over it. Call `resume()` when the same screen is shown again. These methods preserve the same native proxy, creative, visibility, opacity, host, and reserved height:
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
banner.pause()
|
|
74
|
+
openChildWindow()
|
|
75
|
+
|
|
76
|
+
child.addEventListener('close', () => {
|
|
77
|
+
banner.resume()
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Do not mirror `Ti.App` background and foreground events. The native module already owns activity/application lifecycle as an independent pause cause.
|
|
82
|
+
|
|
83
|
+
The library creates no refresh timer. The first request comes from `load()`; later banner refreshes belong to Google Mobile Ads and the refresh policy configured for that ad unit in AdMob. A banner that is not actually on screen is ineligible for Android auto-refresh. On iOS the module disables and restores native autoload while paused.
|
|
84
|
+
|
|
85
|
+
Use `retry()` after a recoverable failure. Use `rebuild()` when the placement configuration changes, such as its width or orientation. Tab focus, window focus, appearance changes and ordinary background/foreground transitions do not require a rebuild.
|
|
86
|
+
|
|
87
|
+
## Fullscreen ads
|
|
88
|
+
|
|
89
|
+
Create once, load early, and show only at a moment chosen by the application:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
const interstitial = ads.createInterstitial({
|
|
93
|
+
window: win,
|
|
94
|
+
adUnitId: Admob.TEST_INTERSTITIAL,
|
|
95
|
+
autoReload: true,
|
|
96
|
+
onLoaded: () => Ti.API.info('Ready for the next natural break')
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
interstitial.load()
|
|
100
|
+
|
|
101
|
+
function onNaturalBreak() {
|
|
102
|
+
interstitial.show() // false means no ready ad; continue without blocking
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Rewarded ads grant value only from `onRewarded`:
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
const rewarded = ads.createRewarded({
|
|
110
|
+
window: win,
|
|
111
|
+
adUnitId: Admob.TEST_REWARDED,
|
|
112
|
+
onRewarded: event => grantReward(event.rewardAmount, event.rewardType)
|
|
113
|
+
})
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
App-open ads are prepared the same way and shown only during the application's own foreground loading experience:
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
const appOpen = ads.createAppOpen({
|
|
120
|
+
window: win,
|
|
121
|
+
adUnitId: Admob.TEST_APP_OPEN
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
appOpen.load()
|
|
125
|
+
|
|
126
|
+
function onApplicationResumed() {
|
|
127
|
+
appOpen.show()
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Pass the owning `window` to each fullscreen factory (otherwise the library reads `Ti.UI.currentWindow`). The library remembers its dimensions when requesting the ad. Rotation alone makes no requests. At `show()`, a changed size discards and reloads only that ad and returns `false`; wait for `onLoaded` and a later user action to show it. Banners are not rebuilt by this check.
|
|
132
|
+
|
|
133
|
+
The raw-API playground shares this logic through `createFullscreenSizeGuard(getSize)`: call `recordLoad()` before requesting, then `show(present, reload)` when the user requests presentation. This helper does not initialize the SDK or run consent.
|
|
134
|
+
|
|
135
|
+
`show()` returns `false` when no valid ad is ready. Do not delay navigation or user work waiting for a fullscreen request.
|
|
136
|
+
|
|
137
|
+
## Privacy and diagnostics
|
|
138
|
+
|
|
139
|
+
Expose the privacy entry point only when required:
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
privacyButton.visible = ads.isPrivacyOptionsRequired()
|
|
143
|
+
|
|
144
|
+
function openPrivacyOptions() {
|
|
145
|
+
ads.showPrivacyOptions().then(event => {
|
|
146
|
+
if (event.success === false) {
|
|
147
|
+
Ti.API.warn(event.error)
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
After the form closes, the library reevaluates authorization and rebuilds active ad requests to account for any consent changes.
|
|
154
|
+
|
|
155
|
+
Ad Inspector also has a promise wrapper:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
ads.openAdInspector().then(event => {
|
|
159
|
+
if (!event.success) {
|
|
160
|
+
Ti.API.warn(event.error)
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Cleanup
|
|
166
|
+
|
|
167
|
+
Destroy a placement when its owning window closes. For application shutdown or a test harness, dispose every registered placement at once.
|
|
168
|
+
|
|
169
|
+
On Android, Titanium also fires `close` while it recreates the window's activity, for example when the user switches between light and dark mode. The window survives, and the event carries `_closeFromActivityForcedToDestroy`. Skip that event, or the ads and their listeners are gone when the window comes back:
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
win.addEventListener('close', event => {
|
|
173
|
+
if (!event._closeFromActivityForcedToDestroy) banner.destroy()
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
// Or, when this ads service owns every placement:
|
|
177
|
+
ads.destroyAll()
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Every destroy operation is idempotent. A destroyed manager cannot be reused; create another manager for a new placement.
|
|
181
|
+
|
|
182
|
+
See [`example/library-usage.js`](../assets/example/library-usage.js) for a complete runnable integration.
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
## Concurrent operations and cleanup
|
|
186
|
+
|
|
187
|
+
Concurrent calls to `showPrivacyOptions()` share one native presentation and one promise. `openAdInspector()` does the same for Inspector. Terminal events and synchronous native exceptions remove their listeners; a later call starts a new operation. `destroyAll()` releases placements only. It does not cancel an SDK form or its pending promise.
|
|
188
|
+
|
|
189
|
+
A banner failure or destruction cleans up the old proxy before invoking application callbacks, so calling `retry()` from those callbacks preserves the replacement. On iOS, adaptive placements reserve the native anchored height when width is known and wait for positive layout before loading. Destroying a placement removes any pending layout listener.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
> Source snapshot: official ti.admob.unified 1.0.0 documentation at commit `5b4cbf9` (copied 2026-10-11). Relative links rebased for this skill.
|
|
2
|
+
|
|
3
|
+
# AdMob mediation
|
|
4
|
+
|
|
5
|
+
The first release, `1.0.0`, provides five optional dependency modules with identical identifiers on iOS and Android. Install only the networks the application intends to use. The core `ti.admob.unified` contains Google Mobile Ads and UMP only. Each complement has no JavaScript API and performs no manual provider initialization.
|
|
6
|
+
|
|
7
|
+
| Network | Module ID | iOS adapter | Android adapter |
|
|
8
|
+
| ------------------------- | ------------------------------------- | ----------- | --------------- |
|
|
9
|
+
| AppLovin | `ti.admob.unified.mediation.applovin` | `13.6.4.0` | `13.6.4.2` |
|
|
10
|
+
| Meta Audience Network | `ti.admob.unified.mediation.meta` | `6.22.0.0` | `6.22.0.1` |
|
|
11
|
+
| InMobi | `ti.admob.unified.mediation.inmobi` | `11.4.1.0` | `11.4.1.2` |
|
|
12
|
+
| Unity Ads | `ti.admob.unified.mediation.unity` | `4.20.1.0` | `4.20.1.0` |
|
|
13
|
+
| Liftoff Monetize (Vungle) | `ti.admob.unified.mediation.liftoff` | `7.7.7.0` | `7.7.8.1` |
|
|
14
|
+
|
|
15
|
+
ironSource mediation is deferred: neither its adapter nor its advertising SDK is distributed. Unity includes UnityCoherenceLib. Unity Ads 4.20.1 no longer depends on IronSourceAdQualitySDK, so it is not distributed.
|
|
16
|
+
|
|
17
|
+
## Installing one or several networks
|
|
18
|
+
|
|
19
|
+
Install the core ZIP and each selected complement ZIP for every target platform. One declaration covers both platforms:
|
|
20
|
+
|
|
21
|
+
```xml
|
|
22
|
+
<modules>
|
|
23
|
+
<module version="1.0.0">ti.admob.unified</module>
|
|
24
|
+
<module version="1.0.0">ti.admob.unified.mediation.applovin</module>
|
|
25
|
+
</modules>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
For AppLovin and Unity together:
|
|
29
|
+
|
|
30
|
+
```xml
|
|
31
|
+
<modules>
|
|
32
|
+
<module version="1.0.0">ti.admob.unified</module>
|
|
33
|
+
<module version="1.0.0">ti.admob.unified.mediation.applovin</module>
|
|
34
|
+
<module version="1.0.0">ti.admob.unified.mediation.unity</module>
|
|
35
|
+
</modules>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use `1.0.0` for the core and complements. Call only `require('ti.admob.unified')` and its factories. To remove a network, remove its declaration and rebuild.
|
|
39
|
+
|
|
40
|
+
## Installing an adapter is not the same as enabling a network
|
|
41
|
+
|
|
42
|
+
Installing an adapter adds its SDK to the application and makes it discoverable by Google Mobile Ads. It does not approve a publisher account, configure a mediation group or validate credentials. Leave unneeded complements out of the build. Their exact frameworks, dependencies and versions are recorded in [Dependencies](dependencies.md).
|
|
43
|
+
|
|
44
|
+
## Publisher setup
|
|
45
|
+
|
|
46
|
+
For each network that an application will use:
|
|
47
|
+
|
|
48
|
+
1. Create or connect the publisher account for that network.
|
|
49
|
+
2. Add the network as an ad source in the AdMob mediation group.
|
|
50
|
+
3. Enter the provider credentials and map the provider placement to the AdMob ad unit.
|
|
51
|
+
4. Complete the provider's privacy and store-disclosure requirements.
|
|
52
|
+
5. Validate the integration with test ads and Ad Inspector before enabling production traffic.
|
|
53
|
+
|
|
54
|
+
Google Mobile Ads can still inspect or initialize every installed adapter during SDK startup. In development, incomplete or conflicting server mappings can produce provider warnings even when Google serves the requested test banner. Examples include a missing AppLovin SDK key and multiple Liftoff Monetize app IDs. The module does not add provider credentials to either native manifest; AdMob supplies those server parameters from the mediation mapping.
|
|
55
|
+
|
|
56
|
+
Do not silence these messages with placeholder credentials. Complete the provider mapping, use that provider's test mode, and verify it through single-source testing in Ad Inspector. If the application does not intend to use a network, leave it out of the AdMob mediation group.
|
|
57
|
+
|
|
58
|
+
Google maintains the current setup instructions and format caveats in its [Android mediation network guide](https://developers.google.com/admob/android/choose-networks) and [iOS mediation network guide](https://developers.google.com/admob/ios/choose-networks). Use formats supported by the selected network and adapter version.
|
|
59
|
+
|
|
60
|
+
## Missing configuration and startup errors
|
|
61
|
+
|
|
62
|
+
Only install selected complements when the app will use mediation and its publisher accounts, source mappings and credentials are configured. The examples and the core-only test app do not require these accounts. Do not install the complements merely to run Google demo ads.
|
|
63
|
+
|
|
64
|
+
An internal Android demo build with several adapters produced these messages. Each points to a different failure; only some identify missing credentials:
|
|
65
|
+
|
|
66
|
+
| Message | What it establishes | Action |
|
|
67
|
+
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
68
|
+
| AppLovin: `Missing or invalid SDK Key.` | The adapter did not receive a usable SDK key. | Verify the publisher SDK key and the AppLovin mapping in AdMob. |
|
|
69
|
+
| AdColony: `Failed to create Adapter.` | Google could not construct the requested adapter. This does not establish a missing key. AdColony is not one of the five distributed adapters. | Inspect the requested ad source/mapping and adapter availability in Ad Inspector. Do not add a legacy SDK or placeholder credentials just to silence it. |
|
|
70
|
+
| Liftoff/Vungle: `Timeout.` | Initialization did not finish before the SDK timeout. In the observed run, a preceding warning reported conflicting app IDs and selection of `fake-vungle-app-id`. | Check the provider app ID and AdMob mapping; the timeout alone does not prove which configuration value is wrong. |
|
|
71
|
+
|
|
72
|
+
### Why there is no automatic “missing local key → skip this network” filter
|
|
73
|
+
|
|
74
|
+
Each optional module only packages dependencies; it does not call each provider's initializer. Google Mobile Ads controls adapter initialization and supplies mediation parameters from AdMob. There is no supported pre-initialization API in the Google Mobile Ads APIs used here that lets this module read all publisher mappings and selectively suppress adapters with missing credentials.
|
|
75
|
+
|
|
76
|
+
A key may be absent from JavaScript or the native manifest and still be configured in AdMob. The [AppLovin adapter guide](https://developers.google.com/admob/android/mediation/applovin) instructs publishers to enter the SDK key in AdMob; its changelog says adapter 12.1.0.0 stopped checking the Android manifest. The module leaves readiness checks and provider initialization to Google, without using private SDK internals.
|
|
77
|
+
|
|
78
|
+
Choose the setup that matches the application:
|
|
79
|
+
|
|
80
|
+
- For Google ads alone, omit complements and call `Admob.initialize({})`. There are no third-party adapters to initialize.
|
|
81
|
+
- For mediation, include one `tiapp.xml` entry per selected network, configure its account and AdMob mappings, and call `Admob.initialize({})`. Google discovers the installed adapters without an `enableMediation` flag or manual provider initializer. Check native initialization results and Ad Inspector; `getMediationStatus()` reports the adapter initialization states known to Google.
|
|
82
|
+
|
|
83
|
+
For a session that deliberately skips initialization of installed adapters, see the [initialization reference](api-reference.md#automatic-adapter-discovery). That exception is global and does not validate credentials or filter individual networks.
|
|
84
|
+
|
|
85
|
+
## Portable diagnostics
|
|
86
|
+
|
|
87
|
+
`getMediationStatus()` belongs to the core and returns `{ initializationState, adapters }`. It includes every adapter Google reports, including Google, sorted by native class name. Entries contain `adapterClass`, `state`, `description` and numeric `latencyMs`; native class names may differ across platforms.
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
const Admob = require('ti.admob.unified')
|
|
91
|
+
Admob.addEventListener('module_initialized', event => {
|
|
92
|
+
const diagnostic = Admob.getMediationStatus()
|
|
93
|
+
Ti.API.info(diagnostic.initializationState)
|
|
94
|
+
diagnostic.adapters.forEach(adapter => {
|
|
95
|
+
Ti.API.info(`${adapter.adapterClass}: ${adapter.state} (${adapter.latencyMs} ms) ${adapter.description}`)
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Before `initialize()`, the result is `not_started` with no adapters. During startup it is `initializing` and Google's map may be partial or empty. `completed` means the core callback finished, even when an adapter is `not_ready`; an initialization exception reports `failed`. The query does not initialize SDKs or request ads. Neither absence from this map nor `ready` establishes installed-module inventory, valid accounts, credentials or ad delivery. See the [complete contract](api-reference.md#mediation-diagnostics).
|
|
101
|
+
|
|
102
|
+
New providers need no core registration. Follow [Adding a network](contributing.md#adding-a-network) to package an existing official adapter.
|
|
103
|
+
|
|
104
|
+
After initialization on a registered test device, inspect actual requests:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
Admob.addEventListener('ad_inspector_closed', event => {
|
|
108
|
+
Ti.API.info(JSON.stringify(event))
|
|
109
|
+
})
|
|
110
|
+
Admob.openAdInspector()
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Privacy and bundled resources
|
|
114
|
+
|
|
115
|
+
Continue using UMP and `canRequestAds()` before requests. Each selected iOS complement includes its vendor resources and privacy manifests. Review the current Google/provider guidance for SKAdNetwork entries, privacy disclosures and consent propagation for the networks the application distributes. Android resolves each selected adapter's SDK transitively through its POM.
|
|
116
|
+
|
|
117
|
+
The public example and the test demo use only the core, with no mediation flag. No provider credentials are required to run Google demo ads. Adding a selected complement to `tiapp.xml` makes its adapter discoverable at SDK startup; configure the provider account and AdMob mapping before using that network. Automatic discovery does not validate credentials or eliminate initialization timeouts.
|
|
118
|
+
|
|
119
|
+
## Release validation
|
|
120
|
+
|
|
121
|
+
Build all discovered modules (two ZIPs per module) and inspect their framework inventories and generated POMs. Compile isolated consumer applications on both platforms with core only, each of the five complements individually, AppLovin + Unity, and all five together. Check that no framework is duplicated and that resolved dependency versions remain pinned.
|
|
122
|
+
|
|
123
|
+
Record separately:
|
|
124
|
+
|
|
125
|
+
- Integration and linking: the build succeeds, expected adapter classes are visible, and official Google test ads load.
|
|
126
|
+
- Provider ad delivery: the provider returns its own test ad with valid publisher accounts and AdMob mappings, confirmed by single-source testing in Ad Inspector.
|
|
127
|
+
|
|
128
|
+
Google test ads do not prove provider delivery. iOS simulator results do not substitute for device results. Re-run device validation when hardware is available. Do not use or click production ads during development.
|
|
129
|
+
|
|
130
|
+
## Unity consent with the pinned adapter
|
|
131
|
+
|
|
132
|
+
The distribution uses Unity adapter `4.20.1.0` on both platforms. It includes the automatic forwarding of `IABTCF_AddtlConsent` introduced in `4.19.0.1` on [Android](https://developers.google.com/admob/android/mediation/unity) and [iOS](https://developers.google.com/admob/ios/mediation/unity). Configure Unity as a consent partner and verify signal propagation with the provider before enabling demand. Adapter presence and a Google test ad do not establish provider consent or delivery.
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
> Source snapshot: official ti.admob.unified 1.0.0 documentation at commit `5b4cbf9` (copied 2026-10-11). Relative links rebased for this skill.
|
|
2
|
+
|
|
3
|
+
# Migrating to ti.admob.unified
|
|
4
|
+
|
|
5
|
+
This guide covers adopting the first release, `1.0.0`, from a platform-specific AdMob module or an internal development build. There are no previously published versions of this module.
|
|
6
|
+
|
|
7
|
+
## Selecting mediation dependencies
|
|
8
|
+
|
|
9
|
+
Install only the core for Google ads. If the application mediates, install a complement for each selected network. For example:
|
|
10
|
+
|
|
11
|
+
```xml
|
|
12
|
+
<modules>
|
|
13
|
+
<module version="1.0.0">ti.admob.unified</module>
|
|
14
|
+
<module version="1.0.0">ti.admob.unified.mediation.applovin</module>
|
|
15
|
+
</modules>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The aggregate development package is not part of this release. Replace its declaration with the desired per-network modules. `getMediationStatus()` now reports Google initialization states through `{ initializationState, adapters }`; it does not validate mappings or delivery. ironSource mediation is deferred. See [AdMob mediation](mediation.md).
|
|
19
|
+
|
|
20
|
+
## If you used an internal pre-release build
|
|
21
|
+
|
|
22
|
+
Internal ZIPs exposed API differences that never reached a published release. Update code that depends on them as follows.
|
|
23
|
+
|
|
24
|
+
### Generic mediation diagnostics
|
|
25
|
+
|
|
26
|
+
Replace reads of the old six-Boolean map (for example `status.appLovin`) with iteration over `Admob.getMediationStatus().adapters` after `module_initialized`. Use `initializationState` for the core process and each entry's `state` for Google's adapter report. There is no portable provider-key mapping: native class names differ between iOS and Android. Before startup the array is empty; during startup it may be partial. A `ready` entry does not prove account configuration or ad delivery.
|
|
27
|
+
|
|
28
|
+
Remove calls to `isAppLovinAvailable`, `isMetaAvailable`, `isInMobiAvailable`, `isVungleAvailable`, `isUnityAvailable`, `isIronSourceAvailable` and `enableOptionalMediationNetworks`. Also remove `setAppLovinGDPRConsent`, `setInMobiGDPRConsent` and `setVungleGDPRConsent`; those pre-release setters only logged warnings. Continue using UMP and each provider's documented consent requirements. `disableMediation` and the `module_initialized` payload are unchanged.
|
|
29
|
+
|
|
30
|
+
### There is no `COLLAPSIBLE_TOP` or `COLLAPSIBLE_BOTTOM`
|
|
31
|
+
|
|
32
|
+
Neither constant is exported. Reading it returns `undefined`; passing `Admob.COLLAPSIBLE_TOP` therefore sends `undefined` to the native layer.
|
|
33
|
+
|
|
34
|
+
They used to hold `"collapsible_top"` and `"collapsible_bottom"`. Google's SDK accepts only `"top"` and `"bottom"`, and the module forwarded the value unchanged, so every request built from those constants was invalid.
|
|
35
|
+
|
|
36
|
+
The `collapsible` property itself is unchanged and now works on both platforms. It takes Google's native string:
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
const banner = Admob.createAdaptiveBanner({
|
|
40
|
+
adUnitId: Admob.TEST_ADAPTIVE_BANNER,
|
|
41
|
+
collapsible: 'bottom'
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### `smart_banner` no longer produces a full-width banner on iOS
|
|
46
|
+
|
|
47
|
+
Google removed the size on Android and deprecated it on iOS. Internal builds selected a fixed 320×50 banner on Android and a full-width strip on iOS. The value now falls back to `BANNER` on both platforms, like any other unrecognised size.
|
|
48
|
+
|
|
49
|
+
Android behaviour is unaffected. On iOS, a placement that relied on `adSize: 'smart_banner'` for a full-width strip now renders a 320×50 banner.
|
|
50
|
+
|
|
51
|
+
The replacement is `customAdSize`, which both platforms accept:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
function screenWidthInDp() {
|
|
55
|
+
const caps = Ti.Platform.displayCaps
|
|
56
|
+
|
|
57
|
+
if (Ti.Platform.osname === 'android') {
|
|
58
|
+
return Math.round(caps.platformWidth / caps.logicalDensityFactor)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return Math.round(caps.platformWidth)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const banner = Admob.createBanner({
|
|
65
|
+
adUnitId: Admob.TEST_BANNER,
|
|
66
|
+
customAdSize: { width: screenWidthInDp(), height: 50 },
|
|
67
|
+
width: Ti.UI.FILL
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`createAdaptiveBanner()` is the other option when Google should choose the height. See [Standard banner properties](banners.md#creation-properties-1).
|
|
72
|
+
|
|
73
|
+
### Legacy privacy methods no longer gate ads
|
|
74
|
+
|
|
75
|
+
`canShowPersonalizedAds()` always returns `false` and `canShowAds()` is an alias of `canRequestAds()`. Code that branched on either one has to move to the single gate described below.
|
|
76
|
+
|
|
77
|
+
## Module declaration
|
|
78
|
+
|
|
79
|
+
Replace platform-specific or older AdMob modules with one declaration:
|
|
80
|
+
|
|
81
|
+
```xml
|
|
82
|
+
<modules>
|
|
83
|
+
<module version="1.0.0">ti.admob.unified</module>
|
|
84
|
+
</modules>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Add the selected network complements only if the application mediates; for example, `<module version="1.0.0">ti.admob.unified.mediation.applovin</module>` for AppLovin.
|
|
88
|
+
|
|
89
|
+
Update JavaScript imports:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
const Admob = require('ti.admob.unified')
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Install both local artifacts when the app targets iOS and Android.
|
|
96
|
+
|
|
97
|
+
## Move the application ID to `tiapp.xml`
|
|
98
|
+
|
|
99
|
+
Remove `applicationId` from JavaScript initialization. Configure `GADApplicationIdentifier` on iOS and `com.google.android.gms.ads.APPLICATION_ID` on Android as described in [Getting started](getting-started.md).
|
|
100
|
+
|
|
101
|
+
## Replace privacy gates
|
|
102
|
+
|
|
103
|
+
Before:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
if (Admob.canShowPersonalizedAds() || !Admob.isGDPR()) {
|
|
107
|
+
loadAds()
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
After:
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
if (Admob.canRequestAds()) {
|
|
115
|
+
loadAds()
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Do not consume:
|
|
120
|
+
|
|
121
|
+
- `canShowPersonalizedAds()`
|
|
122
|
+
- `isGDPR()`
|
|
123
|
+
- `canShowAds()`
|
|
124
|
+
- `consent_ready`
|
|
125
|
+
- `consent_error`
|
|
126
|
+
- legacy payload aliases such as `isPrivacyOptionsRequired`
|
|
127
|
+
|
|
128
|
+
Use `consent_complete`, `canRequestAds`, and `privacyOptionsRequired`.
|
|
129
|
+
|
|
130
|
+
## Replace callback-style consent code
|
|
131
|
+
|
|
132
|
+
The supported contract is event-based:
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
Admob.addEventListener('consent_complete', onConsentComplete)
|
|
136
|
+
Admob.requestConsent({})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Callback properties passed inside the config object are not invoked.
|
|
140
|
+
|
|
141
|
+
## Request UMP before initialization
|
|
142
|
+
|
|
143
|
+
The recommended order is:
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
UMP -> canRequestAds -> initialize -> load ads
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Use that same sequence on both platforms. Do not initialize before UMP has updated the current session.
|
|
150
|
+
|
|
151
|
+
App Tracking Transparency is optional and sits outside this sequence. If your application has its own tracking case, resolve it before `initialize()`; it is not an ad-request gate, and `canRequestAds()` remains the only one. The call is portable: iOS resolves ATT, and Android emits `tracking_authorization_completed` immediately with `applicable: false`.
|
|
152
|
+
|
|
153
|
+
## Adopt adaptive banner sizing
|
|
154
|
+
|
|
155
|
+
Replace fixed full-width or smart-banner assumptions:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
const banner = Admob.createAdaptiveBanner({
|
|
159
|
+
adUnitId: Admob.TEST_ADAPTIVE_BANNER,
|
|
160
|
+
adaptiveType: Admob.ADAPTIVE_ANCHORED,
|
|
161
|
+
width: Ti.UI.FILL
|
|
162
|
+
})
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
On `loaded`, use `event.height` with `event.heightUnit`. Update both the banner host and the adjacent content inset. Collapse both on error and destruction.
|
|
166
|
+
|
|
167
|
+
Do not keep a fixed `50`, `90`, or device-specific height.
|
|
168
|
+
|
|
169
|
+
`ADAPTIVE_INLINE` and `maxHeight` work on iOS too. An application that branched on `Ti.Platform.osname` to keep inline banners off iOS can drop the branch.
|
|
170
|
+
|
|
171
|
+
## Adopt the banner lifecycle
|
|
172
|
+
|
|
173
|
+
Both standard and adaptive banners support:
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
banner.load()
|
|
177
|
+
banner.pause()
|
|
178
|
+
banner.resume()
|
|
179
|
+
banner.isLoaded()
|
|
180
|
+
banner.destroy()
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`destroy()` is terminal and idempotent. Remove JavaScript event listeners and the proxy from its parent when the owning placement closes.
|
|
184
|
+
|
|
185
|
+
The module pauses banners when the Android activity pauses or the iOS application enters the background. Remove any application code that duplicates those handlers. Keep calls for navigation changes the module cannot observe, such as hiding a tab or covering a window. See [Who pauses a banner](banners.md#who-pauses-a-banner).
|
|
186
|
+
|
|
187
|
+
Do not carry forward code that changes `visible`, opacity, height, or the banner host during pause/resume. TiAdMobUnified preserves the same visual slot and creative; navigation owns only the application pause cause.
|
|
188
|
+
|
|
189
|
+
Replace both historical aliases when practical:
|
|
190
|
+
|
|
191
|
+
```js
|
|
192
|
+
banner.destroyAdViewAndCancelRequest()
|
|
193
|
+
banner.destoyAdViewAndCancelRequest()
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
with:
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
banner.destroy()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Remove manual refresh timers
|
|
203
|
+
|
|
204
|
+
Delete `setTimeout`/`setInterval` banner renewal loops. Configure refresh in AdMob and let the native SDK own it.
|
|
205
|
+
|
|
206
|
+
The application issues the initial `load()`. Google Mobile Ads manages later refresh requests; TiAdMobUnified manages lifecycle.
|
|
207
|
+
|
|
208
|
+
## Adopt the fullscreen lifecycle
|
|
209
|
+
|
|
210
|
+
Interstitial, rewarded, and app open proxies share the same methods and event payloads on iOS and Android:
|
|
211
|
+
|
|
212
|
+
```js
|
|
213
|
+
fullscreen.load()
|
|
214
|
+
fullscreen.show()
|
|
215
|
+
fullscreen.isLoaded()
|
|
216
|
+
fullscreen.destroy()
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Calls to `load()` while a request, loaded ad, or presentation is active are ignored. Each native fullscreen ad is single-use. `destroy()` is terminal and idempotent, and emits `destroyed` once.
|
|
220
|
+
|
|
221
|
+
Common events include `adUnitId` and `adType`; failures add `error`, `message`, and `code`. Both platforms emit `opened` and `showed_fullscreen_content`. Rewarded value must be granted only from the `rewarded` event.
|
|
222
|
+
|
|
223
|
+
### App open
|
|
224
|
+
|
|
225
|
+
`createAppOpen()` returns a proxy on both platforms. Of the modules it replaces, `ti.admob` documents the iOS type without a factory, and `ti.android.admob` supplies an Android-only proxy. Applications previously had to implement the missing iOS support themselves.
|
|
226
|
+
|
|
227
|
+
It follows the fullscreen contract above, with one addition: an app open ad expires four hours after the request. Past that point `isLoaded()` reports `false` and `show()` emits `failed_to_show` with code `1`. See [The four hour window](fullscreen.md#the-four-hour-window).
|
|
228
|
+
|
|
229
|
+
## Mediation
|
|
230
|
+
|
|
231
|
+
Five optional complements carry AppLovin, Meta, InMobi, Unity and Liftoff dependencies on both platforms. Google Mobile Ads discovers their adapters; applications keep calling the core factories. ironSource mediation is deferred.
|
|
232
|
+
|
|
233
|
+
Availability probes remain in `ti.admob.unified` for portable diagnostics, and report `false` for every network when no complements are installed. Legacy provider consent setters are deprecated no-ops because UMP and each provider's current requirements must drive privacy configuration. Installing an adapter does not create an account or enable a mediation source: configure mappings and credentials in AdMob, then validate with Ad Inspector.
|
|
234
|
+
|
|
235
|
+
An application that serves AdMob demand only leaves the complements out and uses `Admob.initialize({})`, with no disabling flag. Including selected complements opts into automatic adapter discovery; no `enableMediation` flag is needed. An exceptional session that skips installed adapters is covered in the [initialization reference](api-reference.md#automatic-adapter-discovery).
|
|
236
|
+
|
|
237
|
+
## Development checklist
|
|
238
|
+
|
|
239
|
+
- Use the module's `TEST_*` constants.
|
|
240
|
+
- Keep production IDs disabled until physical validation is complete.
|
|
241
|
+
- Test consent accepted, rejected, not required, and previous-session states.
|
|
242
|
+
- Test ATT authorized, denied, and previously resolved on iOS.
|
|
243
|
+
- Test banner load, error collapse, rotation, background/resume, and repeated window close.
|
|
244
|
+
- Test interstitial, rewarded, and app open duplicate loads, show failures, close, reward delivery, and repeated destruction.
|
|
245
|
+
- Confirm no duplicate banners or retained listeners.
|
|
246
|
+
- Inspect requests with Ad Inspector.
|
|
247
|
+
- Inspect `getMediationStatus()` after `module_initialized`, and verify installed complements separately through package inventories and Ad Inspector.
|
|
248
|
+
- Run `npm test` and `./scripts/verify-artifacts.sh`.
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
## Corrections from internal audit builds
|
|
252
|
+
|
|
253
|
+
Boolean results and payload fields use JavaScript Booleans on both platforms; replace comparisons to numeric `0` or `1`. iOS load errors now use the shared error constants; presentation, UMP and Inspector codes remain domain-specific. Use the event name and the reference's error table when migrating code that compared raw NSError values.
|
|
254
|
+
|
|
255
|
+
Application volume now works on iOS using the same percentage string accepted on Android. Fullscreen configuration properties are mutable for subsequent loads on both platforms. Native helper/delegate methods and internal state from earlier iOS builds are no longer exposed as application APIs. Availability diagnostics require the adapter class, so a network SDK installed without its adapter reports `false`.
|