Language / Ngôn ngữ / भाषा: English | Tiếng Việt | हिन्दी
यह दस्तावेज़ Infinity products में ads integration के लिए partner teams का mandatory reference standard है। Ads से जुड़ा कोई भी बदलाव इसी base project में defined architecture, load/show flow, और gating rules के अनुसार होना चाहिए।
Example-AdLogic-Partner ecosystem के सभी Android apps के लिए template/base के रूप में design किया गया है। Partners को इस base को fork/clone करके यह सुनिश्चित करना चाहिए:
- वही Ads package structure (
AdRemoteConfig,RemoteConfigUtils,AdsManager,AdExtension) - वही config source flow (assets + Firebase Remote Config)
- native ad rendering के लिए वही LiveData observation pattern
- Language screen पर DevSetting के जरिए वही QA entry
लक्ष्य: app-to-app drift कम करना, maintainability बेहतर करना, audit आसान बनाना, और technical support को centralized रखना।
वर्तमान base flow — GlobalApp में early init, Splash में config sync, next-screen preload, AdsManager में centralized gating, और ERainAd.getShouldDisplay*(enableUaCheck) से organic handling — iterative optimization का परिणाम है:
- सही load timing
- UI jank कम
- offline / purchased स्थिति में safe fallback
- cohort-based display control
Partners core flow को modify नहीं करेंगे (जैसे AdsManager bypass करके SDK direct call करना, organic gating हटाना, या load/show order बदलना), जब तक Infinity technical team approval न दे।
नीचे दिए गए screens पहले से implement हैं और इनके load/show behavior, preload points, और gating conditions को preserve करना जरूरी है:
| Screen | Placements / behavior |
|---|---|
| Splash | inter_splash, preload native_language, open_resume config |
| Language | Native language/click, preload onboarding page 1, DevSetting (tvTitle) |
| Onboarding | Native page 1 & 4, native full, inter_onboarding, uninstall widget |
| Welcome / Resume | native_welcome, inter_welcome, ResumeAdsEntryRule |
Banner (Home + screens extending BaseActivityWithBanner) |
Normal / collapsible banner, reload by config |
UI customization के समय केवल layout/container बदलें। isEnable, purchase, network, और getShouldDisplay*(config.enableUaCheck) checks remove न करें।
किसी भी new custom screen (जो base में पहले से नहीं है) के लिए वही rule set लागू होगा:
ad_config.json/ad_config_debug.jsonमें placement keys जोड़ें औरAdRemoteConfigमें matching properties जोड़ें।AdsManagerमें load methods जोड़ें (native के लिएloadNativeInternal, interstitial के लिएload+showpattern)।- Activity/Fragment में
initViewsपर load करें (optional shortpostDelayed), LiveData observe करें, ad मिलने परpopulateNativeAdViewcall करें,nullहोने पर container hide करें। - sensitive placements (onboarding-like, welcome, home, permission, widget...) के लिए 100% mandatory:
ERainAd.getInstance().getShouldDisplay*(config.enableUaCheck)section 4 mapping के अनुसार लगाएं। - banner के लिए
BaseActivityWithBannerextend करें,BannerConfigconfigure करें,AdsManager.loadBannerके बाहर banner load न करें।
Detailed UI/Ads reference (CTA size, Done button delay, native placement by page):
Infinity UI Documentation — Language & Onboarding.
- Debug:
ad_config_debug.jsonread करें। - Release:
ad_config.jsonread करें, फिर optional override Firebase Remote Config (ad_remote_config) से लें।
GlobalApp.onCreate() में order (mandatory):
| Step | Call | Purpose |
|---|---|---|
| 1 | MobileAds.initialize(this) |
Google Mobile Ads SDK initialize |
| 2 | DevConfig.init(...) |
DevConfig UI — ads lib versions (§1.3 देखें) |
| 3 | initAdRemoteConfig() |
AdRemoteConfig.initializeFromAssets(this) |
| 4 | initAds() |
ERainAd + resume/inter rules (§1.5 देखें) |
| 5 | ResumeAdsEntryRule.shouldShowWelcomeOnResume() |
welcome flow हो तो AppLifecycleObserver register |
SplashActivity.checkRemoteConfigResult():- latest remote config apply:
AdRemoteConfig.initialize(this, RemoteConfigUtils.getAdRemoteConfig())
- latest remote config apply:
onCreate() में जल्दी call करें — initAdRemoteConfig() और initAds() से पहले। Version parameters BuildConfig से आते हैं (app/build.gradle में declare अनिवार्य — §1.4):
DevConfig.init(
context = this,
nkhStudioVersion = BuildConfig.ERAIN_STUDIO_VERSION,
playServicesAdsVersion = BuildConfig.PLAY_SERVICES_ADS_VERSION,
gdprModuleVersion = BuildConfig.GDPR_MODULE_VERSION
)| Parameter | BuildConfig field |
DevConfig UI पर |
|---|---|---|
nkhStudioVersion |
ERAIN_STUDIO_VERSION |
ERain Studio / ads module version |
playServicesAdsVersion |
PLAY_SERVICES_ADS_VERSION |
Google Play Services Ads version |
gdprModuleVersion |
GDPR_MODULE_VERSION |
GDPR module version |
LanguageActivity:mBinding.tvTitle.setOnAdminAdToggleListener()- QA यहां check कर सकता है: sdk versions, mediation, config id, ad id, reset organic।
app/build.gradleमें mandatory: DevConfig UI में version info सही दिखाने के लिए नीचे दिए गए 3buildConfigFieldlines (दोनोंdebugऔरreleaseमें) घोषित करना अनिवार्य है:buildConfigField "String", "ERAIN_STUDIO_VERSION", "\"$erain_studio_version\"" buildConfigField "String", "PLAY_SERVICES_ADS_VERSION", "\"$play_services_ads_version\"" buildConfigField "String", "GDPR_MODULE_VERSION", "\"$module_update_gdpr_version\""
DevConfig testing guide (PO / Tester): DevConfig Testing Guide
वर्तमान base में core integration GlobalApp.initAds() में implement है। नया app बनाते समय partners को यही pattern follow करना चाहिए:
- build type के अनुसार
environmentचुनें (ERainAdConfig.ENVIRONMENT_DEVELOP/ERainAdConfig.ENVIRONMENT_PRODUCTION)। mERainAdConfig = ERainAdConfig(this, environment)बनाएं।ERainAd.init(...)call से पहले required fields set करें:adjustConfigfacebookClientTokenadjustTokenTiktokintervalInterstitialAdidAdResume
ERainAd.getInstance().init(this, mERainAdConfig)call करें।- resume/inter के extra rules apply करें:
Admob.getInstance().setDisableAdResumeWhenClickAds(true)Admob.getInstance().setOpenActivityAfterShowInterAds(true)- excluded screens के लिए
AppOpenManager.getInstance().disableAppResumeWithActivity(...)।
Reference snippet:
private fun initAds() {
val environment =
if (BuildConfig.DEBUG) ERainAdConfig.ENVIRONMENT_DEVELOP else ERainAdConfig.ENVIRONMENT_PRODUCTION
mERainAdConfig = ERainAdConfig(this, environment)
mERainAdConfig.adjustConfig = AdjustConfig(true, resources.getString(R.string.adjust_token))
mERainAdConfig.facebookClientToken = resources.getString(R.string.facebook_client_token)
mERainAdConfig.adjustTokenTiktok = resources.getString(R.string.event_token)
mERainAdConfig.intervalInterstitialAd = 35
mERainAdConfig.idAdResume = ""
ERainAd.getInstance().init(this, mERainAdConfig)
}Note:
initAdRemoteConfig()कोinitAds()से पहले call करना चाहिए, और remote config sync फिर भीSplashActivityमेंRemoteConfigUtils.init(...)+AdRemoteConfig.initialize(...)से होता है।
- Inter Splash:
- Condition:
AdRemoteConfig.inter_splash.isEnable == trueऔर network available - API:
ERainAd.getInstance().loadSplashInterstitialAds(...) - successful load (
onAdLoaded) के बादnative_languagepreload
- Condition:
- Open Resume:
ResumeAdsEntryRule.shouldEnableOpenResume()से enable/disable
- Native language:
- Splash से preload:
AdsManager.loadNativeLanguage(...) - Click variant:
AdsManager.loadNativeLanguageClick(...)
- Splash से preload:
- onboarding page 1 के लिए early preload:
AdsManager.loadNativeOnboarding1(...)
AdsManager.loadNativeOnboarding4(...)AdsManager.loadNativeOnboardingFull(...)AdsManager.loadInterOnboarding(...), और onboarding completion परAdsManager.showInterOnboarding(...)
- Native welcome:
AdsManager.loadNativeWelcome(...), gate:getShouldDisplayNativeWelcomeBack(config.enableUaCheck)
- Inter welcome:
AdsManager.loadInterWelcome(...),AdsManager.showInterWelcome(...)- Welcome flow
AppLifecycleObserverद्वारा trigger होता है जबResumeAdsEntryRule.shouldShowWelcomeOnResume()औरgetShouldDisplayInterWelcomeBack(AdRemoteConfig.inter_welcome.enableUaCheck)allow करते हैं।
BaseActivityWithBanneruse करें।AdsManager.loadBanner(..., isCollapse = false)=> normal bannerAdsManager.loadBanner(..., isCollapse = true)=> collapsible banner (SDK expand/collapse behavior)- Reload interval:
reloadIntervalSeconds
AdsManager में ad तभी load होगा जब सभी conditions pass हों:
adUnitConfig.isEnable == true!AppPurchase.getInstance().isPurchased(...)- Network available
- mandatory organic-gated placements के लिए:
getShouldDisplay*(config.enableUaCheck) == true
कोई भी condition fail होने पर native LiveData null emit करेगा, इसलिए UI ad container hide करेगा।
Mandatory: नीचे दिए गए placements में से 100% पर SDK का
getShouldDisplay*check जरूरी है।
ParameterenableUaCheckहै —ad_config.json/ad_config_debug.jsonके placement config से आता है (AdUnitConfig.enableUaCheckमें map)।
यह organic/UA check flag है (ads config से force organic) —true/falsehard-code न करें; हमेशा उसी placement के config से लें जो load/show हो रहा है।
| Ad placement | Required SDK method | Default enable_ua_check in ad_config.json |
Param from ad_config | Code usage |
|---|---|---|---|---|
| NativeOnboardingFull1 | getShouldDisplayNativeOnboardingFull1(...) |
true |
config.enableUaCheck |
AdsManager.loadNativeOnboardingFull (+ OnBoardingActivity में full page insert) |
| NativeOnboardingFull2 | getShouldDisplayNativeOnboardingFull2(...) |
true |
config.enableUaCheck |
AdsManager.loadNativeOnboardingFull2 (+ OnBoardingActivity में full page insert) |
| NativeOnboardingNormal2 | getShouldDisplayNativeOnboardingNormal2(...) |
false |
config.enableUaCheck |
AdsManager.loadNativeOnboarding4 |
| NativeHome | getShouldDisplayNativeHome(...) |
false |
config.enableUaCheck |
AdsManager.loadNativeHome |
| NativePermission | getShouldDisplayNativePermission(...) |
false |
config.enableUaCheck |
AdsManager.loadNativePermission |
| InterOnboarding | getShouldDisplayInterOnboarding(...) |
true |
config.enableUaCheck |
AdsManager.loadInterOnboarding / showInterOnboarding |
| NativeWelcomeBack | getShouldDisplayNativeWelcomeBack(...) |
false |
config.enableUaCheck |
AdsManager.loadNativeWelcome |
| InterWelcomeBack | getShouldDisplayInterWelcomeBack(...) |
false |
config.enableUaCheck |
AppLifecycleObserver (welcome activity redirection) |
| WidgetUninstall | getShouldDisplayWidgetUninstall(...) |
false |
config.enableUaCheck |
OnBoardingActivity widget shortcut; loadNativeSurvey / loadNativeConfirmUninstall |
ad_config defaults: JSON declare करते समय ऊपर वाले column के default
enable_ua_checkset करें, जब तक Infinity अलग value न दे। उदाहरण: Full1/Full2/inter_onboardingdefaulttrue; बाकी placements defaultfalse।
हर placement के JSON में:
"native_onboarding_fullscreen_1_3": {
"id": "ca-app-pub-xxx/yyy",
"isEnable": true,
"enable_ua_check": true
}Code में:
val config = AdRemoteConfig.native_onboarding_fullscreen_1_3
ERainAd.getInstance().getShouldDisplayNativeOnboardingFull1(config.enableUaCheck)| JSON key | Kotlin field | Meaning |
|---|---|---|
enable_ua_check |
AdUnitConfig.enableUaCheck |
उस placement के लिए organic (UA) check on/off जब getShouldDisplay* call हो |
loadNativeInternal(
activity,
config,
layoutRes,
liveData,
ERainAd.getInstance().getShouldDisplayNativeOnboardingFull1(config.enableUaCheck)
)Compliant नहीं अगर:
- ऊपर की table में किसी placement पर
getShouldDisplay*skip करें। getShouldDisplay*(true/false)hard-code करें बजायconfig.enableUaCheckके।- गलत gate method इस्तेमाल करें (जैसे Full1 पर Normal2)।
Organic Ads SDK / growth logic से user classification है, जिसके लिए:
- कुछ users पर sensitive ad slots की frequency कम करना या disable करना
- retention, UX, और revenue का balance रखना
- हर screen rewrite किए बिना cohort rules लागू करना
इस app में कैसे काम करता है:
- app local rules से organic compute नहीं करता।
- app
ERainAd.getInstance().getShouldDisplay*(enableUaCheck)call करता है,enableUaCheckad_configसे आता है। - organic/cohort rules बदलने पर ये method results बदलते हैं और हर slot के load/show को सीधे affect करते हैं।
- DevSetting / Unlimited Ads +
reset organicQA को सभी ad placements + uninstall widget re-verify करने में मदद करते हैं।
if (AdRemoteConfig.inter_splash.isEnable && isNetwork(this)) {
ERainAd.getInstance().loadSplashInterstitialAds(
this, AdRemoteConfig.inter_splash.id, 30000, 5000, object : AdCallback() {
override fun onNextAction() { moveActivity() }
}
)
} else moveActivity()AdsManager.loadNativeOnboarding1(this, appSharedPref.firstOnBoarding, R.layout.layout_native_onboarding)
AdsManager.nativeOnboarding1AdLive.observe(this) { ad ->
if (ad == null) hideAd() else showAd(ad)
}AdsManager.loadInterOnboarding(this)
AdsManager.showInterOnboarding(this) {
goNextScreen()
}override val bannerConfig = BannerConfig(
adUnitConfig = AdRemoteConfig.banner_home,
isCollapse = false
)override val bannerConfig = BannerConfig(
adUnitConfig = AdRemoteConfig.banner_home,
isCollapse = true
)- Infinity UI Documentation — Language & Onboarding — UI, Remote Config, और ad-unit display conditions (placement/method names को इस document से cross-check करना चाहिए)।