Skip to content

feat: Native ads support for React Native - #182

Open
elijahdev0 wants to merge 16 commits into
appodeal:masterfrom
elijahdev0:feat/native-ads
Open

feat: Native ads support for React Native#182
elijahdev0 wants to merge 16 commits into
appodeal:masterfrom
elijahdev0:feat/native-ads

Conversation

@elijahdev0

@elijahdev0 elijahdev0 commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Adds Native ads support to the React Native SDK (Android + iOS + JS) — the only Appodeal ad format that was missing from the RN bridge.

Two ways to render native ads:

  1. Stock templates — drop-in views (newsFeed / appWall / contentStream), same as the native Android/iOS SDKs
  2. Composable assets — AdMob-style JSX layout (AppodealNativeAdView + media/icon/title/description/CTA/attribution children) so apps can style native ads in React Native without custom native modules

API

Module

  • AppodealAdType.NATIVE
  • cacheNativeAds(count), getNativeAds(count), getAvailableNativeAdsCount(), destroyNativeAd(id)
  • setPreferredNativeContentType(type)
  • AppodealNativeEvents (onNativeLoaded, onNativeFailedToLoad, onNativeShown, onNativeClicked, onNativeExpired)

Stock template view

<AppodealNative adId={id} placement="default" adTemplate="contentStream" />

Composable (custom layout)

<AppodealNativeAdView adId={id} placement="default">
  <AppodealNativeMediaView style={...} />
  <AppodealNativeIconView style={...} />
  <AppodealNativeTitleView style={...} />
  <AppodealNativeDescriptionView style={...} />
  <AppodealNativeCallToActionView style={...} />
  <AppodealNativeAttributionView style={...} />
</AppodealNativeAdView>

Platform notes

  • Android: Appodeal.NATIVE, NativeCallbacks, ad store, stock NativeAdView* templates + composable NativeAdView with asset binding
  • iOS: APDNativeAdQueue store + getViewForPlacement / custom asset views

Test plan

  • Initialize with AppodealAdType.NATIVE on Android/iOS
  • cacheNativeAdsonNativeLoadedgetNativeAds(1) returns metadata
  • <AppodealNative adId=... adTemplate="contentStream" /> shows a stock template
  • <AppodealNativeAdView> + asset children render a custom layout
  • Existing interstitial / rewarded / banner / MREC still work

Roo and others added 16 commits July 30, 2026 16:45
Expose Appodeal Native (the only format missing from the RN plugin):
AppodealAdType.NATIVE, getNativeAds/cacheNativeAds APIs, native events,
and AppodealNative template view on both platforms.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
bob lib/ is not produced on yarn git install; Metro can consume src directly.

Co-authored-by: Cursor <cursoragent@cursor.com>
…return

Nullable NativeAd? overrides; getNativeAds returns { ads: [...] } WritableMap.

Co-authored-by: Cursor <cursoragent@cursor.com>
Fabric codegen emits the prop as a C++ field; `template` is a reserved
keyword and breaks clang (`std::string template{}`).

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
ReactViewGroup was not measuring children (unlike banner/MREC), and
registerView often failed canShow under ReactContext — templates stayed GONE.

Co-authored-by: Cursor <cursoragent@cursor.com>
Unregister before rebind, retry canShow/size/Activity failures, notify views
on resume, unbind on destroyNativeAd, and emit per-view load/fail events.

Co-authored-by: Cursor <cursoragent@cursor.com>
Stock templates registered then got destroyed/blank in RN. Bind title/CTA/
media on a custom NativeAdView, stop recreate-after-bind races, single-flight binds.

Co-authored-by: Cursor <cursoragent@cursor.com>
Nesting NativeAdView inside ReactViewGroup left a GONE/empty host in the
UI hierarchy (banner WebView children rendered; native did not). Match the
official Appodeal Android demo: the host IS NativeAdViewContentStream and
registerView runs on self.

Co-authored-by: Cursor <cursoragent@cursor.com>
NativeAdViewContentStream is final and cannot be subclassed. Host is a
VISIBLE FrameLayout; template is added as a MATCH_PARENT child with
visibility forced VISIBLE before registerView (same attach pattern as
the working banner bridge).

Co-authored-by: Cursor <cursoragent@cursor.com>
Logs showed registerView=true but childSize=0x0, so Appodeal reported
"ad not visible globally". RN does not lay out non-RN children; apply the
same measureAndLayout path used by the working banner/MREC views.

Co-authored-by: Cursor <cursoragent@cursor.com>
Stock contentStream is a horizontal news layout and looks broken in
portrait grid cells. gridCard is a custom NativeAdView: media ~56% top,
icon/title/body, then CTA — same structure as the previous AdMob card.

Co-authored-by: Cursor <cursoragent@cursor.com>
Stock templates stay newsFeed/appWall/contentStream. Custom layouts use
AppodealNativeAdView + asset children on Android and iOS (AdMob-style JSX).

Co-authored-by: Cursor <cursoragent@cursor.com>
JavaBean setters like setMediaView do not resolve on a Kotlin subclass;
use mediaView/iconView/titleView property assignment instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
Appodeal's NativeAdView Kotlin metadata is obfuscated, so setMediaView /
mediaView= are unresolved from a Kotlin subclass. Call the public JVM
setters from Java instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant