Skip to content
Open
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
38 changes: 38 additions & 0 deletions .claude/conventions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
conventions:
- id: adapter-structure
description: >
Each network adapter lives under ThirdPartyAdapters/{Network}/ as a
Gradle Android Library module. The main adapter class implements Google
mediation interfaces. Supporting classes include Manager, Initializer,
and format-specific callback classes.
applies_to: "ThirdPartyAdapters/**/*.java"

- id: naming-conventions
description: >
Adapter main class: {Network}MediationAdapter. Initializer:
{Network}Initializer. Manager: {Network}Manager. Callback classes
named by format (e.g., {Network}RewardedAd, {Network}InterstitialAd).
All classes use Java naming conventions.
applies_to: "ThirdPartyAdapters/**/*.java"

- id: ad-format-support
description: >
Adapters support Rewarded Video, Interstitial, and Banner formats.
Each format has its own callback/listener class. Adapters may support
both legacy and new mediation framework interfaces.
applies_to: "ThirdPartyAdapters/**/*.java"

- id: version-management
description: >
Adapter versions encode the underlying SDK version plus an adapter
patch digit (e.g., 6.9.1.0). Version is declared in the adapter's
build.gradle and published via Maven/Bintray. CHANGELOG.md tracks
version history per adapter.
applies_to: "**/build.gradle"

- id: gradle-build
description: >
Each adapter is a Gradle Android Library module with its own
build.gradle. The root project uses AGP 3.5.4. Publishing
configuration targets Maven/Bintray repositories.
applies_to: "**/build.gradle"
23 changes: 23 additions & 0 deletions .claude/knowledge/adrs/001-google-mediation-interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ADR-001: Google Mediation Adapter Interface

## Status
Accepted

## Context
Google Mobile Ads SDK mediates ads from third-party networks on Android. Each network adapter must conform to Google's mediation interfaces so the Google SDK can load and display ads uniformly regardless of the underlying network.

## Decision
Adapters implement Google's mediation interfaces:
- `MediationInterstitialAdapter` for interstitial ads
- `MediationBannerAdapter` for banner ads
- `MediationRewardedVideoAdAdapter` for rewarded video ads
- Newer `Adapter` base class for the updated mediation framework

The main adapter class (`{Network}MediationAdapter`) serves as the entry point. It delegates to format-specific classes that handle loading, displaying, and callback forwarding for each ad type.

## Consequences
- Strict conformance to Google's interface is required; no custom extensions
- Google controls the adapter lifecycle (instantiation, initialization, ad requests)
- Format-specific classes keep the main adapter manageable
- Must map network-specific error codes to Google AdMob error codes
- Adapters are instantiated by reflection, requiring a no-arg constructor
21 changes: 21 additions & 0 deletions .claude/knowledge/adrs/002-legacy-and-new-framework.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# ADR-002: Dual Framework Support (Legacy and New)

## Status
Accepted

## Context
Google transitioned from a legacy mediation framework (individual format interfaces like `MediationInterstitialAdapter`) to a newer unified `Adapter` base class. During the transition period, adapters need to support both frameworks to maintain backward compatibility.

## Decision
Adapters support both the legacy and new mediation frameworks:
- **Legacy**: Implement `MediationInterstitialAdapter`, `MediationBannerAdapter`, `MediationRewardedVideoAdAdapter` directly
- **New**: Extend the `Adapter` base class and implement `MediationInterstitialAd`, `MediationBannerAd`, `MediationRewardedAd`

The main adapter class bridges both frameworks, delegating to appropriate format-specific classes depending on which framework path is invoked.

## Consequences
- Backward compatibility is maintained during the framework transition
- Increased code complexity from supporting two calling conventions
- Format-specific classes may have legacy and new variants
- Eventually legacy support can be removed once migration is complete
- Testing must cover both framework paths
22 changes: 22 additions & 0 deletions .claude/knowledge/adrs/003-singleton-initialization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ADR-003: Singleton Initialization Pattern (VungleInitializer)

## Status
Accepted

## Context
The Vungle SDK (and many other network SDKs) must be initialized exactly once before any ad requests. Multiple adapter instances for different ad formats may attempt initialization concurrently. The Google mediation SDK may create multiple adapter instances.

## Decision
A dedicated `VungleInitializer` singleton manages SDK initialization:
- Private constructor with static `getInstance()` access
- Thread-safe initialization state tracking
- Queues initialization callbacks when init is already in progress
- Caches the initialization result to immediately callback on subsequent requests
- `VungleManager` handles shared SDK state and placement management separately

## Consequences
- SDK is initialized exactly once regardless of how many adapter instances exist
- Concurrent initialization requests are safely queued
- Clear separation: Initializer handles init lifecycle, Manager handles ad state
- Singleton pattern makes unit testing harder (requires reset/mock capability)
- All adapter instances share the same initialization state
55 changes: 55 additions & 0 deletions .claude/knowledge/computed/adapter-class-index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Google Mobile Ads (GMA) — Vungle Android Mediation Adapter Class Index

