@24jieqi/react-native-brayant-ad 0.1.24 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +321 -3
- package/android/src/main/java/com/brayantad/AdManager.java +68 -0
- package/android/src/main/java/com/brayantad/BrayantAdPackage.java +2 -0
- package/android/src/main/java/com/brayantad/dy/DyADCore.java +9 -0
- package/android/src/main/java/com/brayantad/dy/banner/BannerAdModule.java +175 -0
- package/android/src/main/java/com/brayantad/dy/banner/view/BannerAdView.java +11 -0
- package/android/src/main/java/com/brayantad/dy/splash/SplashAdModule.java +155 -0
- package/android/src/main/java/com/brayantad/dy/splash/activity/SplashActivity.java +20 -5
- package/lib/commonjs/dy/api/AdManager.js +15 -1
- package/lib/commonjs/dy/api/AdManager.js.map +1 -1
- package/lib/commonjs/dy/api/SplashAd.js +29 -1
- package/lib/commonjs/dy/api/SplashAd.js.map +1 -1
- package/lib/commonjs/index.js +24 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/dy/api/AdManager.js +14 -1
- package/lib/module/dy/api/AdManager.js.map +1 -1
- package/lib/module/dy/api/SplashAd.js +26 -1
- package/lib/module/dy/api/SplashAd.js.map +1 -1
- package/lib/module/index.js +3 -3
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/dy/api/AdManager.d.ts +8 -1
- package/lib/typescript/src/dy/api/AdManager.d.ts.map +1 -1
- package/lib/typescript/src/dy/api/SplashAd.d.ts +30 -1
- package/lib/typescript/src/dy/api/SplashAd.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/dy/api/AdManager.ts +14 -1
- package/src/dy/api/SplashAd.ts +49 -1
- package/src/index.tsx +16 -2
package/README.md
CHANGED
|
@@ -98,9 +98,47 @@ EmuAnim = 'default' | 'none' | 'catalyst' | 'slide' | 'fade';
|
|
|
98
98
|
| codeid | 广告位id | string | - | 是 |
|
|
99
99
|
| anim | 广告进入方式 | EmuAnim | default | 否 |
|
|
100
100
|
|
|
101
|
+
### preloadSplashAd (Android 推荐)
|
|
102
|
+
|
|
103
|
+
**Android 端推荐使用预加载方式,可避免启动页结束后出现白屏。**
|
|
104
|
+
|
|
105
|
+
在应用启动时(init 之后)预加载开屏广告,展示时直接使用已加载的广告。
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
// 预加载开屏广告
|
|
109
|
+
await preloadSplashAd({ codeid: 'your_code_id' });
|
|
110
|
+
|
|
111
|
+
// 展示广告(使用预加载的广告,无白屏)
|
|
112
|
+
const splashAd = dyLoadSplashAd({ codeid: 'your_code_id' });
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
| 参数 | 说明 | 类型 | 默认值 | 是否必填 |
|
|
116
|
+
| ------ | -------- | ------ | ------ | -------- |
|
|
117
|
+
| codeid | 广告位id | string | - | 是 |
|
|
118
|
+
|
|
119
|
+
### hasPreloadedSplashAd
|
|
120
|
+
|
|
121
|
+
检查是否有预加载的广告可用(Android)。
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
const { hasAd, status } = await hasPreloadedSplashAd();
|
|
125
|
+
// hasAd: boolean - 是否有可用的预加载广告
|
|
126
|
+
// status: number - 预加载状态 (0:未加载 1:加载中 2:成功 3:失败)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### clearPreloadedSplashAd
|
|
130
|
+
|
|
131
|
+
清除预加载的广告缓存(Android)。
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
clearPreloadedSplashAd();
|
|
135
|
+
```
|
|
136
|
+
|
|
101
137
|
## 如何使用
|
|
102
138
|
|
|
103
|
-
|
|
139
|
+
### 基础用法(实时加载)
|
|
140
|
+
|
|
141
|
+
> 注意:这种方式在 Android 端可能会出现白屏
|
|
104
142
|
|
|
105
143
|
```tsx
|
|
106
144
|
import { dyLoadSplashAd } from '@24jieqi/react-native-brayant-ad';
|
|
@@ -142,6 +180,123 @@ const ScrenPage = () => {
|
|
|
142
180
|
};
|
|
143
181
|
```
|
|
144
182
|
|
|
183
|
+
### 推荐用法(预加载 - Android)
|
|
184
|
+
|
|
185
|
+
**Android 端推荐使用预加载方式,避免启动页到广告之间出现白屏。**
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
import {
|
|
189
|
+
init,
|
|
190
|
+
preloadSplashAd,
|
|
191
|
+
hasPreloadedSplashAd,
|
|
192
|
+
dyLoadSplashAd,
|
|
193
|
+
} from '@24jieqi/react-native-brayant-ad';
|
|
194
|
+
import { useEffect } from 'react';
|
|
195
|
+
|
|
196
|
+
const App = () => {
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
const initialize = async () => {
|
|
199
|
+
// 1. 初始化 SDK
|
|
200
|
+
await init({
|
|
201
|
+
appid: 'your_app_id',
|
|
202
|
+
app: '应用名称',
|
|
203
|
+
debug: false,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// 2. Android: 预加载开屏广告(避免白屏)
|
|
207
|
+
if (Platform.OS === 'android') {
|
|
208
|
+
await preloadSplashAd({ codeid: 'your_splash_code_id' });
|
|
209
|
+
console.log('开屏广告预加载完成');
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
initialize();
|
|
214
|
+
}, []);
|
|
215
|
+
|
|
216
|
+
// 3. 展示开屏广告(Android使用预加载,iOS实时加载)
|
|
217
|
+
const showSplash = async () => {
|
|
218
|
+
// 检查预加载状态(可选)
|
|
219
|
+
if (Platform.OS === 'android') {
|
|
220
|
+
const { hasAd } = await hasPreloadedSplashAd();
|
|
221
|
+
console.log('是否有预加载广告:', hasAd);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const splashAd = dyLoadSplashAd({
|
|
225
|
+
codeid: 'your_splash_code_id',
|
|
226
|
+
anim: 'default',
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
splashAd.subscribe('onAdShow', (event) => {
|
|
230
|
+
console.log('广告展示', event);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
splashAd.subscribe('onAdClose', (event) => {
|
|
234
|
+
console.log('广告关闭', event);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
splashAd.subscribe('onAdError', (error) => {
|
|
238
|
+
console.log('广告错误', error);
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
// ...
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 在应用启动时自动展示开屏广告
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import { init, preloadSplashAd, dyLoadSplashAd } from '@24jieqi/react-native-brayant-ad';
|
|
252
|
+
import { hide } from 'react-native-bootsplash';
|
|
253
|
+
|
|
254
|
+
const SplashAdManager = () => {
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
const showSplashAdOnLaunch = async () => {
|
|
257
|
+
try {
|
|
258
|
+
// 1. 初始化广告 SDK
|
|
259
|
+
await init({ appid: 'your_app_id', app: '应用名称' });
|
|
260
|
+
|
|
261
|
+
// 2. Android: 预加载广告
|
|
262
|
+
if (Platform.OS === 'android') {
|
|
263
|
+
await preloadSplashAd({ codeid: 'your_splash_code_id' });
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// 3. 展示广告(Android使用预加载,无白屏)
|
|
267
|
+
const splashAd = dyLoadSplashAd({
|
|
268
|
+
codeid: 'your_splash_code_id',
|
|
269
|
+
anim: 'fade',
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
splashAd.subscribe('onAdShow', () => {
|
|
273
|
+
console.log('广告展示');
|
|
274
|
+
// Android: 此时可以隐藏启动页(广告已准备好)
|
|
275
|
+
hide({ fade: true });
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
splashAd.subscribe('onAdClose', () => {
|
|
279
|
+
console.log('广告关闭');
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
splashAd.subscribe('onAdError', (error) => {
|
|
283
|
+
console.log('广告加载失败', error);
|
|
284
|
+
// 出错时也要隐藏启动页
|
|
285
|
+
hide({ fade: true });
|
|
286
|
+
});
|
|
287
|
+
} catch (error) {
|
|
288
|
+
console.error('广告初始化失败:', error);
|
|
289
|
+
hide({ fade: true });
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
showSplashAdOnLaunch();
|
|
294
|
+
}, []);
|
|
295
|
+
|
|
296
|
+
return null;
|
|
297
|
+
};
|
|
298
|
+
```
|
|
299
|
+
|
|
145
300
|
# 2. 激励视频
|
|
146
301
|
|
|
147
302
|
## API
|
|
@@ -348,6 +503,52 @@ const RewardVideoPage = () => {
|
|
|
348
503
|
|
|
349
504
|
# 5. Banner广告
|
|
350
505
|
|
|
506
|
+
> 注意:Banner广告目前仅支持Android平台
|
|
507
|
+
|
|
508
|
+
## API
|
|
509
|
+
|
|
510
|
+
### preloadBannerAd
|
|
511
|
+
|
|
512
|
+
预加载 Banner 广告(Android 专用)
|
|
513
|
+
|
|
514
|
+
在组件渲染前调用,提前加载广告数据,减少白屏时间。预加载的广告会缓存 5 分钟,过期后自动失效。
|
|
515
|
+
|
|
516
|
+
| 参数 | 说明 | 类型 | 默认值 | 是否必填 |
|
|
517
|
+
| -------- | ------------ | ------ | ------ | -------- |
|
|
518
|
+
| codeid | 广告位 ID | string | - | 是 |
|
|
519
|
+
| adWidth | 广告宽度(dp) | number | 320 | 否 |
|
|
520
|
+
| adHeight | 广告高度(dp) | number | 50 | 否 |
|
|
521
|
+
|
|
522
|
+
```tsx
|
|
523
|
+
import { NativeModules } from 'react-native';
|
|
524
|
+
const { BannerAdModule } = NativeModules;
|
|
525
|
+
|
|
526
|
+
// 在页面进入前预加载
|
|
527
|
+
useEffect(() => {
|
|
528
|
+
BannerAdModule.preloadBannerAd({
|
|
529
|
+
codeid: 'your_codeid',
|
|
530
|
+
adWidth: 320,
|
|
531
|
+
adHeight: 50,
|
|
532
|
+
});
|
|
533
|
+
}, []);
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### hasPreloadedBannerAd
|
|
537
|
+
|
|
538
|
+
检查是否有预加载的 Banner 广告
|
|
539
|
+
|
|
540
|
+
```tsx
|
|
541
|
+
const hasCache = await BannerAdModule.hasPreloadedBannerAd('your_codeid');
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### clearPreloadedBannerAd
|
|
545
|
+
|
|
546
|
+
清除预加载的 Banner 广告缓存
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
BannerAdModule.clearPreloadedBannerAd();
|
|
550
|
+
```
|
|
551
|
+
|
|
351
552
|
## 组件
|
|
352
553
|
|
|
353
554
|
### BannerAdView
|
|
@@ -366,10 +567,10 @@ const RewardVideoPage = () => {
|
|
|
366
567
|
| onAdShow | 广告展示事件 | Function | - | 否 |
|
|
367
568
|
| onAdDislike | 用户不感兴趣事件 | Function | - | 否 |
|
|
368
569
|
|
|
369
|
-
> 注意:Banner广告目前仅支持Android平台
|
|
370
|
-
|
|
371
570
|
## 使用
|
|
372
571
|
|
|
572
|
+
### 基础用法
|
|
573
|
+
|
|
373
574
|
```tsx
|
|
374
575
|
import { BannerAdView, init } from '@24jieqi/react-native-brayant-ad';
|
|
375
576
|
import { useEffect, useState } from 'react';
|
|
@@ -418,8 +619,87 @@ const BannerAdPage = () => {
|
|
|
418
619
|
};
|
|
419
620
|
```
|
|
420
621
|
|
|
622
|
+
### 推荐用法(预加载)
|
|
623
|
+
|
|
624
|
+
```tsx
|
|
625
|
+
import { BannerAdView } from '@24jieqi/react-native-brayant-ad';
|
|
626
|
+
import { NativeModules } from 'react-native';
|
|
627
|
+
import { useEffect, useState } from 'react';
|
|
628
|
+
import { View } from 'react-native';
|
|
629
|
+
|
|
630
|
+
const { BannerAdModule } = NativeModules;
|
|
631
|
+
|
|
632
|
+
const BannerAdPage = () => {
|
|
633
|
+
const [showBannerView, setShowBannerView] = useState(false);
|
|
634
|
+
|
|
635
|
+
useEffect(() => {
|
|
636
|
+
// 先预加载广告,再显示组件
|
|
637
|
+
const preloadAndShow = async () => {
|
|
638
|
+
try {
|
|
639
|
+
await BannerAdModule.preloadBannerAd({
|
|
640
|
+
codeid: 'your_codeid',
|
|
641
|
+
adWidth: 320,
|
|
642
|
+
adHeight: 50,
|
|
643
|
+
});
|
|
644
|
+
} catch (error) {
|
|
645
|
+
console.log('预加载失败', error);
|
|
646
|
+
} finally {
|
|
647
|
+
// 无论预加载成功与否,都显示组件
|
|
648
|
+
setShowBannerView(true);
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
preloadAndShow();
|
|
653
|
+
}, []);
|
|
654
|
+
|
|
655
|
+
return (
|
|
656
|
+
<View>
|
|
657
|
+
<BannerAdView
|
|
658
|
+
codeid={'your_codeid'}
|
|
659
|
+
adWidth={320}
|
|
660
|
+
adHeight={50}
|
|
661
|
+
visible={showBannerView}
|
|
662
|
+
onAdRenderSuccess={(data: any) => {
|
|
663
|
+
console.log('Banner 广告渲染成功!', data);
|
|
664
|
+
}}
|
|
665
|
+
onAdError={(err: any) => {
|
|
666
|
+
console.log('Banner 广告加载失败!', err);
|
|
667
|
+
}}
|
|
668
|
+
/>
|
|
669
|
+
</View>
|
|
670
|
+
);
|
|
671
|
+
};
|
|
672
|
+
```
|
|
673
|
+
|
|
421
674
|
# 6. 信息流广告
|
|
422
675
|
|
|
676
|
+
## API
|
|
677
|
+
|
|
678
|
+
### preloadFeedAd
|
|
679
|
+
|
|
680
|
+
预加载信息流广告(Android 专用)
|
|
681
|
+
|
|
682
|
+
在组件渲染前调用,提前加载广告数据,减少白屏时间。
|
|
683
|
+
|
|
684
|
+
| 参数 | 说明 | 类型 | 默认值 | 是否必填 |
|
|
685
|
+
| ------- | ------------ | ------ | ------ | -------- |
|
|
686
|
+
| appid | 应用 ID | string | - | 是 |
|
|
687
|
+
| codeid | 广告位 ID | string | - | 是 |
|
|
688
|
+
| adWidth | 广告宽度(dp) | string | '280' | 否 |
|
|
689
|
+
|
|
690
|
+
```tsx
|
|
691
|
+
import { preloadFeedAd } from '@24jieqi/react-native-brayant-ad';
|
|
692
|
+
|
|
693
|
+
// 在页面进入前预加载
|
|
694
|
+
useEffect(() => {
|
|
695
|
+
preloadFeedAd({
|
|
696
|
+
appid: 'your_appid',
|
|
697
|
+
codeid: 'your_codeid',
|
|
698
|
+
adWidth: '375',
|
|
699
|
+
});
|
|
700
|
+
}, []);
|
|
701
|
+
```
|
|
702
|
+
|
|
423
703
|
## 组件
|
|
424
704
|
|
|
425
705
|
### FeedAdView
|
|
@@ -437,6 +717,8 @@ const BannerAdPage = () => {
|
|
|
437
717
|
|
|
438
718
|
## 使用
|
|
439
719
|
|
|
720
|
+
### 基础用法
|
|
721
|
+
|
|
440
722
|
```tsx
|
|
441
723
|
import { FeedAdView } from '@24jieqi/react-native-brayant-ad';
|
|
442
724
|
import { useEffect, useState } from 'react';
|
|
@@ -470,6 +752,42 @@ const RewardVideoPage = () => {
|
|
|
470
752
|
};
|
|
471
753
|
```
|
|
472
754
|
|
|
755
|
+
### 推荐用法(预加载)
|
|
756
|
+
|
|
757
|
+
```tsx
|
|
758
|
+
import { FeedAdView, preloadFeedAd } from '@24jieqi/react-native-brayant-ad';
|
|
759
|
+
import { useEffect, useState } from 'react';
|
|
760
|
+
|
|
761
|
+
const RewardVideoPage = () => {
|
|
762
|
+
const [showFeedView, setShowFeedView] = useState(false);
|
|
763
|
+
|
|
764
|
+
// 页面进入时预加载广告
|
|
765
|
+
useEffect(() => {
|
|
766
|
+
preloadFeedAd({
|
|
767
|
+
appid: 'your_appid',
|
|
768
|
+
codeid: 'your_codeid',
|
|
769
|
+
}).then(() => {
|
|
770
|
+
// 预加载成功后显示组件
|
|
771
|
+
setShowFeedView(true);
|
|
772
|
+
});
|
|
773
|
+
}, []);
|
|
774
|
+
|
|
775
|
+
return (
|
|
776
|
+
<FeedAdView
|
|
777
|
+
codeid={'your_codeid'}
|
|
778
|
+
adWidth={375}
|
|
779
|
+
visible={showFeedView}
|
|
780
|
+
onAdLayout={(data: any) => {
|
|
781
|
+
console.log('Feed 广告加载成功!', data);
|
|
782
|
+
}}
|
|
783
|
+
onAdError={(err: any) => {
|
|
784
|
+
console.log('Feed 广告加载失败!', err);
|
|
785
|
+
}}
|
|
786
|
+
/>
|
|
787
|
+
);
|
|
788
|
+
};
|
|
789
|
+
```
|
|
790
|
+
|
|
473
791
|
## License
|
|
474
792
|
|
|
475
793
|
MIT
|
|
@@ -122,6 +122,74 @@ public class AdManager extends ReactContextBaseJavaModule {
|
|
|
122
122
|
loadTTFeedAd(codeId, width);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
/**
|
|
126
|
+
* 预加载信息流广告(FeedAd)
|
|
127
|
+
* 在组件渲染前调用,提前加载广告数据,减少白屏时间
|
|
128
|
+
* 与 loadFeedAd 的区别:此方法不依赖 Promise 回调,静默预加载
|
|
129
|
+
*/
|
|
130
|
+
@ReactMethod
|
|
131
|
+
public void preloadFeedAd(ReadableMap options, final Promise promise) {
|
|
132
|
+
String codeId = options.getString("codeid");
|
|
133
|
+
if (codeId == null || codeId.isEmpty()) {
|
|
134
|
+
promise.reject(TAG, "codeid is required");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
float width = 0;
|
|
139
|
+
if (options.hasKey("adWidth")) {
|
|
140
|
+
width = Float.parseFloat(Objects.requireNonNull(options.getString("adWidth")));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 检查 SDK 是否初始化
|
|
144
|
+
if (DyADCore.TTAdSdk == null) {
|
|
145
|
+
promise.reject(TAG, "TTAdSdk not initialized");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 如果已经有缓存的广告,直接返回成功
|
|
150
|
+
if (DyADCore.feedAd != null) {
|
|
151
|
+
promise.resolve(true);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 创建广告请求参数
|
|
156
|
+
float expressViewWidth = width > 0 ? width : 280;
|
|
157
|
+
float expressViewHeight = 0; // 自动高度
|
|
158
|
+
|
|
159
|
+
AdSlot adSlot = new AdSlot.Builder()
|
|
160
|
+
.setCodeId(codeId)
|
|
161
|
+
.setSupportDeepLink(true)
|
|
162
|
+
.setAdCount(1)
|
|
163
|
+
.setExpressViewAcceptedSize(expressViewWidth, expressViewHeight)
|
|
164
|
+
.setImageAcceptedSize(640, 320)
|
|
165
|
+
.setNativeAdType(AdSlot.TYPE_INTERACTION_AD)
|
|
166
|
+
.build();
|
|
167
|
+
|
|
168
|
+
// 请求广告
|
|
169
|
+
DyADCore.TTAdSdk.loadNativeExpressAd(
|
|
170
|
+
adSlot,
|
|
171
|
+
new TTAdNative.NativeExpressAdListener() {
|
|
172
|
+
@Override
|
|
173
|
+
public void onError(int code, String message) {
|
|
174
|
+
Log.d(TAG, "preloadFeedAd error: " + message);
|
|
175
|
+
promise.reject(TAG, "preload feed ad error: " + message);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@Override
|
|
179
|
+
public void onNativeExpressAdLoad(List<TTNativeExpressAd> ads) {
|
|
180
|
+
Log.d(TAG, "preloadFeedAd success");
|
|
181
|
+
if (ads == null || ads.isEmpty()) {
|
|
182
|
+
promise.reject(TAG, "preload feed ad: no ad content");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// 缓存加载成功的广告
|
|
186
|
+
DyADCore.feedAd = ads.get(0);
|
|
187
|
+
promise.resolve(true);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
125
193
|
/**
|
|
126
194
|
* 加载穿山甲的信息流广告
|
|
127
195
|
*
|
|
@@ -2,6 +2,7 @@ package com.brayantad;
|
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.NonNull;
|
|
4
4
|
|
|
5
|
+
import com.brayantad.dy.banner.BannerAdModule;
|
|
5
6
|
import com.brayantad.dy.banner.BannerAdViewManager;
|
|
6
7
|
import com.brayantad.dy.drawFeed.DrawFeedViewManager;
|
|
7
8
|
import com.brayantad.dy.drawFeed.DrawFeedViewModule;
|
|
@@ -29,6 +30,7 @@ public class BrayantAdPackage implements ReactPackage {
|
|
|
29
30
|
modules.add(new RewardVideoModule(reactContext));
|
|
30
31
|
modules.add(new FullScreenVideoModule(reactContext));
|
|
31
32
|
modules.add(new DrawFeedViewModule(reactContext));
|
|
33
|
+
modules.add(new BannerAdModule(reactContext));
|
|
32
34
|
return modules;
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -70,6 +70,15 @@ public class DyADCore {
|
|
|
70
70
|
public static CSJSplashAd splashAd;
|
|
71
71
|
public static ReactContext reactContext;
|
|
72
72
|
|
|
73
|
+
// 开屏广告预加载状态管理
|
|
74
|
+
public static final int SPLASH_PRELOAD_IDLE = 0; // 未预加载
|
|
75
|
+
public static final int SPLASH_PRELOAD_LOADING = 1; // 预加载中
|
|
76
|
+
public static final int SPLASH_PRELOAD_SUCCESS = 2; // 预加载成功
|
|
77
|
+
public static final int SPLASH_PRELOAD_FAIL = 3; // 预加载失败
|
|
78
|
+
public static int splashPreloadStatus = SPLASH_PRELOAD_IDLE;
|
|
79
|
+
public static long splashPreloadTime = 0; // 预加载成功时间戳
|
|
80
|
+
public static final long SPLASH_PRELOAD_VALID_DURATION = 5 * 60 * 1000; // 预加载有效期5分钟
|
|
81
|
+
|
|
73
82
|
public static void initSdk(Context context, String appId, Boolean debug) {
|
|
74
83
|
if (TTAdSdk != null && Objects.equals(tt_appid, appId)) {
|
|
75
84
|
//已初始化
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
package com.brayantad.dy.banner;
|
|
2
|
+
|
|
3
|
+
import android.util.Log;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
|
|
7
|
+
import com.brayantad.dy.DyADCore;
|
|
8
|
+
import com.bytedance.sdk.openadsdk.AdSlot;
|
|
9
|
+
import com.bytedance.sdk.openadsdk.TTAdNative;
|
|
10
|
+
import com.bytedance.sdk.openadsdk.TTNativeExpressAd;
|
|
11
|
+
import com.facebook.react.bridge.Promise;
|
|
12
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
13
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
14
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
15
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
16
|
+
|
|
17
|
+
import java.util.List;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Banner 广告预加载模块
|
|
21
|
+
* 提供 Banner 广告的预加载功能,减少白屏时间
|
|
22
|
+
*/
|
|
23
|
+
public class BannerAdModule extends ReactContextBaseJavaModule {
|
|
24
|
+
public static final String TAG = "BannerAdModule";
|
|
25
|
+
private static ReactApplicationContext reactAppContext;
|
|
26
|
+
|
|
27
|
+
// Banner 广告缓存
|
|
28
|
+
private static TTNativeExpressAd bannerAdCache = null;
|
|
29
|
+
private static String bannerAdCacheCodeId = null;
|
|
30
|
+
private static long bannerAdCacheTime = 0;
|
|
31
|
+
private static final long CACHE_VALID_DURATION = 5 * 60 * 1000; // 缓存有效期 5 分钟
|
|
32
|
+
|
|
33
|
+
public BannerAdModule(ReactApplicationContext reactContext) {
|
|
34
|
+
super(reactContext);
|
|
35
|
+
reactAppContext = reactContext;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@NonNull
|
|
39
|
+
@Override
|
|
40
|
+
public String getName() {
|
|
41
|
+
return TAG;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 预加载 Banner 广告
|
|
46
|
+
* 在组件渲染前调用,提前加载广告数据
|
|
47
|
+
*
|
|
48
|
+
* @param options 包含 codeid, adWidth, adHeight
|
|
49
|
+
* @param promise 回调
|
|
50
|
+
*/
|
|
51
|
+
@ReactMethod
|
|
52
|
+
public void preloadBannerAd(ReadableMap options, final Promise promise) {
|
|
53
|
+
String codeId = options.hasKey("codeid") ? options.getString("codeid") : null;
|
|
54
|
+
int adWidth = options.hasKey("adWidth") ? options.getInt("adWidth") : 320;
|
|
55
|
+
int adHeight = options.hasKey("adHeight") ? options.getInt("adHeight") : 50;
|
|
56
|
+
|
|
57
|
+
if (codeId == null || codeId.isEmpty()) {
|
|
58
|
+
promise.reject(TAG, "codeid is required");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 检查 SDK 是否初始化
|
|
63
|
+
if (DyADCore.TTAdSdk == null) {
|
|
64
|
+
promise.reject(TAG, "TTAdSdk not initialized");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 检查缓存是否有效
|
|
69
|
+
if (hasValidCache(codeId)) {
|
|
70
|
+
Log.d(TAG, "Using cached banner ad");
|
|
71
|
+
promise.resolve(true);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 清除旧缓存
|
|
76
|
+
clearCache();
|
|
77
|
+
|
|
78
|
+
// 创建广告请求参数
|
|
79
|
+
AdSlot adSlot = new AdSlot.Builder()
|
|
80
|
+
.setCodeId(codeId)
|
|
81
|
+
.setSupportDeepLink(true)
|
|
82
|
+
.setAdCount(1)
|
|
83
|
+
.setExpressViewAcceptedSize(adWidth, adHeight)
|
|
84
|
+
.build();
|
|
85
|
+
|
|
86
|
+
// 请求广告
|
|
87
|
+
DyADCore.TTAdSdk.loadBannerExpressAd(
|
|
88
|
+
adSlot,
|
|
89
|
+
new TTAdNative.NativeExpressAdListener() {
|
|
90
|
+
@Override
|
|
91
|
+
public void onError(int code, String message) {
|
|
92
|
+
Log.d(TAG, "preloadBannerAd error: " + message);
|
|
93
|
+
promise.reject(TAG, "preload banner ad error: " + message);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@Override
|
|
97
|
+
public void onNativeExpressAdLoad(List<TTNativeExpressAd> ads) {
|
|
98
|
+
Log.d(TAG, "preloadBannerAd success");
|
|
99
|
+
if (ads == null || ads.isEmpty()) {
|
|
100
|
+
promise.reject(TAG, "preload banner ad: no ad content");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// 缓存广告
|
|
104
|
+
bannerAdCache = ads.get(0);
|
|
105
|
+
bannerAdCacheCodeId = codeId;
|
|
106
|
+
bannerAdCacheTime = System.currentTimeMillis();
|
|
107
|
+
promise.resolve(true);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 检查是否有有效的缓存广告
|
|
115
|
+
*
|
|
116
|
+
* @param codeId 广告位 ID
|
|
117
|
+
* @return true 如果缓存有效
|
|
118
|
+
*/
|
|
119
|
+
@ReactMethod
|
|
120
|
+
public void hasPreloadedBannerAd(String codeId, Promise promise) {
|
|
121
|
+
promise.resolve(hasValidCache(codeId));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 获取缓存的广告(供 BannerAdView 使用)
|
|
126
|
+
*
|
|
127
|
+
* @param codeId 广告位 ID
|
|
128
|
+
* @return 缓存的广告,如果没有则返回 null
|
|
129
|
+
*/
|
|
130
|
+
public static TTNativeExpressAd getCachedBannerAd(String codeId) {
|
|
131
|
+
if (hasValidCache(codeId)) {
|
|
132
|
+
TTNativeExpressAd cachedAd = bannerAdCache;
|
|
133
|
+
// 使用后清除缓存,避免重复使用
|
|
134
|
+
clearCache();
|
|
135
|
+
return cachedAd;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 清除缓存的广告
|
|
142
|
+
*/
|
|
143
|
+
@ReactMethod
|
|
144
|
+
public void clearPreloadedBannerAd() {
|
|
145
|
+
clearCache();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 检查缓存是否有效
|
|
150
|
+
*/
|
|
151
|
+
private static boolean hasValidCache(String codeId) {
|
|
152
|
+
if (bannerAdCache == null || bannerAdCacheCodeId == null) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// 检查 codeId 是否匹配
|
|
156
|
+
if (!bannerAdCacheCodeId.equals(codeId)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
// 检查缓存是否过期
|
|
160
|
+
long currentTime = System.currentTimeMillis();
|
|
161
|
+
return (currentTime - bannerAdCacheTime) < CACHE_VALID_DURATION;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 清除缓存
|
|
166
|
+
*/
|
|
167
|
+
private static void clearCache() {
|
|
168
|
+
if (bannerAdCache != null) {
|
|
169
|
+
bannerAdCache.destroy();
|
|
170
|
+
bannerAdCache = null;
|
|
171
|
+
}
|
|
172
|
+
bannerAdCacheCodeId = null;
|
|
173
|
+
bannerAdCacheTime = 0;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -9,6 +9,7 @@ import android.widget.RelativeLayout;
|
|
|
9
9
|
|
|
10
10
|
import com.brayantad.R;
|
|
11
11
|
import com.brayantad.dy.DyADCore;
|
|
12
|
+
import com.brayantad.dy.banner.BannerAdModule;
|
|
12
13
|
import com.brayantad.utils.Utils;
|
|
13
14
|
import com.bytedance.sdk.openadsdk.AdSlot;
|
|
14
15
|
import com.bytedance.sdk.openadsdk.TTAdDislike;
|
|
@@ -109,6 +110,16 @@ public class BannerAdView extends RelativeLayout {
|
|
|
109
110
|
mBannerAd.destroy();
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
// 先检查是否有预加载的缓存广告
|
|
114
|
+
TTNativeExpressAd cachedAd = BannerAdModule.getCachedBannerAd(mCodeId);
|
|
115
|
+
if (cachedAd != null) {
|
|
116
|
+
mBannerAd = cachedAd;
|
|
117
|
+
showBannerAd(mBannerAd);
|
|
118
|
+
mIsAdLoading = false;
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 没有缓存,正常加载
|
|
112
123
|
// 创建广告请求参数AdSlot
|
|
113
124
|
mAdSlot =
|
|
114
125
|
new AdSlot.Builder()
|