react-native-topon
v0.1.7
Published
topon sdk
Downloads
19
Readme
react-native-topon
React Native TurboModule 封装的 TopOn (Anythink) SDK 接入方案,支持激励视频、插屏、Banner、开屏、原生等广告能力。
环境要求
- Node.js ≥ 20(示例工程使用 Yarn 3)
- React Native ≥ 0.81(TurboModule 新架构)
- Android:AGP 8.7.x、compileSdk 36、minSdk 24
安装
yarn add react-native-topon安装后需要运行一次 Codegen 生成 TurboModule 绑定:
yarn react-native codegen快速开始
TopOn 模块分为两个层面:
- SDK:负责初始化、GDPR、日志开关等全局配置。
- RewardedVideo / Interstitial / Banner / Splash / Native:提供各广告位的加载、展示、状态查询方法。
import Topon, {
SDK,
RewardedVideo,
Interstitial,
Banner,
Splash,
Native,
NativeAdView,
ToponEvents,
} from 'react-native-topon';
import { NativeEventEmitter } from 'react-native';
// SDK 初始化
SDK.init('your-app-id', 'your-app-key');
// 订阅事件
const emitter = new NativeEventEmitter(Topon.NativeModule);
const subscription = emitter.addListener(ToponEvents.RewardedVideo.Loaded, payload => {
console.log('Rewarded loaded', payload.placementId);
});
// 激励广告示例
RewardedVideo.loadAd('placement-id', { userID: 'user-1' });
const isReady = await RewardedVideo.hasAdReady('placement-id');
if (isReady) {
RewardedVideo.showAd('placement-id');
}
const status = await RewardedVideo.checkAdStatus('placement-id');
console.log('Rewarded status', status?.isReady);
// 组件卸载时移除监听
subscription.remove();详细 API 请查看 src/index.tsx 中的导出定义,或参考下方表格。
支持的广告类型与平台
| 广告类型 | 目标平台 | 说明 | | --- | --- | --- | | RewardedVideo | Android / iOS | 激励视频,标准激励流程 | | Interstitial | Android / iOS | 插屏广告 | | Banner | Android / iOS | 横幅广告 | | Splash | Android / iOS | 开屏广告 | | Native | Android / iOS | 原生自渲染广告,需要自定义布局 |
各广告模块在 JS 侧的 API 形式保持一致(
loadAd/hasAdReady/showAd/checkAdStatus),便于横向复用。
开屏广告接入(Splash)
目标平台:Android / iOS
- 按照本 README 的 Android / iOS 集成说明,引入
AnyThinkSplash(iOS)或splash-tpn(Android)依赖。 - JS 侧调用方式与其他广告一致:先
loadAd,再判断hasAdReady,最后showAd。
import { Splash } from 'react-native-topon';
Splash.loadAd('splash-placement-id', {
tolerateTimeout: 5000,
});
const isReady = await Splash.hasAdReady('splash-placement-id');
if (isReady) {
Splash.showAd('splash-placement-id');
}- 事件回调使用
ToponEvents.Splash.*(Loaded/LoadFail/Timeout/Show/Click/Close),可按需监听首屏展示与超时等状态。
原生广告接入(Native)
目标平台:Android / iOS
- 按照本 README 的 Android / iOS 集成说明,引入
AnyThinkNative(iOS)或nativead-tpn(Android)依赖。 - 原生广告采用 自渲染布局:用
NativeAdView作为容器,自定义 RN 组件布局。 - 布局完成后,将各子组件的
viewTag传给Native.showAd进行绑定。
import React, { useRef } from 'react';
import { findNodeHandle, Image, Text } from 'react-native';
import { Native, NativeAdView } from 'react-native-topon';
const nativeViewRef = useRef<NativeAdView>(null);
const titleRef = useRef<Text>(null);
const descRef = useRef<Text>(null);
const iconRef = useRef<Image>(null);
const ctaRef = useRef<Text>(null);
Native.loadAd('native-placement-id', { width: 320, height: 250 });
const bindNativeAd = () => {
const viewRefs = {
parent: findNodeHandle(nativeViewRef.current) ?? 0,
title: findNodeHandle(titleRef.current) ?? 0,
desc: findNodeHandle(descRef.current) ?? 0,
icon: findNodeHandle(iconRef.current) ?? 0,
cta: findNodeHandle(ctaRef.current) ?? 0,
};
Native.showAd('native-placement-id', viewRefs);
};
return (
<NativeAdView ref={nativeViewRef} onLayout={bindNativeAd}>
<Image ref={iconRef} />
<Text ref={titleRef} />
<Text ref={descRef} />
<Text ref={ctaRef} />
</NativeAdView>
);- 若需要素材数据,可调用
Native.getAdMaterial,或监听ToponEvents.Native.Show回调中的adMaterial字段。 - 组件卸载时调用
Native.removeAd释放绑定。
API 总览
SDK
| 方法 | 说明 |
| --- | --- |
| init(appId, appKey) | 初始化 SDK,必须在所有广告调用前执行一次 |
| setLogDebug(isDebug) | 打开/关闭原生日志输出,便于调试 |
| getSDKVersionName() | 返回当前 TopOn SDK 版本号 |
| isCnSDK() | 判断是否为国内 SDK |
| setExcludeMyOfferPkgList(packages) | 排除 MyOffer 包名黑名单 |
| initCustomMap(customMap) / setPlacementCustomMap(placementId, map) | 设置全局或广告位级别的扩展参数 |
| setGDPRLevel(level) / getGDPRLevel() / getUserLocation() / showGDPRAuth() / showGDPRConsentDialog(appId) / showGDPRConsentSecondDialog(appId) / setUMPTestDeviceId(deviceId) | GDPR 相关 API |
| deniedUploadDeviceInfo(keys) | 拒绝上传指定设备信息字段 |
RewardedVideo / Interstitial
| 方法 | 说明 |
| --- | --- |
| loadAd(placementId, settings?) | 加载广告,settings 可包含 userID、media_ext、custom_rule 等 TopOn 字段 |
| showAd(placementId) / showAdInScenario(placementId, scenario) | 展示广告,可按需指定 scenario |
| hasAdReady(placementId) | 返回该广告位当前是否可播放 |
| checkAdStatus(placementId) | 返回 ToponAdStatus(isLoading、isReady、adInfo),便于诊断 |
建议在收到
Loaded事件后再调用hasAdReady或checkAdStatus,避免频繁轮询。
Banner
| 方法 | 说明 |
| --- | --- |
| loadAd(placementId, settings?) | 加载 Banner;settings 支持 width、height、adaptive_type 等键 |
| showAdInRectangle(placementId, rect) | 以 { x, y, width, height } 指定展示区域 |
| showAdInPosition(placementId, position) | position 取值 top/bottom |
| showAdInRectangleAndScenario / showAdInPositionAndScenario | 在指定场景中展示 |
| hideAd / reShowAd / removeAd | 控制 Banner 显示、隐藏与彻底移除 |
| hasAdReady / checkAdStatus | 查询加载状态信息 |
Splash
| 方法 | 说明 |
| --- | --- |
| loadAd(placementId, settings?) | 加载开屏;settings 支持 tolerateTimeout(毫秒)等字段 |
| showAd / showAdInScenario | 展示开屏,可按需指定 scenario |
| hasAdReady / checkAdStatus | 查询加载状态信息 |
Native
| 方法 | 说明 |
| --- | --- |
| loadAd(placementId, settings?) | 加载原生;settings 支持 width、height、adaptive_height 等 |
| showAd(placementId, viewRefs) / showAdInScenario | 绑定自渲染布局并展示(viewRefs 见下文) |
| hasAdReady / checkAdStatus | 查询加载状态信息 |
| getAdMaterial | 获取原生素材信息(JSON) |
| removeAd | 从容器中移除原生广告 |
Native viewRefs 说明
viewRefs 用于把原生广告素材绑定到你自定义的 RN 组件上:
parent:必填,NativeAdView容器的 viewTagtitle/desc/cta/icon/mainImage/adLogo/dislike:可选,对应素材展示控件
建议在布局完成后再调用
Native.showAd,例如在onLayout或requestAnimationFrame中获取 viewTag。
事件监听
TopOn 模块通过 ToponEvents 常量暴露所有回调,配合 NativeEventEmitter 使用即可:
import { NativeEventEmitter } from 'react-native';
import Topon, { ToponEvents } from 'react-native-topon';
const emitter = new NativeEventEmitter(Topon.NativeModule);
const subscriptions = [
emitter.addListener(ToponEvents.RewardedVideo.Loaded, payload => {
console.log('激励加载成功', payload.placementId);
}),
emitter.addListener(ToponEvents.RewardedVideo.LoadFail, payload => {
console.warn('激励加载失败', payload.errorMsg);
}),
emitter.addListener(ToponEvents.RewardedVideo.Close, payload => {
console.log('激励关闭', payload.placementId);
}),
];
// 组件卸载时清理
return () => subscriptions.forEach(sub => sub.remove());可监听的事件名称:
- RewardedVideo:
Loaded、LoadFail、PlayStart、PlayEnd、PlayFail、Close、Click、Reward - Interstitial:
Loaded、LoadFail、PlayStart、PlayEnd、PlayFail、Close、Click、Show - Banner:
Loaded、LoadFail、Close、Click、Show、Refresh、RefreshFail - Splash:
Loaded、LoadFail、Timeout、Show、Click、Close - Native:
Loaded、LoadFail、Show、Click、Close、VideoStart、VideoEnd、VideoProgress
事件回调默认携带 { placementId, adCallbackInfo? };失败类事件额外包含 errorMsg,原生 Show 回调额外包含 adMaterial(素材 JSON),具体类型定义请参考 ToponRewardedEventPayload 等 TypeScript 类型。
示例工程
仓库提供了一个最小示例(example workspace)。运行前先在 example/src/App.tsx 填写自身的 AppId / AppKey 以及广告位 ID:
SDK.init('your-app-id', 'your-app-key');
RewardedVideo.loadAd('reward-placement-id', {
userID: 'demo-user',
media_ext: 'demo',
});
Banner.loadAd('banner-placement-id', {
width: 320,
height: 50,
adaptive_type: 0,
});
Splash.loadAd('splash-placement-id', {
tolerateTimeout: 5000,
});
// 原生广告:先加载,再在自定义布局中绑定 viewRefs
Native.loadAd('native-placement-id', {
width: 320,
height: 250,
});
// 插屏广告需要真实的插屏位 ID
// Interstitial.loadAd('interstitial-placement-id');原生广告绑定自渲染布局示例:
import React, { useMemo, useRef } from 'react';
import { findNodeHandle, Image, Text } from 'react-native';
import { Native, NativeAdView } from 'react-native-topon';
const nativeViewRef = useRef<NativeAdView>(null);
const titleRef = useRef<Text>(null);
const descRef = useRef<Text>(null);
const iconRef = useRef<Image>(null);
const ctaRef = useRef<Text>(null);
const viewRefs = useMemo(() => ({
parent: findNodeHandle(nativeViewRef.current) ?? 0,
title: findNodeHandle(titleRef.current) ?? 0,
desc: findNodeHandle(descRef.current) ?? 0,
icon: findNodeHandle(iconRef.current) ?? 0,
cta: findNodeHandle(ctaRef.current) ?? 0,
}), []);
Native.showAd('native-placement-id', viewRefs);
return (
<NativeAdView ref={nativeViewRef}>
<Image ref={iconRef} />
<Text ref={titleRef} />
<Text ref={descRef} />
<Text ref={ctaRef} />
</NativeAdView>
);然后依次执行:
yarn install
yarn example # 启动 Metro
yarn run android --port=4321应用会在界面上输出各广告位的事件日志。若出现 Invalid placement,请检查后台状态与参数是否一致。
Android 集成说明
1. 仓库地址
TopOn 官方依赖托管在 overseas_sdk 仓库,宿主 App 的 android/build.gradle(Project 级)需要额外声明:
allprojects {
repositories {
maven { url "https://jfrog.anythinktech.com/artifactory/overseas_sdk" }
maven { url "https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea" } // 如使用 Mintegral
flatDir { dirs "$rootDir/libs" } // 若需手动放置本地 AAR
}
}2. 依赖管理
由于仓库样例处于离线环境,库模块默认引用了 reactnative_sdk_output/Android/bridge_android/library/anythink_reactnativejs_bridge.aar。在真实项目中请改为使用 TopOn 官方 Maven 依赖,例如:
dependencies {
implementation "com.anythink.sdk:core-tpn:6.5.10"
implementation "com.anythink.sdk:banner-tpn:6.5.10"
implementation "com.anythink.sdk:interstitial-tpn:6.5.10"
implementation "com.anythink.sdk:rewardedvideo-tpn:6.5.10"
implementation "com.anythink.sdk:nativead-tpn:6.5.10"
implementation "com.anythink.sdk:splash-tpn:6.5.10"
implementation "com.anythink.sdk:tramini-plugin-tpn:6.5.10"
// 广告网络适配器(示例)
implementation "com.anythink.sdk:adapter-tpn-admob:6.5.10"
implementation "com.google.android.gms:play-services-ads:24.4.0"
implementation "com.anythink.sdk:adapter-tpn-facebook:6.5.10"
implementation "com.facebook.android:audience-network-sdk:6.20.0"
// ... 根据后台配置决定
}⚠️ 请严格与 TopOn 后台配置保持一致;离线开发时,可将官方 SDK AAR 放入
android/libs并通过implementation files('libs/xxx.aar')引用。
如果集成 AdMob,请为宿主应用添加 com.google.android.gms.ads.APPLICATION_ID 元信息。调试阶段可使用 Google 提供的测试 ID:
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" />生产包请务必替换为自己的 AdMob App ID。
3. Manifest 配置
库模块会自动合并以下节点,如宿主 App 有自定义 application,请确保未被覆盖:
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
<meta-data
android:name="com.google.android.gms.ads.AD_MANAGER_APP"
android:value="true" />若还有其他渠道所需权限、provider、activity 等,请根据 TopOn 官方文档 合并到宿主工程。
4. 混淆与权限
TopOn 要求保留大量类与字段,请在宿主 App 的 proguard-rules.pro 中加入官方提供的 keep 配置,并在 AndroidManifest.xml 中声明网络、设备信息等必要权限,同样参考 TopOn 文档补全。
5. GDPR / UMP(Android)
如需对接 Google UMP,请完成以下步骤并确保网络可访问 Google 服务器:
- 引入 UMP 依赖
dependencies {
implementation("com.google.android.ump:user-messaging-platform:3.1.0")
}- 配置 AdMob App ID
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />- 混淆配置
-keep public class com.google.android.ump.*- 弹窗同意后再初始化
import { SDK } from 'react-native-topon';
await SDK.showGDPRConsentDialog('your-admob-app-id');
SDK.init('your-topon-app-id', 'your-topon-app-key');若需提供“撤消同意”的入口,可调用 SDK.showGDPRConsentSecondDialog(appId) 重新征求意见。
如果未集成 UMP SDK,
showGDPRConsentDialog会自动回退到 TopOn 自带 GDPR 弹窗。 若 TopOn SDK 未提供带回调的 GDPR 弹窗接口,调用会立即返回,此时不要依赖await等待用户操作。
调试弹窗
调试阶段可调用 SDK.setUMPTestDeviceId(deviceId)(仅 Android),设备 ID 可通过 logcat 里 addTestDeviceHashedId 获取:
SDK.setUMPTestDeviceId('your-device-id');
await SDK.showGDPRConsentDialog('your-admob-app-id');发布前请移除调试代码。
使用技巧
ADMOB_APP_ID(代码里传入)需要与AndroidManifest.xml的com.google.android.gms.ads.APPLICATION_ID保持一致,否则可能不弹窗。- 如未在 EEA/UK,且没有测试设备配置,UMP 会直接回调不弹窗属正常现象;建议先设置测试设备 ID 并重装应用。
- 已经同意过的设备可能不会再次弹窗,可清理应用数据或卸载重装测试。
- 若需强制 EEA 流程,可在宿主 App 的原生侧使用 UMP 调试地理位置配置(当前 RN 封装未提供该入口)。
showGDPRConsentDialog回调后再SDK.init,避免同意流程未完成就请求广告。
iOS 集成说明
- 进入示例或宿主 App 的
ios目录执行RCT_NEW_ARCH_ENABLED=1 pod install(或直接pod install),Topon.podspec会自动拉取AnyThinkSDK、AnyThinkRewardedVideo、AnyThinkInterstitial、AnyThinkBanner等依赖;如启用原生/开屏,请确认工程已包含AnyThinkNative/AnyThinkSplash相关 Pod。 - 在 JS 侧调用
SDK.init(appId, appKey)与 Android 保持一致,其他 API 亦共享同一套定义。 - 确保
Info.plist中包含NSUserTrackingUsageDescription(请求 IDFA 必须)以及宿主业务所需的权限、SKAdNetworkItems等配置,具体以 TopOn iOS 接入文档 为准。 - 若工程启用
use_frameworks!,请保持与 React Native 新架构兼容的配置(use_frameworks! :linkage => :static),避免 Pod 链接方式冲突。
iOS 与 Android 在事件名、回调入参上保持一致,所有广告能力均通过同一个 TurboModule 导出,示例应用可直接在 iOS 端运行验证。
开发与贡献
常用脚本:
yarn typecheck
yarn lint
yarn testLicense
MIT