## Adapter Entry Point

| Class | Superclass | Package |
|-------|-----------|---------|
| `VungleMediationAdapter` | `Adapter` (Google) | `com.google.ads.mediation.vungle` |

**Initialization**: `initialize(context, initConfig, callback)` → calls `VungleAds.init(context, appId)`
**Singleton**: `VungleInitializer` manages shared initialization state across all format instances

## Format Classes

| Format | Class | Google Interface |
|--------|-------|-----------------|
| Interstitial | `VungleInterstitialAdapter` | `MediationInterstitialAd` |
| Rewarded | `VungleRewardedAdapter` | `MediationRewardedAd` |
| Banner | `VungleBannerAdapter` | `MediationBannerAd` |

## VungleInitializer (Singleton)

```
VungleInitializer.getInstance()
└─ initialize(context, appId, callback)
├─ Already initialized → immediate callback
├─ Initializing → queue callback
└─ Not initialized → VungleAds.init() + queue callback
```

## Callback Mapping (Vungle → Google GMA)

| Vungle Callback | GMA Callback | Context |
|----------------|-------------|---------|
| `onAdLoaded(ad)` | `onSuccess(adapter)` | Load success |
| `onAdFailedToLoad(ad, error)` | `onFailure(adError)` | Load failure |
| `onAdStart(ad)` | `reportAdImpression()` | Impression |
| `onAdClicked(ad)` | `reportAdClicked()` | Click |
| `onAdEnd(ad)` | `onAdDismissedFullScreenContent()` | Fullscreen closed |
| `onAdRewarded(ad)` | `onUserEarnedReward(rewardItem)` | Reward granted |
| `onAdFailedToPlay(ad, error)` | `onAdFailedToShowFullScreenContent(error)` | Show failure |

## Bidding Support

- Implements `RtbAdapter` for real-time bidding
- `collectSignals(signalConfig, callback)` → `VungleAds.getBiddingToken(context)`
- `loadRtbInterstitialAd()` / `loadRtbRewardedAd()` / `loadRtbBannerAd()` for bid response loading

## Key Patterns

1. **Singleton VungleInitializer**: Thread-safe initialization with callback queuing, prevents duplicate init calls
2. **RtbAdapter**: Extends base `Adapter` with RTB signal collection for Google Open Bidding
3. **Error code mapping**: Vungle error codes mapped to `AdError` with Google-standard codes
4. **Banner size mapping**: Google `AdSize` → Vungle `BannerAdSize` via `VungleBannerAdSizeUtil`
5. **Server parameters**: App ID and placement ID extracted from `MediationConfiguration.getServerParameters()`
6. **Privacy**: GDPR/CCPA/COPPA forwarded via `VunglePrivacySettings` from mediation extras
16 changes: 16 additions & 0 deletions .claude/knowledge/computed/churn-leaders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Churn Leaders
# Auto-generated — do not edit manually

## Files With Most Lines Changed (last 90 days)

| Rank | File | Lines Added | Lines Removed | Net |
|------|------|------------|--------------|-----|
| - | `CLAUDE.md` | +39 | -0 | 39 |
| - | `.claude/conventions.yml` | +38 | -0 | 38 |
| - | `.claude/review-rules.yml` | +27 | -0 | 27 |
| - | `.claude/knowledge/adrs/001-google-mediation-interface.md` | +23 | -0 | 23 |
| - | `.claude/knowledge/adrs/003-singleton-initialization.md` | +22 | -0 | 22 |
| - | `.claude/knowledge/adrs/002-legacy-and-new-framework.md` | +21 | -0 | 21 |

---
_Generated: 2026-03-24 | Period: 2025-12-24 to 2026-03-24 | Commits: 1 | Authors: 0_
8 changes: 8 additions & 0 deletions .claude/knowledge/computed/co-change-clusters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Co-Change Clusters
# Auto-generated — do not edit manually

## Files That Frequently Change Together (last 90 days)


---
_Generated: 2026-03-24 | Period: 2025-12-24 to 2026-03-24 | Commits: 1 | Authors: 0_
10 changes: 10 additions & 0 deletions .claude/knowledge/computed/contributor-summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Contributor Summary
# Auto-generated — do not edit manually

## Top Contributors (last 90 days)

| Author | Commits | Files Touched |
|--------|---------|--------------|

