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
39 changes: 39 additions & 0 deletions .claude/conventions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
conventions:
- id: adapter-structure
description: >
Each network adapter lives under Adapters/{Network}/IS{Network}Adapter/
as an Android Library module. All adapters extend AbstractAdapter and
implement INetworkInitCallbackListener. Separate listener classes for
each ad format's load and play events.
applies_to: "Adapters/**/*.{java,kt}"

- id: naming-conventions
description: >
Adapter class: IS{Network}Adapter. Listener classes follow
IS{Network}{Format}Listener pattern (e.g., ISVungleRewardedVideoListener).
Java is the primary language; Kotlin used only for Pangle and Yahoo
adapters. Standard Android/Java naming conventions.
applies_to: "Adapters/**/*.{java,kt}"

- id: ad-format-support
description: >
All adapters must support three formats: Rewarded Video, Interstitial,
and Banner. Each format has distinct load and play listener classes.
The AbstractAdapter base class provides shared format registration
and lifecycle management.
applies_to: "Adapters/**/*.{java,kt}"

- id: version-management
description: >
Adapter versions are tracked per network. The adapter version and
underlying SDK version are declared in the adapter's build.gradle.
Version history is maintained in adapter-level documentation.
applies_to: "**/build.gradle"

- id: aar-build-output
description: >
The custom Gradle task createAAR builds release AAR artifacts and
places them in the ReleaseCandidates/ directory. This is the primary
build command: ./gradlew createAAR. AAR files are the distribution
format for adapters.
applies_to: "**/build.gradle"
22 changes: 22 additions & 0 deletions .claude/knowledge/adrs/001-abstract-adapter-pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ADR-001: AbstractAdapter Base Class Pattern

## Status
Accepted

## Context
Unity LevelPlay (ironSource) mediates ads from 10 network SDKs on Android. Each adapter must handle SDK initialization, ad format registration, and lifecycle management. Significant boilerplate is shared across all adapters.

## Decision
All network adapters extend the `AbstractAdapter` base class provided by the ironSource SDK:
- `AbstractAdapter` provides shared initialization lifecycle and format registration
- Each adapter implements `INetworkInitCallbackListener` for initialization callbacks
- The adapter class (`IS{Network}Adapter`) overrides methods for each supported ad format
- Initialization, ad loading, and ad display follow the template method pattern

## Consequences
- Consistent adapter structure across all 10 networks
- Shared initialization and lifecycle logic reduces duplication
- Adapters focus on network-specific integration code
- AbstractAdapter updates (from ironSource SDK) affect all adapters
- Must keep adapter implementations compatible with the base class contract
- New ad formats require AbstractAdapter support before adapters can implement them
22 changes: 22 additions & 0 deletions .claude/knowledge/adrs/002-listener-separation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ADR-002: Separate Load and Play Listeners Per Format

## Status
Accepted

## Context
Each ad format (Rewarded Video, Interstitial, Banner) has distinct lifecycle events. Some events occur during ad loading (success, failure) while others occur during ad playback/display (impression, click, close, reward). Combining these in the adapter class creates large, unwieldy files.

## Decision
Each ad format has two separate listener classes:
- **Load Listener** (`IS{Network}{Format}LoadListener`): Handles ad load success and failure callbacks
- **Play/Show Listener** (`IS{Network}{Format}Listener`): Handles ad display events (show, click, close, reward)

These listener classes are instantiated by the adapter and registered with the network SDK for their respective lifecycle phases.

## Consequences
- Clean separation between loading and display concerns
- Each listener class has a focused, single responsibility
- Adapter class orchestrates listeners but delegates callback handling
- More files per adapter (2 listeners x 3 formats = 6 listener classes)
- Listeners must hold references to the adapter or mediation callback interfaces
- Easier to test individual lifecycle phases in isolation
23 changes: 23 additions & 0 deletions .claude/knowledge/adrs/003-create-aar-task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ADR-003: Custom Gradle createAAR Build Task

## Status
Accepted

