adwhale-sdk-react-native 2.7.100
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/AdwhaleSdkReactNative.podspec +20 -0
- package/LICENSE +20 -0
- package/README.md +121 -0
- package/android/build.gradle +135 -0
- package/android/gradle.properties +2 -0
- package/android/proguard-rules.pro +247 -0
- package/android/settings.gradle +71 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/adwhalesdkreactnative/AdwhaleSdkReactNativePackage.java +130 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationAdSettingModule.java +64 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationAdView.java +172 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationCustomNativeAdView.java +197 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationInterstitialAd.java +134 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationLoggerModule.java +35 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationRewardAd.java +151 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationTemplateNativeAdView.java +317 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNWrapperView.java +48 -0
- package/android/src/main/res/layout/custom_native_ad_layout.xml +58 -0
- package/app.plugin.js +2 -0
- package/ios/AdwhaleSdkReactNative.h +5 -0
- package/ios/AdwhaleSdkReactNative.mm +21 -0
- package/lib/module/AdWhaleBannerView.js +20 -0
- package/lib/module/AdWhaleBannerView.js.map +1 -0
- package/lib/module/AdWhaleInterstitialAd.js +47 -0
- package/lib/module/AdWhaleInterstitialAd.js.map +1 -0
- package/lib/module/AdWhaleMediationSdk.js +48 -0
- package/lib/module/AdWhaleMediationSdk.js.map +1 -0
- package/lib/module/AdWhaleNativeCustomView.js +36 -0
- package/lib/module/AdWhaleNativeCustomView.js.map +1 -0
- package/lib/module/AdWhaleNativeTemplateView.js +40 -0
- package/lib/module/AdWhaleNativeTemplateView.js.map +1 -0
- package/lib/module/AdWhaleRewardAd.js +50 -0
- package/lib/module/AdWhaleRewardAd.js.map +1 -0
- package/lib/module/NativeAdwhaleSdkReactNative.js +5 -0
- package/lib/module/NativeAdwhaleSdkReactNative.js.map +1 -0
- package/lib/module/index.js +28 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/AdWhaleBannerView.d.ts +18 -0
- package/lib/typescript/src/AdWhaleBannerView.d.ts.map +1 -0
- package/lib/typescript/src/AdWhaleInterstitialAd.d.ts +19 -0
- package/lib/typescript/src/AdWhaleInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/src/AdWhaleMediationSdk.d.ts +17 -0
- package/lib/typescript/src/AdWhaleMediationSdk.d.ts.map +1 -0
- package/lib/typescript/src/AdWhaleNativeCustomView.d.ts +19 -0
- package/lib/typescript/src/AdWhaleNativeCustomView.d.ts.map +1 -0
- package/lib/typescript/src/AdWhaleNativeTemplateView.d.ts +40 -0
- package/lib/typescript/src/AdWhaleNativeTemplateView.d.ts.map +1 -0
- package/lib/typescript/src/AdWhaleRewardAd.d.ts +24 -0
- package/lib/typescript/src/AdWhaleRewardAd.d.ts.map +1 -0
- package/lib/typescript/src/NativeAdwhaleSdkReactNative.d.ts +7 -0
- package/lib/typescript/src/NativeAdwhaleSdkReactNative.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +11 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +168 -0
- package/plugin/index.js +16 -0
- package/react-native.config.js +30 -0
- package/src/AdWhaleBannerView.tsx +53 -0
- package/src/AdWhaleInterstitialAd.ts +93 -0
- package/src/AdWhaleMediationSdk.ts +93 -0
- package/src/AdWhaleNativeCustomView.tsx +87 -0
- package/src/AdWhaleNativeTemplateView.tsx +119 -0
- package/src/AdWhaleRewardAd.ts +106 -0
- package/src/NativeAdwhaleSdkReactNative.ts +7 -0
- package/src/index.ts +61 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
package com.adwhalesdkreactnative;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.BaseReactPackage;
|
|
6
|
+
import com.facebook.react.bridge.NativeModule;
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
+
import com.facebook.react.module.model.ReactModuleInfo;
|
|
9
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
10
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
11
|
+
|
|
12
|
+
import java.util.Arrays;
|
|
13
|
+
import java.util.HashMap;
|
|
14
|
+
import java.util.List;
|
|
15
|
+
import java.util.Map;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* React Native New Architecture 적용
|
|
19
|
+
* TurboModule(code gen 모듈) + 기존 NativeModule(전면/보상형) + ViewManager 혼용 구조
|
|
20
|
+
*/
|
|
21
|
+
public class AdwhaleSdkReactNativePackage extends BaseReactPackage {
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
25
|
+
// TurboModule (New Arch용) – initialize 모듈
|
|
26
|
+
if (RNAdWhaleMediationAdSettingModule.REACT_CLASS_NAME.equals(name)) {
|
|
27
|
+
return new RNAdWhaleMediationAdSettingModule(reactContext);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 로거 Old Architecture를 따르지만 등록은 TurboModule로 등록
|
|
31
|
+
if (RNAdWhaleMediationLoggerModule.REACT_CLASS_NAME.equals(name)) {
|
|
32
|
+
return new RNAdWhaleMediationLoggerModule(reactContext);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 전면 Old Architecture를 따르지만 등록은 TurboModule로 등록
|
|
36
|
+
if (RNAdWhaleMediationInterstitialAd.REACT_CLASS_NAME.equals(name)) {
|
|
37
|
+
return new RNAdWhaleMediationInterstitialAd(reactContext);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 보상형 Old Architecture를 따르지만 등록은 TurboModule로 등록
|
|
41
|
+
if (RNAdWhaleMediationRewardAd.REACT_CLASS_NAME.equals(name)) {
|
|
42
|
+
return new RNAdWhaleMediationRewardAd(reactContext);
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@NonNull
|
|
48
|
+
@Override
|
|
49
|
+
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
|
|
50
|
+
// Old Arch + New Arch 브리지에서 사용할 전면/보상형 모듈 등록
|
|
51
|
+
// Old Architecture 앱도 지원하기 위해 그대로 유지
|
|
52
|
+
return Arrays.<NativeModule>asList(
|
|
53
|
+
new RNAdWhaleMediationLoggerModule(reactContext),
|
|
54
|
+
new RNAdWhaleMediationInterstitialAd(reactContext),
|
|
55
|
+
new RNAdWhaleMediationRewardAd(reactContext)
|
|
56
|
+
// RNAdWhaleMediationAdSettingModule는 TurboModule로 등록되므로 여기서 굳이 추가 안 해도 됨
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@NonNull
|
|
61
|
+
@Override
|
|
62
|
+
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
|
|
63
|
+
// 배너 ViewManager
|
|
64
|
+
return Arrays.<ViewManager>asList(
|
|
65
|
+
new RNAdWhaleMediationAdView(),
|
|
66
|
+
new RNAdWhaleMediationTemplateNativeAdView(),
|
|
67
|
+
new RNAdWhaleMediationCustomNativeAdView());
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Override
|
|
71
|
+
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
72
|
+
return () -> {
|
|
73
|
+
Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
|
|
74
|
+
|
|
75
|
+
// TurboModule: RNAdWhaleMediationAdSettingModule
|
|
76
|
+
moduleInfos.put(
|
|
77
|
+
RNAdWhaleMediationAdSettingModule.REACT_CLASS_NAME,
|
|
78
|
+
new ReactModuleInfo(
|
|
79
|
+
RNAdWhaleMediationAdSettingModule.REACT_CLASS_NAME,
|
|
80
|
+
RNAdWhaleMediationAdSettingModule.REACT_CLASS_NAME,
|
|
81
|
+
false, // canOverrideExistingModule
|
|
82
|
+
false, // needsEagerInit
|
|
83
|
+
false, // isCxxModule
|
|
84
|
+
true // isTurboModule
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// 로거/전면/보상형은 legacy 모듈로 사용 (isTurboModule = false)
|
|
89
|
+
moduleInfos.put(
|
|
90
|
+
RNAdWhaleMediationLoggerModule.REACT_CLASS_NAME,
|
|
91
|
+
new ReactModuleInfo(
|
|
92
|
+
RNAdWhaleMediationLoggerModule.REACT_CLASS_NAME,
|
|
93
|
+
RNAdWhaleMediationLoggerModule.REACT_CLASS_NAME,
|
|
94
|
+
false,
|
|
95
|
+
false,
|
|
96
|
+
false,
|
|
97
|
+
false
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// 로거/전면/보상형은 legacy 모듈로 사용 (isTurboModule = false)
|
|
102
|
+
moduleInfos.put(
|
|
103
|
+
RNAdWhaleMediationInterstitialAd.REACT_CLASS_NAME,
|
|
104
|
+
new ReactModuleInfo(
|
|
105
|
+
RNAdWhaleMediationInterstitialAd.REACT_CLASS_NAME,
|
|
106
|
+
RNAdWhaleMediationInterstitialAd.REACT_CLASS_NAME,
|
|
107
|
+
false,
|
|
108
|
+
false,
|
|
109
|
+
false,
|
|
110
|
+
false
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// 로거/전면/보상형은 legacy 모듈로 사용 (isTurboModule = false)
|
|
115
|
+
moduleInfos.put(
|
|
116
|
+
RNAdWhaleMediationRewardAd.REACT_CLASS_NAME,
|
|
117
|
+
new ReactModuleInfo(
|
|
118
|
+
RNAdWhaleMediationRewardAd.REACT_CLASS_NAME,
|
|
119
|
+
RNAdWhaleMediationRewardAd.REACT_CLASS_NAME,
|
|
120
|
+
false,
|
|
121
|
+
false,
|
|
122
|
+
false,
|
|
123
|
+
false
|
|
124
|
+
)
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
return moduleInfos;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationAdSettingModule.java
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package com.adwhalesdkreactnative;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.util.Log;
|
|
5
|
+
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
7
|
+
|
|
8
|
+
import com.facebook.react.bridge.Promise;
|
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
10
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
11
|
+
import com.facebook.react.module.annotations.ReactModule;
|
|
12
|
+
|
|
13
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationAds;
|
|
14
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationOnInitCompleteListener;
|
|
15
|
+
import net.adwhale.sdk.utils.AdWhaleLog;
|
|
16
|
+
|
|
17
|
+
import java.util.HashMap;
|
|
18
|
+
import java.util.Map;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 초기화 모듈은 최신 TurboModule을 적용
|
|
22
|
+
* JS <--> 네이티브 호출이 더 빠르고 타입 안정성이 제공되기 때문
|
|
23
|
+
*/
|
|
24
|
+
@ReactModule(name = RNAdWhaleMediationAdSettingModule.REACT_CLASS_NAME)
|
|
25
|
+
public class RNAdWhaleMediationAdSettingModule extends NativeAdwhaleSdkReactNativeSpec {
|
|
26
|
+
public static final String REACT_CLASS_NAME = "AdwhaleSdkReactNative";
|
|
27
|
+
|
|
28
|
+
public RNAdWhaleMediationAdSettingModule(ReactApplicationContext reactContext) {
|
|
29
|
+
super(reactContext);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Override
|
|
33
|
+
public String getName() {
|
|
34
|
+
return REACT_CLASS_NAME;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
38
|
+
public void initialize(final Promise promise) {
|
|
39
|
+
Log.i(REACT_CLASS_NAME, ".initialize()");
|
|
40
|
+
Activity currentActivity = getCurrentActivity();
|
|
41
|
+
if (currentActivity == null) {
|
|
42
|
+
promise.reject("NO_ACTIVITY", "Unable to initialize AdWhale SDK: No activity available");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
AdWhaleLog.setLogLevel(AdWhaleLog.LogLevel.Verbose);
|
|
47
|
+
|
|
48
|
+
AdWhaleMediationAds.init(currentActivity, new AdWhaleMediationOnInitCompleteListener() {
|
|
49
|
+
@Override
|
|
50
|
+
public void onInitComplete(int statusCode, String message) {
|
|
51
|
+
Log.i(REACT_CLASS_NAME, ".onInitComplete(" + statusCode + ", " + message + ")");
|
|
52
|
+
promise.resolve(statusCode);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Nullable
|
|
58
|
+
@Override
|
|
59
|
+
public Map<String, Object> getConstants() {
|
|
60
|
+
final Map<String, Object> constants = new HashMap<>();
|
|
61
|
+
return constants;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
package com.adwhalesdkreactnative;
|
|
2
|
+
|
|
3
|
+
import android.os.Handler;
|
|
4
|
+
import android.os.Looper;
|
|
5
|
+
import android.util.Log;
|
|
6
|
+
import android.widget.LinearLayout;
|
|
7
|
+
import android.widget.RelativeLayout;
|
|
8
|
+
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
10
|
+
import androidx.annotation.Nullable;
|
|
11
|
+
|
|
12
|
+
import com.facebook.react.bridge.Arguments;
|
|
13
|
+
import com.facebook.react.bridge.ReactContext;
|
|
14
|
+
import com.facebook.react.bridge.WritableMap;
|
|
15
|
+
import com.facebook.react.common.MapBuilder;
|
|
16
|
+
import com.facebook.react.uimanager.ThemedReactContext;
|
|
17
|
+
import com.facebook.react.uimanager.ViewGroupManager;
|
|
18
|
+
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
19
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
20
|
+
|
|
21
|
+
import net.adwhale.sdk.mediation.ads.ADWHALE_AD_SIZE;
|
|
22
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationAdView;
|
|
23
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationAdViewListener;
|
|
24
|
+
|
|
25
|
+
import java.util.Map;
|
|
26
|
+
|
|
27
|
+
public class RNAdWhaleMediationAdView extends ViewGroupManager<RNWrapperView> {
|
|
28
|
+
|
|
29
|
+
public static final String REACT_CLASS_NAME = RNAdWhaleMediationAdView.class.getSimpleName();
|
|
30
|
+
|
|
31
|
+
public RNAdWhaleMediationAdView(){
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@NonNull
|
|
35
|
+
@Override
|
|
36
|
+
public String getName() {
|
|
37
|
+
return REACT_CLASS_NAME;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@NonNull
|
|
41
|
+
@Override
|
|
42
|
+
protected RNWrapperView createViewInstance(@NonNull ThemedReactContext themedReactContext) {
|
|
43
|
+
final RNWrapperView wrapperView = new RNWrapperView(themedReactContext);
|
|
44
|
+
Log.e(REACT_CLASS_NAME, "wrapperView created.");
|
|
45
|
+
Log.i(REACT_CLASS_NAME, "getCurrentActivity(): " + themedReactContext.getCurrentActivity());
|
|
46
|
+
|
|
47
|
+
final AdWhaleMediationAdView adWhaleMediationAdView = new AdWhaleMediationAdView(themedReactContext.getCurrentActivity());
|
|
48
|
+
|
|
49
|
+
adWhaleMediationAdView.setAdWhaleMediationAdViewListener(new AdWhaleMediationAdViewListener() {
|
|
50
|
+
@Override
|
|
51
|
+
public void onAdLoaded() {
|
|
52
|
+
Log.e(REACT_CLASS_NAME, "onAdLoaded()");
|
|
53
|
+
ReactContext context = (ReactContext) wrapperView.getContext();
|
|
54
|
+
if (context != null) {
|
|
55
|
+
context.getJSModule(RCTEventEmitter.class)
|
|
56
|
+
.receiveEvent(wrapperView.getId(),
|
|
57
|
+
"onAdLoaded", null);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Override
|
|
62
|
+
public void onAdLoadFailed(int statusCode, String message) {
|
|
63
|
+
Log.e(REACT_CLASS_NAME, "onAdLoadFailed(" + statusCode + "," + message + ")");
|
|
64
|
+
ReactContext context = (ReactContext) wrapperView.getContext();
|
|
65
|
+
if (context != null) {
|
|
66
|
+
WritableMap params = Arguments.createMap();
|
|
67
|
+
params.putInt("statusCode", statusCode);
|
|
68
|
+
params.putString("message", message);
|
|
69
|
+
context.getJSModule(RCTEventEmitter.class)
|
|
70
|
+
.receiveEvent(wrapperView.getId(),
|
|
71
|
+
"onAdLoadFailed", params);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@Override
|
|
76
|
+
public void onAdClicked() {
|
|
77
|
+
Log.e(REACT_CLASS_NAME, "onAdClicked()");
|
|
78
|
+
ReactContext context = (ReactContext) wrapperView.getContext();
|
|
79
|
+
if (context != null) {
|
|
80
|
+
context.getJSModule(RCTEventEmitter.class)
|
|
81
|
+
.receiveEvent(wrapperView.getId(),
|
|
82
|
+
"onAdClicked", null);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
|
|
88
|
+
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
|
89
|
+
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
|
|
90
|
+
wrapperView.addView(adWhaleMediationAdView, params);
|
|
91
|
+
Log.e(REACT_CLASS_NAME, "adWhaleMediationAdView is attached to wrapperView.");
|
|
92
|
+
|
|
93
|
+
return wrapperView;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@ReactProp(name = "placementUid")
|
|
97
|
+
public void setPlacementUid(RNWrapperView view, String placementUid) {
|
|
98
|
+
AdWhaleMediationAdView adView = getAdWhaleMediationAdView(view);
|
|
99
|
+
if (adView != null) {
|
|
100
|
+
adView.setPlacementUid(placementUid);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@ReactProp(name = "adSize")
|
|
105
|
+
public void setAdSize(RNWrapperView view, String adSizeName) {
|
|
106
|
+
AdWhaleMediationAdView adView = getAdWhaleMediationAdView(view);
|
|
107
|
+
if (adView == null) return;
|
|
108
|
+
|
|
109
|
+
ADWHALE_AD_SIZE adSize = ADWHALE_AD_SIZE.DEFAULT;
|
|
110
|
+
if ("320x50".equals(adSizeName)) {
|
|
111
|
+
adSize = ADWHALE_AD_SIZE.BANNER320x50;
|
|
112
|
+
} else if ("320x100".equals(adSizeName)) {
|
|
113
|
+
adSize = ADWHALE_AD_SIZE.BANNER320x100;
|
|
114
|
+
} else if ("300x250".equals(adSizeName)) {
|
|
115
|
+
adSize = ADWHALE_AD_SIZE.BANNER300x250;
|
|
116
|
+
} else if ("250x250".equals(adSizeName)) {
|
|
117
|
+
adSize = ADWHALE_AD_SIZE.BANNER250x250;
|
|
118
|
+
} else if ("ADAPTIVE_ANCHOR".equals(adSizeName)) {
|
|
119
|
+
adSize = ADWHALE_AD_SIZE.ADAPTIVE_ANCHOR;
|
|
120
|
+
}
|
|
121
|
+
adView.setAdwhaleAdSize(adSize);
|
|
122
|
+
Log.d(REACT_CLASS_NAME, "Ad size set to: " + adSize.name());
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@ReactProp(name = "loadAd")
|
|
126
|
+
public void setLoadAd(RNWrapperView view, boolean loadAd) {
|
|
127
|
+
if (loadAd) {
|
|
128
|
+
AdWhaleMediationAdView adView = getAdWhaleMediationAdView(view);
|
|
129
|
+
if (adView != null) {
|
|
130
|
+
// Delay slightly to ensure placementUid is set
|
|
131
|
+
new Handler(Looper.getMainLooper()).postDelayed(adView::loadAd, 100);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private AdWhaleMediationAdView getAdWhaleMediationAdView(RNWrapperView parent) {
|
|
137
|
+
if (parent != null && parent.getChildCount() > 0 && parent.getChildAt(0) instanceof AdWhaleMediationAdView) {
|
|
138
|
+
return (AdWhaleMediationAdView) parent.getChildAt(0);
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@Override
|
|
144
|
+
public void onDropViewInstance(@NonNull RNWrapperView view) {
|
|
145
|
+
Log.e(REACT_CLASS_NAME, "onDropViewInstance() - cleaning up AdView");
|
|
146
|
+
super.onDropViewInstance(view);
|
|
147
|
+
AdWhaleMediationAdView adView = getAdWhaleMediationAdView(view);
|
|
148
|
+
if (adView != null) {
|
|
149
|
+
adView.destroy();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// The listener methods are now implemented in an anonymous class within createViewInstance
|
|
154
|
+
// and are no longer part of this class, so they are removed from here.
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@Nullable
|
|
158
|
+
@Override
|
|
159
|
+
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
|
|
160
|
+
Log.e(REACT_CLASS_NAME, "getExportedCustomDirectEventTypeConstants()");
|
|
161
|
+
return MapBuilder.<String, Object>builder()
|
|
162
|
+
.put("onAdLoaded",
|
|
163
|
+
MapBuilder.of("registrationName", "onAdLoaded"))
|
|
164
|
+
.put("onAdLoadFailed",
|
|
165
|
+
MapBuilder.of("registrationName", "onAdLoadFailed"))
|
|
166
|
+
.put("onAdClicked",
|
|
167
|
+
MapBuilder.of("registrationName", "onAdClicked"))
|
|
168
|
+
.build();
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationCustomNativeAdView.java
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
package com.adwhalesdkreactnative;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.util.Log;
|
|
5
|
+
import android.view.LayoutInflater;
|
|
6
|
+
import android.view.View;
|
|
7
|
+
|
|
8
|
+
import androidx.annotation.NonNull;
|
|
9
|
+
import androidx.annotation.Nullable;
|
|
10
|
+
|
|
11
|
+
import com.facebook.react.bridge.Arguments;
|
|
12
|
+
import com.facebook.react.bridge.ReactContext;
|
|
13
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
14
|
+
import com.facebook.react.bridge.WritableMap;
|
|
15
|
+
import com.facebook.react.common.MapBuilder;
|
|
16
|
+
import com.facebook.react.uimanager.SimpleViewManager;
|
|
17
|
+
import com.facebook.react.uimanager.ThemedReactContext;
|
|
18
|
+
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
19
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
20
|
+
|
|
21
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationNativeAdView;
|
|
22
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationNativeAdViewListener;
|
|
23
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleNativeAdBinder;
|
|
24
|
+
|
|
25
|
+
import java.util.Map;
|
|
26
|
+
|
|
27
|
+
public class RNAdWhaleMediationCustomNativeAdView extends SimpleViewManager<RNWrapperView> {
|
|
28
|
+
private static final String REACT_CLASS_NAME = RNAdWhaleMediationCustomNativeAdView.class.getSimpleName();
|
|
29
|
+
|
|
30
|
+
public static final int COMMAND_LOAD_AD = 1;
|
|
31
|
+
public static final int COMMAND_SHOW_AD = 2;
|
|
32
|
+
|
|
33
|
+
private String placementUid;
|
|
34
|
+
private String layoutName;
|
|
35
|
+
|
|
36
|
+
@NonNull
|
|
37
|
+
@Override
|
|
38
|
+
public String getName() {
|
|
39
|
+
return REACT_CLASS_NAME;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@NonNull
|
|
43
|
+
@Override
|
|
44
|
+
protected RNWrapperView createViewInstance(@NonNull ThemedReactContext reactContext) {
|
|
45
|
+
return new RNWrapperView(reactContext);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@ReactProp(name = "placementUid")
|
|
49
|
+
public void setPlacementUid(RNWrapperView view, @Nullable String pid) {
|
|
50
|
+
this.placementUid = pid;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@ReactProp(name = "layoutName")
|
|
54
|
+
public void setLayoutName(RNWrapperView view, @Nullable String name) {
|
|
55
|
+
this.layoutName = name;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@Nullable
|
|
59
|
+
@Override
|
|
60
|
+
public Map<String, Integer> getCommandsMap() {
|
|
61
|
+
return MapBuilder.of(
|
|
62
|
+
"loadAd", COMMAND_LOAD_AD,
|
|
63
|
+
"showAd", COMMAND_SHOW_AD
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Nullable
|
|
68
|
+
@Override
|
|
69
|
+
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
|
|
70
|
+
return MapBuilder.of(
|
|
71
|
+
"onAdLoaded", MapBuilder.of("registrationName", "onAdLoaded"),
|
|
72
|
+
"onAdFailedToLoad", MapBuilder.of("registrationName", "onAdFailedToLoad")
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Override
|
|
77
|
+
public void receiveCommand(@NonNull RNWrapperView root, int commandId, @Nullable ReadableArray args) {
|
|
78
|
+
super.receiveCommand(root, commandId, args);
|
|
79
|
+
switch (commandId) {
|
|
80
|
+
case COMMAND_LOAD_AD:
|
|
81
|
+
loadAd(root);
|
|
82
|
+
break;
|
|
83
|
+
case COMMAND_SHOW_AD:
|
|
84
|
+
showAd(root);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private void loadAd(RNWrapperView root) {
|
|
90
|
+
if (placementUid == null || placementUid.isEmpty()) {
|
|
91
|
+
Log.e(REACT_CLASS_NAME, "Placement UID is not set.");
|
|
92
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Placement UID is not set."));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (layoutName == null || layoutName.isEmpty()) {
|
|
97
|
+
Log.e(REACT_CLASS_NAME, "Layout name is not provided from JS.");
|
|
98
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Layout name is not provided from JS."));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
ReactContext reactContext = (ReactContext) root.getContext();
|
|
103
|
+
Activity currentActivity = reactContext.getCurrentActivity();
|
|
104
|
+
|
|
105
|
+
if (currentActivity == null) {
|
|
106
|
+
Log.e(REACT_CLASS_NAME, "Could not get current Activity.");
|
|
107
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Could not get current Activity."));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
int layoutId = currentActivity.getResources().getIdentifier(this.layoutName, "layout", currentActivity.getPackageName());
|
|
112
|
+
|
|
113
|
+
if (layoutId == 0) {
|
|
114
|
+
String errorMessage = "Layout file not found: " + this.layoutName;
|
|
115
|
+
Log.e(REACT_CLASS_NAME, errorMessage);
|
|
116
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, errorMessage));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
currentActivity.runOnUiThread(() -> {
|
|
121
|
+
// Clean up previous ad view if any
|
|
122
|
+
root.removeAllViews();
|
|
123
|
+
|
|
124
|
+
AdWhaleMediationNativeAdView adView = new AdWhaleMediationNativeAdView(currentActivity);
|
|
125
|
+
root.addView(adView); // Add the SDK's view to our wrapper view
|
|
126
|
+
|
|
127
|
+
adView.setAdWhaleMediationNativeAdViewListener(new AdWhaleMediationNativeAdViewListener() {
|
|
128
|
+
@Override
|
|
129
|
+
public void onNativeAdLoaded() {
|
|
130
|
+
Log.d(REACT_CLASS_NAME, "Ad loaded successfully. Ready to show.");
|
|
131
|
+
dispatchEvent(root, "onAdLoaded", null);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@Override
|
|
135
|
+
public void onNativeAdFailedToLoad(int errorCode, String errorMessage) {
|
|
136
|
+
Log.e(REACT_CLASS_NAME, "Ad failed to load: " + errorMessage);
|
|
137
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(errorCode, errorMessage));
|
|
138
|
+
}
|
|
139
|
+
@Override public void onNativeAdClicked() {}
|
|
140
|
+
@Override public void onNativeAdClosed() {}
|
|
141
|
+
@Override public void onNativeAdShowFailed(int i, @NonNull String s) {}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
String packageName = currentActivity.getPackageName();
|
|
145
|
+
AdWhaleNativeAdBinder binder = new AdWhaleNativeAdBinder.Builder(currentActivity, layoutId)
|
|
146
|
+
.setIconViewId(currentActivity.getResources().getIdentifier("view_icon", "id", packageName))
|
|
147
|
+
.setTitleViewId(currentActivity.getResources().getIdentifier("view_title", "id", packageName))
|
|
148
|
+
.setBodyTextViewId(currentActivity.getResources().getIdentifier("view_body", "id", packageName))
|
|
149
|
+
.setCallToActionViewId(currentActivity.getResources().getIdentifier("button_cta", "id", packageName))
|
|
150
|
+
.setMediaViewGroupId(currentActivity.getResources().getIdentifier("view_media", "id", packageName))
|
|
151
|
+
.build();
|
|
152
|
+
|
|
153
|
+
adView.setPlacementUid(placementUid);
|
|
154
|
+
adView.loadAdWithBinder(binder);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private void showAd(RNWrapperView root) {
|
|
159
|
+
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(root);
|
|
160
|
+
if (adView != null) {
|
|
161
|
+
Log.d(REACT_CLASS_NAME, "Calling show().");
|
|
162
|
+
adView.show();
|
|
163
|
+
root.requestLayout();
|
|
164
|
+
} else {
|
|
165
|
+
Log.e(REACT_CLASS_NAME, "AdView not found. Cannot show ad.");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@Override
|
|
170
|
+
public void onDropViewInstance(@NonNull RNWrapperView view) {
|
|
171
|
+
super.onDropViewInstance(view);
|
|
172
|
+
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(view);
|
|
173
|
+
if (adView != null) {
|
|
174
|
+
adView.destroy();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private AdWhaleMediationNativeAdView getAdWhaleMediationNativeAdView(RNWrapperView parent) {
|
|
179
|
+
if (parent != null && parent.getChildCount() > 0 && parent.getChildAt(0) instanceof AdWhaleMediationNativeAdView) {
|
|
180
|
+
return (AdWhaleMediationNativeAdView) parent.getChildAt(0);
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private WritableMap createErrorEvent(int errorCode, String errorMessage) {
|
|
186
|
+
WritableMap event = Arguments.createMap();
|
|
187
|
+
event.putInt("errorCode", errorCode);
|
|
188
|
+
event.putString("errorMessage", errorMessage);
|
|
189
|
+
return event;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private void dispatchEvent(View view, String eventName, @Nullable WritableMap event) {
|
|
193
|
+
ReactContext reactContext = (ReactContext) view.getContext();
|
|
194
|
+
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(view.getId(), eventName, event);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
package com.adwhalesdkreactnative;
|
|
2
|
+
|
|
3
|
+
import android.util.Log;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
7
|
+
|
|
8
|
+
import com.facebook.react.bridge.Arguments;
|
|
9
|
+
import com.facebook.react.bridge.Promise;
|
|
10
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
11
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
12
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
13
|
+
import com.facebook.react.bridge.UiThreadUtil;
|
|
14
|
+
import com.facebook.react.bridge.WritableMap;
|
|
15
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
16
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
17
|
+
|
|
18
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationInterstitialAd;
|
|
19
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleMediationInterstitialAdListener;
|
|
20
|
+
|
|
21
|
+
import java.util.HashMap;
|
|
22
|
+
import java.util.Map;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Old Architecture 를 사용한다.
|
|
26
|
+
* JS <--> 네이티브 모듈 간 왕복 호출이 많지도 않고 성능 상 TurboModule이 꼭 필요하진 않음
|
|
27
|
+
*/
|
|
28
|
+
public class RNAdWhaleMediationInterstitialAd extends ReactContextBaseJavaModule implements AdWhaleMediationInterstitialAdListener {
|
|
29
|
+
|
|
30
|
+
public static final String REACT_CLASS_NAME = RNAdWhaleMediationInterstitialAd.class.getSimpleName();
|
|
31
|
+
private AdWhaleMediationInterstitialAd adWhaleMediationInterstitialAd;
|
|
32
|
+
private String placementUid;
|
|
33
|
+
|
|
34
|
+
public RNAdWhaleMediationInterstitialAd(ReactApplicationContext context) {
|
|
35
|
+
super(context);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@NonNull
|
|
39
|
+
@Override
|
|
40
|
+
public String getName() {
|
|
41
|
+
return REACT_CLASS_NAME;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@ReactMethod
|
|
45
|
+
public void loadAd(String placementUid) {
|
|
46
|
+
Log.e(REACT_CLASS_NAME, ".loadAd()");
|
|
47
|
+
this.placementUid = placementUid;
|
|
48
|
+
adWhaleMediationInterstitialAd = new AdWhaleMediationInterstitialAd(placementUid);
|
|
49
|
+
adWhaleMediationInterstitialAd.setAdWhaleMediationInterstitialAdListener(this);
|
|
50
|
+
|
|
51
|
+
UiThreadUtil.runOnUiThread(() -> {
|
|
52
|
+
adWhaleMediationInterstitialAd.loadAd();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@ReactMethod
|
|
57
|
+
public void showAd() {
|
|
58
|
+
Log.e(REACT_CLASS_NAME, "showAd()");
|
|
59
|
+
if (adWhaleMediationInterstitialAd == null) {
|
|
60
|
+
Log.e(REACT_CLASS_NAME, "adWhaleMediationInterstitialAd is null");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
UiThreadUtil.runOnUiThread(() -> {
|
|
65
|
+
adWhaleMediationInterstitialAd.showAd();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@Override
|
|
70
|
+
public void onAdLoaded() {
|
|
71
|
+
Log.i(REACT_CLASS_NAME, "onAdLoaded()");
|
|
72
|
+
sendEvent("onInterstitialAdLoaded", null);
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Override
|
|
77
|
+
public void onAdLoadFailed(int statusCode, String message) {
|
|
78
|
+
Log.i(REACT_CLASS_NAME, "onAdLoadFailed(" + statusCode + ", " + message + ")");
|
|
79
|
+
WritableMap params = Arguments.createMap();
|
|
80
|
+
params.putInt("statusCode", statusCode);
|
|
81
|
+
params.putString("message", message);
|
|
82
|
+
sendEvent("onInterstitialAdLoadFailed", params);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@Override
|
|
86
|
+
public void onAdShowed() {
|
|
87
|
+
Log.i(REACT_CLASS_NAME, "onAdShowed()");
|
|
88
|
+
sendEvent("onInterstitialAdShowed", null);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Override
|
|
92
|
+
public void onAdShowFailed(int statusCode, String message) {
|
|
93
|
+
Log.i(REACT_CLASS_NAME, "onAdShowFailed(" + statusCode + ", " + message + ")");
|
|
94
|
+
WritableMap params = Arguments.createMap();
|
|
95
|
+
params.putInt("statusCode", statusCode);
|
|
96
|
+
params.putString("message", message);
|
|
97
|
+
sendEvent("onInterstitialAdShowFailed", params);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Override
|
|
101
|
+
public void onAdClosed() {
|
|
102
|
+
Log.i(REACT_CLASS_NAME, "onAdClosed()");
|
|
103
|
+
sendEvent("onInterstitialAdClosed", null);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@Override
|
|
107
|
+
public void onAdClicked() {
|
|
108
|
+
Log.i(REACT_CLASS_NAME, "onAdClicked()");
|
|
109
|
+
sendEvent("onInterstitialAdClicked", null);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Nullable
|
|
113
|
+
@Override
|
|
114
|
+
public Map<String, Object> getConstants() {
|
|
115
|
+
final Map<String, Object> constants = new HashMap<>();
|
|
116
|
+
return constants;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private void sendEvent(String eventName, @Nullable WritableMap params) {
|
|
120
|
+
getReactApplicationContext()
|
|
121
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
122
|
+
.emit(eventName, params);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@ReactMethod
|
|
126
|
+
public void addListener(String eventName) {
|
|
127
|
+
//TODO NOTHING
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@ReactMethod
|
|
131
|
+
public void removeListeners(Integer count) {
|
|
132
|
+
//TODO NOTHING
|
|
133
|
+
}
|
|
134
|
+
}
|