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.
Files changed (66) hide show
  1. package/AdwhaleSdkReactNative.podspec +20 -0
  2. package/LICENSE +20 -0
  3. package/README.md +121 -0
  4. package/android/build.gradle +135 -0
  5. package/android/gradle.properties +2 -0
  6. package/android/proguard-rules.pro +247 -0
  7. package/android/settings.gradle +71 -0
  8. package/android/src/main/AndroidManifest.xml +2 -0
  9. package/android/src/main/java/com/adwhalesdkreactnative/AdwhaleSdkReactNativePackage.java +130 -0
  10. package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationAdSettingModule.java +64 -0
  11. package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationAdView.java +172 -0
  12. package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationCustomNativeAdView.java +197 -0
  13. package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationInterstitialAd.java +134 -0
  14. package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationLoggerModule.java +35 -0
  15. package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationRewardAd.java +151 -0
  16. package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationTemplateNativeAdView.java +317 -0
  17. package/android/src/main/java/com/adwhalesdkreactnative/RNWrapperView.java +48 -0
  18. package/android/src/main/res/layout/custom_native_ad_layout.xml +58 -0
  19. package/app.plugin.js +2 -0
  20. package/ios/AdwhaleSdkReactNative.h +5 -0
  21. package/ios/AdwhaleSdkReactNative.mm +21 -0
  22. package/lib/module/AdWhaleBannerView.js +20 -0
  23. package/lib/module/AdWhaleBannerView.js.map +1 -0
  24. package/lib/module/AdWhaleInterstitialAd.js +47 -0
  25. package/lib/module/AdWhaleInterstitialAd.js.map +1 -0
  26. package/lib/module/AdWhaleMediationSdk.js +48 -0
  27. package/lib/module/AdWhaleMediationSdk.js.map +1 -0
  28. package/lib/module/AdWhaleNativeCustomView.js +36 -0
  29. package/lib/module/AdWhaleNativeCustomView.js.map +1 -0
  30. package/lib/module/AdWhaleNativeTemplateView.js +40 -0
  31. package/lib/module/AdWhaleNativeTemplateView.js.map +1 -0
  32. package/lib/module/AdWhaleRewardAd.js +50 -0
  33. package/lib/module/AdWhaleRewardAd.js.map +1 -0
  34. package/lib/module/NativeAdwhaleSdkReactNative.js +5 -0
  35. package/lib/module/NativeAdwhaleSdkReactNative.js.map +1 -0
  36. package/lib/module/index.js +28 -0
  37. package/lib/module/index.js.map +1 -0
  38. package/lib/module/package.json +1 -0
  39. package/lib/typescript/package.json +1 -0
  40. package/lib/typescript/src/AdWhaleBannerView.d.ts +18 -0
  41. package/lib/typescript/src/AdWhaleBannerView.d.ts.map +1 -0
  42. package/lib/typescript/src/AdWhaleInterstitialAd.d.ts +19 -0
  43. package/lib/typescript/src/AdWhaleInterstitialAd.d.ts.map +1 -0
  44. package/lib/typescript/src/AdWhaleMediationSdk.d.ts +17 -0
  45. package/lib/typescript/src/AdWhaleMediationSdk.d.ts.map +1 -0
  46. package/lib/typescript/src/AdWhaleNativeCustomView.d.ts +19 -0
  47. package/lib/typescript/src/AdWhaleNativeCustomView.d.ts.map +1 -0
  48. package/lib/typescript/src/AdWhaleNativeTemplateView.d.ts +40 -0
  49. package/lib/typescript/src/AdWhaleNativeTemplateView.d.ts.map +1 -0
  50. package/lib/typescript/src/AdWhaleRewardAd.d.ts +24 -0
  51. package/lib/typescript/src/AdWhaleRewardAd.d.ts.map +1 -0
  52. package/lib/typescript/src/NativeAdwhaleSdkReactNative.d.ts +7 -0
  53. package/lib/typescript/src/NativeAdwhaleSdkReactNative.d.ts.map +1 -0
  54. package/lib/typescript/src/index.d.ts +11 -0
  55. package/lib/typescript/src/index.d.ts.map +1 -0
  56. package/package.json +168 -0
  57. package/plugin/index.js +16 -0
  58. package/react-native.config.js +30 -0
  59. package/src/AdWhaleBannerView.tsx +53 -0
  60. package/src/AdWhaleInterstitialAd.ts +93 -0
  61. package/src/AdWhaleMediationSdk.ts +93 -0
  62. package/src/AdWhaleNativeCustomView.tsx +87 -0
  63. package/src/AdWhaleNativeTemplateView.tsx +119 -0
  64. package/src/AdWhaleRewardAd.ts +106 -0
  65. package/src/NativeAdwhaleSdkReactNative.ts +7 -0
  66. 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
+ }
@@ -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
+
@@ -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
+ }