android-reverse-engineering.../plugins/android-reverse-engineering/skills/ad-analysis/references/ad-format-patterns.md

248 lines
6.9 KiB
Markdown

# Ad Format Patterns
Code patterns for each ad format across major SDKs — how to identify banner, interstitial, rewarded, native, and app-open ads in decompiled code.
## Banner Ads
Small ads displayed within the app UI, typically at top or bottom of screen.
### Lifecycle
1. Create ad view (XML layout or programmatic)
2. Set ad unit ID
3. Load ad request
4. Ad displays inline — auto-refreshes periodically
### SDK-specific patterns
**AdMob**:
```java
AdView adView = new AdView(context);
adView.setAdSize(AdSize.BANNER); // or LARGE_BANNER, MEDIUM_RECTANGLE, FULL_BANNER, LEADERBOARD
adView.setAdUnitId("ca-app-pub-XXXXX/YYYYY");
adView.loadAd(new AdRequest.Builder().build());
```
**Unity Ads**:
```java
BannerView bannerView = new BannerView(activity, "placement_id", new UnityBannerSize(320, 50));
bannerView.load();
```
**IronSource**:
```java
IronSource.loadBanner(bannerLayout, "placement_name");
// or LevelPlay:
LevelPlayBannerAdView banner = new LevelPlayBannerAdView(context, "ad_unit_id");
banner.loadAd();
```
**AppLovin MAX**:
```java
MaxAdView adView = new MaxAdView("ad_unit_id", context);
adView.loadAd();
adView.startAutoRefresh();
```
**Meta AN**:
```java
AdView adView = new AdView(context, "placement_id", AdSize.BANNER_HEIGHT_50);
adView.loadAd();
```
### Grep for all banners
```bash
grep -rn 'AdView\|BannerView\|AdSize\.\|BANNER\|loadBanner\|IronSourceBannerLayout\|MaxAdView\|MBBannerView\|PAGBannerAd\|InMobiBanner' "$SOURCE_DIR"
```
---
## Interstitial Ads
Full-screen ads shown at natural transition points (level complete, between pages).
### Lifecycle
1. Load ad in advance (preload)
2. Check if ad is ready
3. Show ad at transition point
4. Handle close callback → resume app flow
### SDK-specific patterns
**AdMob**:
```java
InterstitialAd.load(context, "ca-app-pub-XXXXX/YYYYY", adRequest,
new InterstitialAdLoadCallback() {
@Override public void onAdLoaded(InterstitialAd ad) { /* cache */ }
@Override public void onAdFailedToLoad(LoadAdError error) { /* retry */ }
});
// Show:
interstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() { ... });
interstitialAd.show(activity);
```
**Unity Ads**:
```java
UnityAds.load("placement_id", new IUnityAdsLoadListener() { ... });
UnityAds.show(activity, "placement_id", new IUnityAdsShowListener() { ... });
```
**IronSource**:
```java
IronSource.loadInterstitial();
if (IronSource.isInterstitialReady()) {
IronSource.showInterstitial("placement_name");
}
```
**AppLovin MAX**:
```java
MaxInterstitialAd interstitialAd = new MaxInterstitialAd("ad_unit_id", activity);
interstitialAd.loadAd();
interstitialAd.showAd();
```
### Grep for all interstitials
```bash
grep -rn 'InterstitialAd\|showInterstitial\|loadInterstitial\|MaxInterstitialAd\|isInterstitialReady\|FullScreenContentCallback\|TTFullScreenVideoAd\|PAGInterstitialAd' "$SOURCE_DIR"
```
---
## Rewarded Ads
Full-screen ads that give the user an in-app reward for watching.
### Lifecycle
1. Load ad in advance
2. Show ad when user opts in (e.g., "Watch ad for extra life")
3. User watches ad to completion
4. Reward callback fires → grant reward
5. Handle incomplete views (user skipped)
### SDK-specific patterns
**AdMob**:
```java
RewardedAd.load(context, "ca-app-pub-XXXXX/YYYYY", adRequest,
new RewardedAdLoadCallback() {
@Override public void onAdLoaded(RewardedAd ad) { /* cache */ }
});
// Show:
rewardedAd.show(activity, new OnUserEarnedRewardListener() {
@Override public void onUserEarnedReward(RewardItem reward) {
int amount = reward.getAmount();
String type = reward.getType();
}
});
```
**Unity Ads**:
```java
// Same load/show as interstitial, but placement configured as rewarded on dashboard
UnityAds.load("rewarded_placement", loadListener);
UnityAds.show(activity, "rewarded_placement", showListener);
// Reward granted in onUnityAdsShowComplete with UnityAds.UnityAdsShowCompletionState.COMPLETED
```
**IronSource**:
```java
// Auto-loaded by default
if (IronSource.isRewardedVideoAvailable()) {
IronSource.showRewardedVideo("placement_name");
}
// Reward in RewardedVideoListener.onRewardedVideoAdRewarded(Placement placement)
```
**AppLovin MAX**:
```java
MaxRewardedAd rewardedAd = MaxRewardedAd.getInstance("ad_unit_id", activity);
rewardedAd.loadAd();
rewardedAd.showAd(); // reward via MaxRewardedAdListener.onUserRewarded(MaxAd, MaxReward)
```
### Grep for all rewarded
```bash
grep -rn 'RewardedAd\|RewardedVideo\|showRewardedVideo\|OnUserEarnedRewardListener\|RewardItem\|MaxRewardedAd\|TTRewardVideoAd\|PAGRewardedAd\|MBRewardVideoHandler' "$SOURCE_DIR"
```
---
## Native Ads
Ads that match the app's look and feel, rendered with custom templates.
### Lifecycle
1. Create ad loader with ad unit ID
2. Load ad
3. Receive native ad object with assets (headline, body, image, CTA, icon)
4. Inflate custom layout and bind assets
5. Register ad view for impression/click tracking
### SDK-specific patterns
**AdMob**:
```java
AdLoader adLoader = new AdLoader.Builder(context, "ca-app-pub-XXXXX/YYYYY")
.forNativeAd(nativeAd -> { /* bind to NativeAdView */ })
.withNativeAdOptions(new NativeAdOptions.Builder().build())
.build();
adLoader.loadAd(new AdRequest.Builder().build());
```
**Meta AN**:
```java
NativeAd nativeAd = new NativeAd(context, "placement_id");
nativeAd.loadAd(nativeAd.buildLoadAdConfig()
.withAdListener(new NativeAdListener() { ... })
.build());
```
**AppLovin MAX**:
```java
MaxNativeAdLoader nativeAdLoader = new MaxNativeAdLoader("ad_unit_id", context);
nativeAdLoader.setNativeAdListener(new MaxNativeAdListener() { ... });
nativeAdLoader.loadAd();
```
### Grep for all native
```bash
grep -rn 'NativeAd\|NativeAdView\|NativeAdLoader\|AdLoader\.Builder\|NativeBannerAd\|NativeAdLayout\|MaxNativeAdLoader\|InMobiNative\|VungleNativeAd' "$SOURCE_DIR"
```
---
## App Open Ads
Full-screen ads shown when the app is foregrounded (cold start or resume from background).
### Lifecycle
1. Preload ad during app initialization or background
2. On app foreground, check if ad is available and not expired
3. Show ad before the main content appears
4. Handle close callback → show app content
### Pattern (AdMob-specific)
```java
AppOpenAd.load(context, "ca-app-pub-XXXXX/YYYYY", adRequest,
AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
new AppOpenAd.AppOpenAdLoadCallback() {
@Override public void onAdLoaded(AppOpenAd ad) { /* cache with timestamp */ }
});
// Show on foreground:
appOpenAd.show(activity);
```
Common implementation pattern uses `Application.ActivityLifecycleCallbacks` to detect foreground transitions:
```java
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override public void onActivityStarted(Activity activity) {
// Show app open ad if available
}
});
```
### Grep for app open
```bash
grep -rn 'AppOpenAd\|AppOpenAdLoadCallback\|APP_OPEN_AD\|AppOpenAdManager\|appOpenAd' "$SOURCE_DIR"
```