## Context
Adapter libraries need to be distributed as AAR (Android Archive) files for integration by publishers. The standard Gradle `assembleRelease` task produces AARs in individual module build directories, but a centralized output location simplifies release management and distribution.

## Decision
A custom Gradle task `createAAR` is defined that:
1. Builds all adapter modules in release configuration
2. Copies the resulting AAR files to a centralized `ReleaseCandidates/` directory
3. Names AAR files with adapter name and version for clarity

The build command is: `./gradlew createAAR`

## Consequences
- Single command builds all adapters for release
- Centralized output directory simplifies artifact collection
- AAR naming convention makes version identification easy
- ReleaseCandidates/ directory serves as the staging area for distribution
- Custom task must be maintained as adapters are added or removed
- Developers use this task instead of standard `assembleRelease` for releases
56 changes: 56 additions & 0 deletions .claude/knowledge/computed/adapter-class-index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# LevelPlay (ironSource) — Vungle Android Adapter Class Index

## Adapter Entry Point

| Class | Superclass | Package |
|-------|-----------|---------|
| `VungleAdapter` | `AbstractAdapter` | `com.ironsource.adapters.vungle` |

**Initialization**: `init(activity, appKey, userId)` → calls `VungleAds.init(context, appKey)`
**Network Key**: `"Vungle"` (registered in ironSource mediation)

## Format Classes

| Format | Class | Listener Interface |
|--------|-------|--------------------|
| Interstitial | `VungleInterstitialAdapter` | `InterstitialAdListener` |
| Rewarded | `VungleRewardedVideoAdapter` | `RewardedAdListener` |
| Banner | `VungleBannerAdapter` | `BannerAdListener` |

## Listener Classes (6 total)

| Listener | Delegates For | Key Callbacks |
|----------|--------------|---------------|
| `VungleInterstitialAdListener` | Interstitial load | `onAdLoaded`, `onAdFailedToLoad` |
| `VungleInterstitialAdShowListener` | Interstitial show | `onAdStart`, `onAdEnd`, `onAdClicked`, `onAdImpression` |
| `VungleRewardedAdListener` | Rewarded load | `onAdLoaded`, `onAdFailedToLoad` |
| `VungleRewardedAdShowListener` | Rewarded show | `onAdStart`, `onAdEnd`, `onAdClicked`, `onAdRewarded` |
| `VungleBannerAdListener` | Banner load | `onAdLoaded`, `onAdFailedToLoad` |
| `VungleBannerAdShowListener` | Banner show | `onAdImpression`, `onAdClicked` |

## Callback Mapping (Vungle → LevelPlay)

| Vungle Callback | LevelPlay Callback | Context |
|----------------|-------------------|---------|
| `onAdLoaded(ad)` | `onAdOpened(adInfo)` / `onAdReady()` | Load success |
| `onAdFailedToLoad(ad, error)` | `onAdLoadFailed(error)` | Load failure |
| `onAdStart(ad)` | `onAdShowSucceeded(adInfo)` | Fullscreen shown |
| `onAdImpression(ad)` | `onAdVisible(adInfo)` | Impression tracked |
| `onAdClicked(ad)` | `onAdClicked(adInfo)` | Click |
| `onAdEnd(ad)` | `onAdClosed(adInfo)` | Fullscreen closed |
| `onAdRewarded(ad)` | `onAdRewarded(adInfo)` | Reward granted |
| `onAdFailedToPlay(ad, error)` | `onAdShowFailed(error)` | Show failure |

## Bidding Support

- Implements `INetworkBiddingProvider` interface
- `collectBiddingData(context, params)` → calls `VungleAds.getBiddingToken(context)`
- Token passed to ironSource auction, bid payload returned via `serverData`

## Key Patterns