---
_Generated: 2026-03-24 | Period: 2025-12-24 to 2026-03-24 | Commits: 1 | Authors: 0_
24 changes: 24 additions & 0 deletions .claude/knowledge/computed/git-intelligence.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"generated": "2026-03-23T00:00:00Z",
"period_days": 180,
"since": "2025-09-24",
"recent_activity": {
"total_commits": 1,
"unique_authors": 1,
"fix_bug_commits": 0,
"first_commit_date": "2026-03-20",
"last_commit_date": "2026-03-20",
"commits_per_month": {
"2026-03": 1
}
},
"top_authors": [
{"author": "Mian Leow", "commits": 1}
],
"file_churn": [
{"file": "CLAUDE.md", "commits": 1}, {"file": ".claude/review-rules.yml", "commits": 1}, {"file": ".claude/knowledge/adrs/003-singleton-initialization.md", "commits": 1}, {"file": ".claude/knowledge/adrs/002-legacy-and-new-framework.md", "commits": 1}, {"file": ".claude/knowledge/adrs/001-google-mediation-interface.md", "commits": 1}, {"file": ".claude/conventions.yml", "commits": 1}
],
"bug_hotspots": [

]
}
17 changes: 17 additions & 0 deletions .claude/knowledge/computed/hotspot-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Git Hotspot Map
# Auto-generated — do not edit manually
# Re-run: .claude/scripts/git-hotspots.sh

## Most Frequently Changed Files (last 90 days)

| Rank | File | Commits | Last Changed |
|------|------|---------|-------------|
| - | `CLAUDE.md` | 1 | 2026-03-20 |
| - | `.claude/review-rules.yml` | 1 | 2026-03-20 |
| - | `.claude/knowledge/adrs/003-singleton-initialization.md` | 1 | 2026-03-20 |
| - | `.claude/knowledge/adrs/002-legacy-and-new-framework.md` | 1 | 2026-03-20 |
| - | `.claude/knowledge/adrs/001-google-mediation-interface.md` | 1 | 2026-03-20 |
| - | `.claude/conventions.yml` | 1 | 2026-03-20 |

---
_Generated: 2026-03-24 | Period: 2025-12-24 to 2026-03-24 | Commits: 1 | Authors: 0_
8 changes: 8 additions & 0 deletions .claude/knowledge/computed/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Claude knowledge layer metadata
generated: 2026-03-23T00:00:00Z
source_commit: 71043b4dad7e87cf866e28783492471cdb8fca35
stale_if_older_than: 7d
artifacts:
git-intelligence.json: { bytes: 842, tokens: ~210 }
total_bytes: 842
total_tokens: ~210
27 changes: 27 additions & 0 deletions .claude/review-rules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
review_rules:
- path: "ThirdPartyAdapters/**/*.java"
rules:
- Adapter must implement the correct Google mediation interfaces for supported formats
- SDK initialization must go through the singleton Initializer class
- All ad callbacks must be invoked on the main thread
- Null checks required before invoking mediation callbacks
- Error handling must map network-specific errors to AdMob error codes

- path: "**/build.gradle"
rules:
- compileSdkVersion and targetSdkVersion must match project standards
- minSdkVersion must be 16 or as required by the network SDK
- Google Mobile Ads SDK dependency version must be compatible
- Network SDK dependency version must match adapter version scheme
- No snapshot dependencies in release configurations

- path: "ThirdPartyAdapters/**/Initializer*.java"
rules:
- Initializer must be a singleton (private constructor, static instance)
- Must handle concurrent initialization requests safely
- Must cache initialization state to avoid redundant init calls

- path: "**/CHANGELOG.md"
rules:
- Every version bump must have a corresponding CHANGELOG entry
- Entries should note SDK version updates and behavioral changes
39 changes: 39 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Google Ads Mobile Android Mediation

## Overview
Google-maintained Android mediation adapters for the Google Mobile Ads SDK. Contains 21 third-party network adapters enabling mediation through AdMob/Ad Manager.

## Language
- **Java** (100%)

## Build System
- **Gradle** with Android Gradle Plugin 3.5.4
- Android Library modules per adapter
- Maven/Bintray publishing for distribution

## Architecture
- Directory structure: `ThirdPartyAdapters/{Network}/` with adapter module
- Adapters implement Google mediation interfaces: `MediationInterstitialAdapter`, `MediationBannerAdapter`, `MediationRewardedVideoAdAdapter`
- Ad formats: Rewarded Video, Interstitial, Banner

## Vungle Adapter
- Main class: `VungleMediationAdapter`
- Supporting classes: `VungleManager` (SDK lifecycle), `VungleInitializer` (singleton init), format-specific callback classes
- Adapter version: 6.9.1.0
- Pattern: Adapter + Manager + Initializer + per-format callbacks

## Platform Requirements
- Target SDK: 29
- Min SDK: 16
- Google Mobile Ads SDK: 19.7.0

## Example App
- Sample adapter implementation
- Custom event example
- Test application for manual verification

## Key Conventions
- One module per network under `ThirdPartyAdapters/`
- Singleton initialization pattern via dedicated Initializer class
- Manager class handles shared SDK lifecycle
- Format-specific callback classes (not inline)