@vynix-org/react-native-ads-sdk 0.1.1
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/AdsSdk.podspec +52 -0
- package/LICENSE +20 -0
- package/README.md +95 -0
- package/android/build.gradle +108 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/java/com/adssdk/AdsSdkModule.kt +23 -0
- package/android/src/main/java/com/adssdk/AdsSdkPackage.kt +33 -0
- package/ios/AdsSdk.h +5 -0
- package/ios/AdsSdk.mm +18 -0
- package/lib/module/ads-manager/AppOpenAdsManager.js +131 -0
- package/lib/module/ads-manager/AppOpenAdsManager.js.map +1 -0
- package/lib/module/ads-manager/GoogleMobileAdsManager.js +62 -0
- package/lib/module/ads-manager/GoogleMobileAdsManager.js.map +1 -0
- package/lib/module/ads-manager/InterstitialAdsManager.js +291 -0
- package/lib/module/ads-manager/InterstitialAdsManager.js.map +1 -0
- package/lib/module/ads-manager/NativeAdsManager.js +405 -0
- package/lib/module/ads-manager/NativeAdsManager.js.map +1 -0
- package/lib/module/ads-manager/RewardedAdsManager.js +328 -0
- package/lib/module/ads-manager/RewardedAdsManager.js.map +1 -0
- package/lib/module/ads-manager/RewardedInterstitialAdsManager.js +328 -0
- package/lib/module/ads-manager/RewardedInterstitialAdsManager.js.map +1 -0
- package/lib/module/components/BannerAdComponent.js +159 -0
- package/lib/module/components/BannerAdComponent.js.map +1 -0
- package/lib/module/components/FullscreenStyles.js +162 -0
- package/lib/module/components/FullscreenStyles.js.map +1 -0
- package/lib/module/components/NativeAdComponent.js +172 -0
- package/lib/module/components/NativeAdComponent.js.map +1 -0
- package/lib/module/components/NativeAdFullscreenComponent.js +205 -0
- package/lib/module/components/NativeAdFullscreenComponent.js.map +1 -0
- package/lib/module/components/NativeStyles.js +143 -0
- package/lib/module/components/NativeStyles.js.map +1 -0
- package/lib/module/event/custom-event.js +29 -0
- package/lib/module/event/custom-event.js.map +1 -0
- package/lib/module/hook/useAppOpenAd.js +138 -0
- package/lib/module/hook/useAppOpenAd.js.map +1 -0
- package/lib/module/hook/useInterstitialAd.js +157 -0
- package/lib/module/hook/useInterstitialAd.js.map +1 -0
- package/lib/module/hook/useNativeAd.js +147 -0
- package/lib/module/hook/useNativeAd.js.map +1 -0
- package/lib/module/hook/useRewardedAd.js +166 -0
- package/lib/module/hook/useRewardedAd.js.map +1 -0
- package/lib/module/hook/useRewardedInterstitialAd.js +166 -0
- package/lib/module/hook/useRewardedInterstitialAd.js.map +1 -0
- package/lib/module/index.js +14 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/stores/interstitial-ads-store.js +205 -0
- package/lib/module/stores/interstitial-ads-store.js.map +1 -0
- package/lib/module/stores/native-ads-store.js +204 -0
- package/lib/module/stores/native-ads-store.js.map +1 -0
- package/lib/module/stores/rewarded-ads-store.js +216 -0
- package/lib/module/stores/rewarded-ads-store.js.map +1 -0
- package/lib/module/stores/rewarded-interstitial-ads-store.js +216 -0
- package/lib/module/stores/rewarded-interstitial-ads-store.js.map +1 -0
- package/lib/module/types/ads-types.js +25 -0
- package/lib/module/types/ads-types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/ads-manager/AppOpenAdsManager.d.ts +38 -0
- package/lib/typescript/src/ads-manager/AppOpenAdsManager.d.ts.map +1 -0
- package/lib/typescript/src/ads-manager/GoogleMobileAdsManager.d.ts +22 -0
- package/lib/typescript/src/ads-manager/GoogleMobileAdsManager.d.ts.map +1 -0
- package/lib/typescript/src/ads-manager/InterstitialAdsManager.d.ts +22 -0
- package/lib/typescript/src/ads-manager/InterstitialAdsManager.d.ts.map +1 -0
- package/lib/typescript/src/ads-manager/NativeAdsManager.d.ts +59 -0
- package/lib/typescript/src/ads-manager/NativeAdsManager.d.ts.map +1 -0
- package/lib/typescript/src/ads-manager/RewardedAdsManager.d.ts +25 -0
- package/lib/typescript/src/ads-manager/RewardedAdsManager.d.ts.map +1 -0
- package/lib/typescript/src/ads-manager/RewardedInterstitialAdsManager.d.ts +25 -0
- package/lib/typescript/src/ads-manager/RewardedInterstitialAdsManager.d.ts.map +1 -0
- package/lib/typescript/src/components/BannerAdComponent.d.ts +22 -0
- package/lib/typescript/src/components/BannerAdComponent.d.ts.map +1 -0
- package/lib/typescript/src/components/FullscreenStyles.d.ts +155 -0
- package/lib/typescript/src/components/FullscreenStyles.d.ts.map +1 -0
- package/lib/typescript/src/components/NativeAdComponent.d.ts +24 -0
- package/lib/typescript/src/components/NativeAdComponent.d.ts.map +1 -0
- package/lib/typescript/src/components/NativeAdFullscreenComponent.d.ts +26 -0
- package/lib/typescript/src/components/NativeAdFullscreenComponent.d.ts.map +1 -0
- package/lib/typescript/src/components/NativeStyles.d.ts +139 -0
- package/lib/typescript/src/components/NativeStyles.d.ts.map +1 -0
- package/lib/typescript/src/event/custom-event.d.ts +8 -0
- package/lib/typescript/src/event/custom-event.d.ts.map +1 -0
- package/lib/typescript/src/hook/useAppOpenAd.d.ts +19 -0
- package/lib/typescript/src/hook/useAppOpenAd.d.ts.map +1 -0
- package/lib/typescript/src/hook/useInterstitialAd.d.ts +20 -0
- package/lib/typescript/src/hook/useInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/src/hook/useNativeAd.d.ts +20 -0
- package/lib/typescript/src/hook/useNativeAd.d.ts.map +1 -0
- package/lib/typescript/src/hook/useRewardedAd.d.ts +27 -0
- package/lib/typescript/src/hook/useRewardedAd.d.ts.map +1 -0
- package/lib/typescript/src/hook/useRewardedInterstitialAd.d.ts +27 -0
- package/lib/typescript/src/hook/useRewardedInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/stores/interstitial-ads-store.d.ts +36 -0
- package/lib/typescript/src/stores/interstitial-ads-store.d.ts.map +1 -0
- package/lib/typescript/src/stores/native-ads-store.d.ts +36 -0
- package/lib/typescript/src/stores/native-ads-store.d.ts.map +1 -0
- package/lib/typescript/src/stores/rewarded-ads-store.d.ts +39 -0
- package/lib/typescript/src/stores/rewarded-ads-store.d.ts.map +1 -0
- package/lib/typescript/src/stores/rewarded-interstitial-ads-store.d.ts +39 -0
- package/lib/typescript/src/stores/rewarded-interstitial-ads-store.d.ts.map +1 -0
- package/lib/typescript/src/types/ads-types.d.ts +164 -0
- package/lib/typescript/src/types/ads-types.d.ts.map +1 -0
- package/package.json +177 -0
- package/src/ads-manager/AppOpenAdsManager.ts +155 -0
- package/src/ads-manager/GoogleMobileAdsManager.ts +68 -0
- package/src/ads-manager/InterstitialAdsManager.ts +371 -0
- package/src/ads-manager/NativeAdsManager.ts +445 -0
- package/src/ads-manager/RewardedAdsManager.ts +383 -0
- package/src/ads-manager/RewardedInterstitialAdsManager.ts +410 -0
- package/src/components/BannerAdComponent.tsx +205 -0
- package/src/components/FullscreenStyles.ts +158 -0
- package/src/components/NativeAdComponent.tsx +208 -0
- package/src/components/NativeAdFullscreenComponent.tsx +261 -0
- package/src/components/NativeStyles.ts +141 -0
- package/src/event/custom-event.ts +30 -0
- package/src/hook/useAppOpenAd.ts +161 -0
- package/src/hook/useInterstitialAd.ts +195 -0
- package/src/hook/useNativeAd.ts +173 -0
- package/src/hook/useRewardedAd.ts +205 -0
- package/src/hook/useRewardedInterstitialAd.ts +212 -0
- package/src/index.tsx +33 -0
- package/src/stores/interstitial-ads-store.ts +287 -0
- package/src/stores/native-ads-store.ts +272 -0
- package/src/stores/rewarded-ads-store.ts +290 -0
- package/src/stores/rewarded-interstitial-ads-store.ts +318 -0
- package/src/types/ads-types.ts +239 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { MobileAds } from 'react-native-google-mobile-ads';
|
|
2
|
+
|
|
3
|
+
export class GoogleMobileAdsManager {
|
|
4
|
+
private static instance: GoogleMobileAdsManager;
|
|
5
|
+
private isInitialized = false;
|
|
6
|
+
private initPromise: Promise<void> | null = null;
|
|
7
|
+
|
|
8
|
+
private constructor() {}
|
|
9
|
+
|
|
10
|
+
static getInstance(): GoogleMobileAdsManager {
|
|
11
|
+
if (!GoogleMobileAdsManager.instance) {
|
|
12
|
+
GoogleMobileAdsManager.instance = new GoogleMobileAdsManager();
|
|
13
|
+
}
|
|
14
|
+
return GoogleMobileAdsManager.instance;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Khởi tạo Google Mobile Ads SDK
|
|
19
|
+
*/
|
|
20
|
+
async initialize(): Promise<void> {
|
|
21
|
+
if (this.isInitialized) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (this.initPromise) {
|
|
26
|
+
return this.initPromise;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.initPromise = this.initializeInternal();
|
|
30
|
+
return this.initPromise;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private async initializeInternal(): Promise<void> {
|
|
34
|
+
try {
|
|
35
|
+
await MobileAds().initialize();
|
|
36
|
+
this.isInitialized = true;
|
|
37
|
+
console.log('Google Mobile Ads SDK initialized successfully');
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('Failed to initialize Google Mobile Ads SDK:', error);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Kiểm tra xem SDK đã được khởi tạo chưa
|
|
46
|
+
*/
|
|
47
|
+
isSDKInitialized(): boolean {
|
|
48
|
+
return this.isInitialized;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Lấy trạng thái khởi tạo
|
|
53
|
+
*/
|
|
54
|
+
getInitializationStatus(): Promise<boolean> {
|
|
55
|
+
if (this.isInitialized) {
|
|
56
|
+
return Promise.resolve(true);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (this.initPromise) {
|
|
60
|
+
return this.initPromise.then(() => true).catch(() => false);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return Promise.resolve(false);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Singleton instance
|
|
68
|
+
export const googleMobileAdsManager = GoogleMobileAdsManager.getInstance();
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AdStatus,
|
|
3
|
+
type InterstitialAdConfig,
|
|
4
|
+
type InterstitialAdInstance,
|
|
5
|
+
} from '../types/ads-types';
|
|
6
|
+
import { googleMobileAdsManager } from './GoogleMobileAdsManager';
|
|
7
|
+
import { CustomEventEmitter } from '../event/custom-event';
|
|
8
|
+
|
|
9
|
+
export class InterstitialAdsManager extends CustomEventEmitter {
|
|
10
|
+
private state: Map<string, InterstitialAdInstance> = new Map();
|
|
11
|
+
private configs: Map<string, InterstitialAdConfig> = new Map();
|
|
12
|
+
private loadPromises: Map<string, Promise<void>> = new Map();
|
|
13
|
+
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
this.initializeGoogleMobileAds();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private async initializeGoogleMobileAds(): Promise<void> {
|
|
20
|
+
try {
|
|
21
|
+
await googleMobileAdsManager.initialize();
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.warn('Failed to initialize Google Mobile Ads SDK:', error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Thay đổi signature: chỉ nhận config
|
|
28
|
+
async preloadAd(config: InterstitialAdConfig): Promise<void> {
|
|
29
|
+
const fullConfig: InterstitialAdConfig = {
|
|
30
|
+
...config,
|
|
31
|
+
timeout: config.timeout ?? 10000,
|
|
32
|
+
maxRetries: config.maxRetries ?? 3,
|
|
33
|
+
showOnAppStateChange: config.showOnAppStateChange ?? false,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const { adKey, adId } = fullConfig;
|
|
37
|
+
this.configs.set(adKey, fullConfig);
|
|
38
|
+
|
|
39
|
+
if (!this.state.has(adKey)) {
|
|
40
|
+
const adInstance: InterstitialAdInstance = {
|
|
41
|
+
adKey,
|
|
42
|
+
adId,
|
|
43
|
+
status: AdStatus.IDLE,
|
|
44
|
+
data: null,
|
|
45
|
+
error: null,
|
|
46
|
+
loadTime: null,
|
|
47
|
+
displayTime: null,
|
|
48
|
+
retryCount: 0,
|
|
49
|
+
type: 'interstitial',
|
|
50
|
+
config: fullConfig,
|
|
51
|
+
isUsingHighPriority: false,
|
|
52
|
+
hasTriedHighPriority: false,
|
|
53
|
+
};
|
|
54
|
+
this.state.set(adKey, adInstance);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (this.loadPromises.has(adKey)) {
|
|
58
|
+
return this.loadPromises.get(adKey)!;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const loadPromise = this.loadAdInternal(adKey);
|
|
62
|
+
this.loadPromises.set(adKey, loadPromise);
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
await loadPromise;
|
|
66
|
+
} finally {
|
|
67
|
+
this.loadPromises.delete(adKey);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Thay đổi signature: chỉ nhận config
|
|
72
|
+
async loadAd(config: InterstitialAdConfig): Promise<void> {
|
|
73
|
+
return this.preloadAd(config);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async displayAd(adKey: string): Promise<InterstitialAdInstance | null> {
|
|
77
|
+
const ad = this.state.get(adKey);
|
|
78
|
+
|
|
79
|
+
if (!ad) {
|
|
80
|
+
console.warn(`Interstitial ad with key "${adKey}" not found`);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (ad.status === AdStatus.LOADED) {
|
|
85
|
+
try {
|
|
86
|
+
await this.showInterstitialAd(ad);
|
|
87
|
+
|
|
88
|
+
ad.status = AdStatus.DISPLAYED;
|
|
89
|
+
ad.displayTime = Date.now();
|
|
90
|
+
this.emit('adDisplayed', ad);
|
|
91
|
+
|
|
92
|
+
return ad;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
ad.status = AdStatus.ERROR;
|
|
95
|
+
ad.error = error instanceof Error ? error.message : String(error);
|
|
96
|
+
this.emit('adError', ad);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (ad.status === AdStatus.LOADING) {
|
|
102
|
+
await this.waitForAdLoad(adKey);
|
|
103
|
+
return this.displayAd(adKey);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (ad.status === AdStatus.ERROR) {
|
|
107
|
+
await this.refreshAd(adKey);
|
|
108
|
+
return this.displayAd(adKey);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.warn(
|
|
112
|
+
`Cannot display interstitial ad with key "${adKey}" in status: ${ad.status}`
|
|
113
|
+
);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
getAd(adKey: string): InterstitialAdInstance | null {
|
|
118
|
+
return this.state.get(adKey) || null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
removeAd(adKey: string): void {
|
|
122
|
+
this.state.delete(adKey);
|
|
123
|
+
this.configs.delete(adKey);
|
|
124
|
+
this.loadPromises.delete(adKey);
|
|
125
|
+
this.emit('adRemoved', adKey);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async refreshAd(adKey: string): Promise<void> {
|
|
129
|
+
const config = this.configs.get(adKey);
|
|
130
|
+
if (!config) {
|
|
131
|
+
throw new Error(`Config for key "${adKey}" not found`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
console.log('Refresh ad:', adKey);
|
|
135
|
+
|
|
136
|
+
const ad = this.state.get(adKey);
|
|
137
|
+
if (ad) {
|
|
138
|
+
ad.status = AdStatus.IDLE;
|
|
139
|
+
ad.error = null;
|
|
140
|
+
ad.retryCount = 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return this.preloadAd(config); // Truyền config thay vì adKey, adId, config
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
clearAllAds(): void {
|
|
147
|
+
const keys = Array.from(this.state.keys());
|
|
148
|
+
keys.forEach((adKey) => this.removeAd(adKey));
|
|
149
|
+
this.emit('allAdsCleared');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private async loadAdInternal(adKey: string): Promise<void> {
|
|
153
|
+
const ad = this.state.get(adKey);
|
|
154
|
+
const config = this.configs.get(adKey);
|
|
155
|
+
|
|
156
|
+
if (!ad || !config) {
|
|
157
|
+
throw new Error(`Ad or config for key "${adKey}" not found`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Xác định adId sẽ được sử dụng
|
|
161
|
+
let adIdToLoad = config.adId;
|
|
162
|
+
|
|
163
|
+
// Nếu có adHighpriorityId và chưa thử load high priority
|
|
164
|
+
if (config.adHighpriorityId && !ad.hasTriedHighPriority) {
|
|
165
|
+
adIdToLoad = config.adHighpriorityId;
|
|
166
|
+
ad.isUsingHighPriority = true;
|
|
167
|
+
} else {
|
|
168
|
+
ad.isUsingHighPriority = false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Kiểm tra retry limit
|
|
172
|
+
if (ad.retryCount >= config.maxRetries!) {
|
|
173
|
+
// Nếu đang dùng high priority và đã hết retry, fallback về adId bình thường
|
|
174
|
+
if (ad.isUsingHighPriority) {
|
|
175
|
+
console.log(
|
|
176
|
+
`High priority ad failed after ${config.maxRetries} retries, falling back to normal ad`
|
|
177
|
+
);
|
|
178
|
+
ad.hasTriedHighPriority = true;
|
|
179
|
+
ad.retryCount = 0;
|
|
180
|
+
ad.isUsingHighPriority = false;
|
|
181
|
+
return this.loadAdInternal(adKey);
|
|
182
|
+
} else {
|
|
183
|
+
ad.status = AdStatus.ERROR;
|
|
184
|
+
ad.error = `Max retries (${config.maxRetries}) exceeded`;
|
|
185
|
+
this.emit('adError', ad);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ad.status = AdStatus.LOADING;
|
|
191
|
+
ad.retryCount++;
|
|
192
|
+
this.emit('adLoading', ad);
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
await googleMobileAdsManager.initialize();
|
|
196
|
+
|
|
197
|
+
const interstitialAd = await this.loadInterstitialAd(
|
|
198
|
+
adIdToLoad,
|
|
199
|
+
config.timeout!
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
ad.status = AdStatus.LOADED;
|
|
203
|
+
ad.interstitialAd = interstitialAd;
|
|
204
|
+
ad.error = null;
|
|
205
|
+
ad.loadTime = Date.now();
|
|
206
|
+
ad.retryCount = 0;
|
|
207
|
+
|
|
208
|
+
if (ad.isUsingHighPriority) {
|
|
209
|
+
ad.hasTriedHighPriority = true;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
this.emit('adLoaded', ad);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
ad.status = AdStatus.ERROR;
|
|
215
|
+
ad.error = error instanceof Error ? error.message : String(error);
|
|
216
|
+
this.emit('adError', ad);
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private async loadInterstitialAd(
|
|
222
|
+
adId: string,
|
|
223
|
+
timeout: number
|
|
224
|
+
): Promise<any> {
|
|
225
|
+
try {
|
|
226
|
+
const googleMobileAdsModule = await import(
|
|
227
|
+
'react-native-google-mobile-ads'
|
|
228
|
+
);
|
|
229
|
+
const { InterstitialAd, TestIds, AdEventType } = googleMobileAdsModule;
|
|
230
|
+
|
|
231
|
+
const finalAdId = adId === 'test' ? TestIds.INTERSTITIAL : adId;
|
|
232
|
+
|
|
233
|
+
return new Promise((resolve, reject) => {
|
|
234
|
+
const timeoutId = setTimeout(() => {
|
|
235
|
+
reject(
|
|
236
|
+
new Error(`Timeout loading interstitial ad after ${timeout}ms`)
|
|
237
|
+
);
|
|
238
|
+
}, timeout);
|
|
239
|
+
|
|
240
|
+
// Tạo interstitial ad instance
|
|
241
|
+
const interstitialAd = InterstitialAd.createForAdRequest(finalAdId);
|
|
242
|
+
|
|
243
|
+
// Thêm event listeners
|
|
244
|
+
const unsubscribeLoaded = interstitialAd.addAdEventListener(
|
|
245
|
+
AdEventType.LOADED,
|
|
246
|
+
() => {
|
|
247
|
+
clearTimeout(timeoutId);
|
|
248
|
+
unsubscribeLoaded();
|
|
249
|
+
unsubscribeError();
|
|
250
|
+
resolve(interstitialAd);
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const unsubscribeError = interstitialAd.addAdEventListener(
|
|
255
|
+
AdEventType.ERROR,
|
|
256
|
+
(error: any) => {
|
|
257
|
+
clearTimeout(timeoutId);
|
|
258
|
+
unsubscribeLoaded();
|
|
259
|
+
unsubscribeError();
|
|
260
|
+
reject(
|
|
261
|
+
new Error(
|
|
262
|
+
`Failed to load interstitial ad: ${error.message || error}`
|
|
263
|
+
)
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// Bắt đầu load quảng cáo
|
|
269
|
+
interstitialAd.load();
|
|
270
|
+
});
|
|
271
|
+
} catch (error) {
|
|
272
|
+
console.warn('Failed to load interstitial ad:', error);
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private async showInterstitialAd(ad: InterstitialAdInstance): Promise<void> {
|
|
278
|
+
if (!ad.interstitialAd) {
|
|
279
|
+
throw new Error('Interstitial ad not loaded');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
console.log('Show interstitial ad:', ad.adKey);
|
|
283
|
+
|
|
284
|
+
return new Promise((resolve, reject) => {
|
|
285
|
+
const googleMobileAdsModule = require('react-native-google-mobile-ads');
|
|
286
|
+
const { AdEventType } = googleMobileAdsModule;
|
|
287
|
+
|
|
288
|
+
// Thêm event listeners cho việc hiển thị
|
|
289
|
+
const unsubscribeClosed = ad.interstitialAd.addAdEventListener(
|
|
290
|
+
AdEventType.CLOSED,
|
|
291
|
+
() => {
|
|
292
|
+
unsubscribeClosed();
|
|
293
|
+
unsubscribeError();
|
|
294
|
+
unsubscribeOpened();
|
|
295
|
+
unsubscribeClicked();
|
|
296
|
+
|
|
297
|
+
// Emit sự kiện adClosed
|
|
298
|
+
this.emit('adClosed', ad);
|
|
299
|
+
resolve();
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
const unsubscribeError = ad.interstitialAd.addAdEventListener(
|
|
304
|
+
AdEventType.ERROR,
|
|
305
|
+
(error: any) => {
|
|
306
|
+
unsubscribeClosed();
|
|
307
|
+
unsubscribeError();
|
|
308
|
+
unsubscribeOpened();
|
|
309
|
+
unsubscribeClicked();
|
|
310
|
+
reject(
|
|
311
|
+
new Error(
|
|
312
|
+
`Failed to show interstitial ad: ${error.message || error}`
|
|
313
|
+
)
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
const unsubscribeOpened = ad.interstitialAd.addAdEventListener(
|
|
319
|
+
AdEventType.OPENED,
|
|
320
|
+
() => {
|
|
321
|
+
// Emit sự kiện adOpened
|
|
322
|
+
this.emit('adOpened', ad);
|
|
323
|
+
}
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
const unsubscribeClicked = ad.interstitialAd.addAdEventListener(
|
|
327
|
+
AdEventType.CLICKED,
|
|
328
|
+
() => {
|
|
329
|
+
// Emit sự kiện adClicked
|
|
330
|
+
this.emit('adClicked', ad);
|
|
331
|
+
}
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
// Hiển thị quảng cáo
|
|
335
|
+
ad.interstitialAd.show();
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private async waitForAdLoad(adKey: string): Promise<void> {
|
|
340
|
+
return new Promise((resolve, reject) => {
|
|
341
|
+
const timeout = setTimeout(() => {
|
|
342
|
+
reject(
|
|
343
|
+
new Error(`Timeout waiting for interstitial ad "${adKey}" to load`)
|
|
344
|
+
);
|
|
345
|
+
}, 10000);
|
|
346
|
+
|
|
347
|
+
const checkAd = () => {
|
|
348
|
+
const ad = this.state.get(adKey);
|
|
349
|
+
if (!ad) {
|
|
350
|
+
clearTimeout(timeout);
|
|
351
|
+
reject(new Error(`Interstitial ad "${adKey}" not found`));
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (ad.status === AdStatus.LOADED) {
|
|
356
|
+
clearTimeout(timeout);
|
|
357
|
+
resolve();
|
|
358
|
+
} else if (ad.status === AdStatus.ERROR) {
|
|
359
|
+
clearTimeout(timeout);
|
|
360
|
+
reject(new Error(ad.error || 'Unknown error'));
|
|
361
|
+
} else {
|
|
362
|
+
setTimeout(checkAd, 100);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
checkAd();
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export const interstitialAdsManager = new InterstitialAdsManager();
|