1. **Separate load/show listeners**: Each format has distinct listener for load vs show phase
2. **AdInfo wrapping**: Vungle ad objects wrapped into ironSource `AdInfo` for callback forwarding
3. **Singleton VungleAds**: Single initialization, placement IDs from server data
4. **Banner size mapping**: ironSource `ISBannerSize` → Vungle `BannerAdSize` (BANNER, MREC, LEADERBOARD)
5. **Privacy**: GDPR consent, CCPA via `VunglePrivacySettings`, COPPA via `setCoppa()`
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` | +40 | -0 | 40 |
| - | `.claude/conventions.yml` | +39 | -0 | 39 |
| - | `.claude/review-rules.yml` | +29 | -0 | 29 |
| - | `.claude/knowledge/adrs/003-create-aar-task.md` | +23 | -0 | 23 |
| - | `.claude/knowledge/adrs/002-listener-separation.md` | +22 | -0 | 22 |
| - | `.claude/knowledge/adrs/001-abstract-adapter-pattern.md` | +22 | -0 | 22 |

---
_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-create-aar-task.md", "commits": 1}, {"file": ".claude/knowledge/adrs/002-listener-separation.md", "commits": 1}, {"file": ".claude/knowledge/adrs/001-abstract-adapter-pattern.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-create-aar-task.md` | 1 | 2026-03-20 |
| - | `.claude/knowledge/adrs/002-listener-separation.md` | 1 | 2026-03-20 |
| - | `.claude/knowledge/adrs/001-abstract-adapter-pattern.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: 0363b552ca36e057c49585517300addd82af1255
stale_if_older_than: 7d
artifacts:
git-intelligence.json: { bytes: 826, tokens: ~206 }
total_bytes: 826
total_tokens: ~206
29 changes: 29 additions & 0 deletions .claude/review-rules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
review_rules:
- path: "Adapters/**/*.{java,kt}"
rules:
- Adapter must extend AbstractAdapter and implement INetworkInitCallbackListener
- All three ad formats (Rewarded Video, Interstitial, Banner) must be supported
- Load and play listeners must be separate classes per format
- SDK initialization must use the callback listener pattern
- All ad callbacks must be invoked on the main/UI thread
- Null safety checks required before invoking listener methods

- path: "**/build.gradle"
rules:
- minSdkVersion must be 16 or higher as required by the network SDK
- targetSdkVersion should be 30 or current project standard
- mediationsdk dependency version must be compatible with 7.2.4.1
- createAAR task must be present and correctly configured
- No snapshot dependencies in release builds

- path: "Adapters/**/*Listener*.{java,kt}"
rules:
- Listener classes must handle all callback methods for their format
- Load listeners handle ad load success/failure
- Play listeners handle ad show, click, close, and reward events
- Must not hold strong references that could cause memory leaks

- path: "ReleaseCandidates/**"
rules:
- Only AAR artifacts should be committed to this directory
- AAR filenames must include adapter name and version
40 changes: 40 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# LevelPlay Android Adapters

## Overview
Unity LevelPlay (ironSource) Android mediation adapters. Contains 10 network adapters for serving ads through the ironSource mediation platform.

## Languages
- **Java** (primary, 36 files) — most adapters
- **Kotlin** (8 files) — Pangle and Yahoo adapters only

## Build System
- **Gradle** with Android Gradle Plugin 4.2.0
- Android Library modules
- Custom `createAAR` Gradle task for building release artifacts
- Build output: `./gradlew createAAR` produces AARs in `ReleaseCandidates/` directory

## Architecture
- Directory structure: `Adapters/{Network}/IS{Network}Adapter/`
- All adapters extend `AbstractAdapter` base class
- Implement `INetworkInitCallbackListener` for SDK initialization
- Separate listener classes per ad format (load listener + play listener)

## Ad Formats
- Rewarded Video (all adapters)
- Interstitial (all adapters)
- Banner (all adapters)

## Vungle Adapter
- Adapter version: v4.3.36
- VungleAds SDK: 7.4.0

## Platform Requirements
- Target SDK: 30
- Min SDK: 16
- IronSource SDK (mediationsdk): 7.2.4.1

## Key Conventions
- Adapter naming: `IS{Network}Adapter`
- Listener separation: distinct load and play listener classes per format
- AbstractAdapter provides shared initialization and lifecycle
- AAR artifacts built via custom Gradle task