adwhale-sdk-react-native 2.7.202 → 2.7.203
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 +3 -3
- package/android/src/main/java/com/adwhalesdkreactnative/AdwhaleSdkReactNativePackage.java +37 -0
- package/android/src/main/java/com/adwhalesdkreactnative/NativeAdBinderFactory.java +19 -0
- package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationCustomNativeAdView.java +186 -196
- package/android/src/main/java/com/adwhalesdkreactnative/SimpleBinderFactory.java +55 -0
- package/lib/module/{AdWhaleBannerView.js → AdWhaleAdView.js} +3 -3
- package/lib/module/AdWhaleAdView.js.map +1 -0
- package/lib/module/{AdWhaleMediationSdk.js → AdWhaleMediationAds.js} +14 -14
- package/lib/module/{AdWhaleMediationSdk.js.map → AdWhaleMediationAds.js.map} +1 -1
- package/lib/module/index.js +9 -9
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/{AdWhaleBannerView.d.ts → AdWhaleAdView.d.ts} +2 -2
- package/lib/typescript/src/AdWhaleAdView.d.ts.map +1 -0
- package/lib/typescript/src/{AdWhaleMediationSdk.d.ts → AdWhaleMediationAds.d.ts} +2 -2
- package/lib/typescript/src/{AdWhaleMediationSdk.d.ts.map → AdWhaleMediationAds.d.ts.map} +1 -1
- package/lib/typescript/src/AdWhaleNativeCustomView.d.ts +1 -1
- package/lib/typescript/src/AdWhaleNativeCustomView.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 +4 -4
- package/plugin/index.js +14 -367
- package/src/{AdWhaleBannerView.tsx → AdWhaleAdView.tsx} +2 -2
- package/src/{AdWhaleMediationSdk.ts → AdWhaleMediationAds.ts} +13 -13
- package/src/AdWhaleNativeCustomView.tsx +1 -1
- package/src/index.ts +11 -11
- package/android/src/main/res/layout/custom_native_ad_layout.xml +0 -58
- package/lib/module/AdWhaleBannerView.js.map +0 -1
- package/lib/typescript/src/AdWhaleBannerView.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ npm install adwhale-sdk-react-native
|
|
|
43
43
|
운영 안정성을 중시하는 경우
|
|
44
44
|
```json
|
|
45
45
|
{
|
|
46
|
-
"adwhale-sdk-react-native": "~2.7.
|
|
46
|
+
"adwhale-sdk-react-native": "~2.7.203"
|
|
47
47
|
}
|
|
48
48
|
```
|
|
49
49
|
- Android SDK 2.7.2 기반 유지
|
|
@@ -52,7 +52,7 @@ npm install adwhale-sdk-react-native
|
|
|
52
52
|
### 동일한 Android SDK 기반의 최신 RN 수정만 사용
|
|
53
53
|
```json
|
|
54
54
|
{
|
|
55
|
-
"adwhale-sdk-react-native": "^2.7.
|
|
55
|
+
"adwhale-sdk-react-native": "^2.7.203"
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
- Android SDK 2.7.x 범위 내 최신 RN 수정 자동 반영
|
|
@@ -62,7 +62,7 @@ npm install adwhale-sdk-react-native
|
|
|
62
62
|
### 특정 버전을 완전히 고정하여 사용하는 경우
|
|
63
63
|
```json
|
|
64
64
|
{
|
|
65
|
-
"adwhale-sdk-react-native": "2.7.
|
|
65
|
+
"adwhale-sdk-react-native": "2.7.203"
|
|
66
66
|
}
|
|
67
67
|
```
|
|
68
68
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.adwhalesdkreactnative;
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
4
5
|
|
|
5
6
|
import com.facebook.react.BaseReactPackage;
|
|
6
7
|
import com.facebook.react.bridge.NativeModule;
|
|
@@ -13,12 +14,48 @@ import java.util.Arrays;
|
|
|
13
14
|
import java.util.HashMap;
|
|
14
15
|
import java.util.List;
|
|
15
16
|
import java.util.Map;
|
|
17
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* React Native New Architecture 적용
|
|
19
21
|
* TurboModule(code gen 모듈) + 기존 NativeModule(전면/보상형) + ViewManager 혼용 구조
|
|
20
22
|
*/
|
|
21
23
|
public class AdwhaleSdkReactNativePackage extends BaseReactPackage {
|
|
24
|
+
/**
|
|
25
|
+
* factoryId를 키로 하는 BinderFactory 저장소
|
|
26
|
+
*/
|
|
27
|
+
private static final Map<String, NativeAdBinderFactory> binderFactoryMap = new ConcurrentHashMap<>();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 사용자 지정 커스텀 네이티브 레이아웃을 등록합니다.
|
|
31
|
+
* Flutter의 AdWhaleSdkFlutterPlugin.registerBinderFactory와 동일한 기능을 제공합니다.
|
|
32
|
+
*
|
|
33
|
+
* @param factoryId 팩토리 ID (예: "app_custom")
|
|
34
|
+
* @param factory BinderFactory 인스턴스
|
|
35
|
+
*/
|
|
36
|
+
public static void registerBinderFactory(@NonNull String factoryId, @NonNull NativeAdBinderFactory factory) {
|
|
37
|
+
if (factoryId == null || factoryId.isEmpty()) {
|
|
38
|
+
throw new IllegalArgumentException("factoryId cannot be null or empty");
|
|
39
|
+
}
|
|
40
|
+
if (factory == null) {
|
|
41
|
+
throw new IllegalArgumentException("factory cannot be null");
|
|
42
|
+
}
|
|
43
|
+
binderFactoryMap.put(factoryId, factory);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 등록된 BinderFactory를 가져옵니다.
|
|
48
|
+
*
|
|
49
|
+
* @param factoryId 팩토리 ID
|
|
50
|
+
* @return 등록된 BinderFactory 또는 null
|
|
51
|
+
*/
|
|
52
|
+
@Nullable
|
|
53
|
+
public static NativeAdBinderFactory getBinderFactory(@Nullable String factoryId) {
|
|
54
|
+
if (factoryId == null || factoryId.isEmpty()) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return binderFactoryMap.get(factoryId);
|
|
58
|
+
}
|
|
22
59
|
|
|
23
60
|
@Override
|
|
24
61
|
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package com.adwhalesdkreactnative;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import androidx.annotation.NonNull;
|
|
5
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleNativeAdBinder;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 네이티브 광고 바인더를 생성하는 팩토리 인터페이스
|
|
9
|
+
*/
|
|
10
|
+
public interface NativeAdBinderFactory {
|
|
11
|
+
/**
|
|
12
|
+
* AdWhaleNativeAdBinder를 생성합니다.
|
|
13
|
+
*
|
|
14
|
+
* @param activity 현재 Activity
|
|
15
|
+
* @return AdWhaleNativeAdBinder 인스턴스
|
|
16
|
+
*/
|
|
17
|
+
@NonNull
|
|
18
|
+
AdWhaleNativeAdBinder createBinder(@NonNull Activity activity);
|
|
19
|
+
}
|
package/android/src/main/java/com/adwhalesdkreactnative/RNAdWhaleMediationCustomNativeAdView.java
CHANGED
|
@@ -2,7 +2,6 @@ package com.adwhalesdkreactnative;
|
|
|
2
2
|
|
|
3
3
|
import android.app.Activity;
|
|
4
4
|
import android.util.Log;
|
|
5
|
-
import android.view.LayoutInflater;
|
|
6
5
|
import android.view.View;
|
|
7
6
|
|
|
8
7
|
import androidx.annotation.NonNull;
|
|
@@ -27,203 +26,194 @@ import net.adwhale.sdk.mediation.ads.AdWhaleNativeAdBinder;
|
|
|
27
26
|
import java.util.Map;
|
|
28
27
|
|
|
29
28
|
public class RNAdWhaleMediationCustomNativeAdView extends SimpleViewManager<RNWrapperView> {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
29
|
+
private static final String REACT_CLASS_NAME = RNAdWhaleMediationCustomNativeAdView.class.getSimpleName();
|
|
30
|
+
|
|
31
|
+
public static final int COMMAND_LOAD_AD = 1;
|
|
32
|
+
public static final int COMMAND_SHOW_AD = 2;
|
|
33
|
+
|
|
34
|
+
private String placementUid;
|
|
35
|
+
private String factoryId;
|
|
36
|
+
private String placementName;
|
|
37
|
+
|
|
38
|
+
@NonNull
|
|
39
|
+
@Override
|
|
40
|
+
public String getName() {
|
|
41
|
+
return REACT_CLASS_NAME;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@NonNull
|
|
45
|
+
@Override
|
|
46
|
+
protected RNWrapperView createViewInstance(@NonNull ThemedReactContext reactContext) {
|
|
47
|
+
return new RNWrapperView(reactContext);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@ReactProp(name = "placementUid")
|
|
51
|
+
public void setPlacementUid(RNWrapperView view, @Nullable String pid) {
|
|
52
|
+
this.placementUid = pid;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@ReactProp(name = "factoryId")
|
|
56
|
+
public void setFactoryId(RNWrapperView view, @Nullable String id) {
|
|
57
|
+
this.factoryId = id;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@ReactProp(name = "placementName")
|
|
62
|
+
public void setPlacementName(RNWrapperView view, String placementName) {
|
|
63
|
+
Log.e(REACT_CLASS_NAME, "placementName: " + placementName);
|
|
64
|
+
this.placementName = placementName;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@ReactProp(name = "region")
|
|
68
|
+
public void setRegion(RNWrapperView view, String region) {
|
|
69
|
+
Log.e(REACT_CLASS_NAME, "region: " + region);
|
|
70
|
+
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(view);
|
|
71
|
+
if (adView != null) {
|
|
72
|
+
adView.setRegion(region);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@ReactProp(name = "gcoder")
|
|
77
|
+
public void setGcoder(RNWrapperView view, ReadableMap gcoderMap) {
|
|
78
|
+
Log.e(REACT_CLASS_NAME, "gcoderMap: " + gcoderMap);
|
|
79
|
+
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(view);
|
|
80
|
+
|
|
81
|
+
if (adView != null && gcoderMap != null) {
|
|
82
|
+
double lt = gcoderMap.hasKey("lt") ? gcoderMap.getDouble("lt") : 0.0;
|
|
83
|
+
double lng = gcoderMap.hasKey("lng") ? gcoderMap.getDouble("lng") : 0.0;
|
|
84
|
+
|
|
85
|
+
adView.setGcoder(lt, lng);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@Nullable
|
|
90
|
+
@Override
|
|
91
|
+
public Map<String, Integer> getCommandsMap() {
|
|
92
|
+
return MapBuilder.of(
|
|
93
|
+
"loadAd", COMMAND_LOAD_AD,
|
|
94
|
+
"showAd", COMMAND_SHOW_AD
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@Nullable
|
|
99
|
+
@Override
|
|
100
|
+
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
|
|
101
|
+
return MapBuilder.of(
|
|
102
|
+
"onAdLoaded", MapBuilder.of("registrationName", "onAdLoaded"),
|
|
103
|
+
"onAdFailedToLoad", MapBuilder.of("registrationName", "onAdFailedToLoad")
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Override
|
|
108
|
+
public void receiveCommand(@NonNull RNWrapperView root, int commandId, @Nullable ReadableArray args) {
|
|
109
|
+
super.receiveCommand(root, commandId, args);
|
|
110
|
+
switch (commandId) {
|
|
111
|
+
case COMMAND_LOAD_AD:
|
|
112
|
+
loadAd(root);
|
|
113
|
+
break;
|
|
114
|
+
case COMMAND_SHOW_AD:
|
|
115
|
+
showAd(root);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private void loadAd(RNWrapperView root) {
|
|
121
|
+
if (placementUid == null || placementUid.isEmpty()) {
|
|
122
|
+
Log.e(REACT_CLASS_NAME, "Placement UID is not set.");
|
|
123
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Placement UID is not set."));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (factoryId == null || factoryId.isEmpty()) {
|
|
128
|
+
Log.e(REACT_CLASS_NAME, "Factory ID is not set.");
|
|
129
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Factory ID is not set."));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
ReactContext reactContext = (ReactContext) root.getContext();
|
|
134
|
+
Activity currentActivity = reactContext.getCurrentActivity();
|
|
135
|
+
|
|
136
|
+
if (currentActivity == null) {
|
|
137
|
+
Log.e(REACT_CLASS_NAME, "Could not get current Activity.");
|
|
138
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Could not get current Activity."));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
NativeAdBinderFactory binderFactory = AdwhaleSdkReactNativePackage.getBinderFactory(factoryId);
|
|
143
|
+
if (binderFactory == null) {
|
|
144
|
+
String errorMessage = "BinderFactory not found for factoryId: " + factoryId;
|
|
145
|
+
Log.e(REACT_CLASS_NAME, errorMessage);
|
|
146
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, errorMessage));
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
currentActivity.runOnUiThread(() -> {
|
|
151
|
+
// Clean up previous ad view if any
|
|
152
|
+
root.removeAllViews();
|
|
153
|
+
|
|
154
|
+
AdWhaleMediationNativeAdView adView = new AdWhaleMediationNativeAdView(currentActivity);
|
|
155
|
+
root.addView(adView); // Add the SDK's view to our wrapper view
|
|
156
|
+
|
|
157
|
+
adView.setAdWhaleMediationNativeAdViewListener(new AdWhaleMediationNativeAdViewListener() {
|
|
158
|
+
@Override
|
|
159
|
+
public void onNativeAdLoaded() {
|
|
160
|
+
Log.d(REACT_CLASS_NAME, "Ad loaded successfully. Ready to show.");
|
|
161
|
+
dispatchEvent(root, "onAdLoaded", null);
|
|
118
162
|
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
private void loadAd(RNWrapperView root) {
|
|
122
|
-
if (placementUid == null || placementUid.isEmpty()) {
|
|
123
|
-
Log.e(REACT_CLASS_NAME, "Placement UID is not set.");
|
|
124
|
-
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Placement UID is not set."));
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (layoutName == null || layoutName.isEmpty()) {
|
|
129
|
-
Log.e(REACT_CLASS_NAME, "Layout name is not provided from JS.");
|
|
130
|
-
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Layout name is not provided from JS."));
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
ReactContext reactContext = (ReactContext) root.getContext();
|
|
135
|
-
Activity currentActivity = reactContext.getCurrentActivity();
|
|
136
|
-
|
|
137
|
-
if (currentActivity == null) {
|
|
138
|
-
Log.e(REACT_CLASS_NAME, "Could not get current Activity.");
|
|
139
|
-
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, "Could not get current Activity."));
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
int layoutId = currentActivity.getResources().getIdentifier(this.layoutName, "layout", currentActivity.getPackageName());
|
|
144
|
-
|
|
145
|
-
if (layoutId == 0) {
|
|
146
|
-
String errorMessage = "Layout file not found: " + this.layoutName;
|
|
147
|
-
Log.e(REACT_CLASS_NAME, errorMessage);
|
|
148
|
-
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(-1, errorMessage));
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
currentActivity.runOnUiThread(() -> {
|
|
153
|
-
// Clean up previous ad view if any
|
|
154
|
-
root.removeAllViews();
|
|
155
|
-
|
|
156
|
-
AdWhaleMediationNativeAdView adView = new AdWhaleMediationNativeAdView(currentActivity);
|
|
157
|
-
root.addView(adView); // Add the SDK's view to our wrapper view
|
|
158
|
-
|
|
159
|
-
adView.setAdWhaleMediationNativeAdViewListener(new AdWhaleMediationNativeAdViewListener() {
|
|
160
|
-
@Override
|
|
161
|
-
public void onNativeAdLoaded() {
|
|
162
|
-
Log.d(REACT_CLASS_NAME, "Ad loaded successfully. Ready to show.");
|
|
163
|
-
dispatchEvent(root, "onAdLoaded", null);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
@Override
|
|
167
|
-
public void onNativeAdFailedToLoad(int errorCode, String errorMessage) {
|
|
168
|
-
Log.e(REACT_CLASS_NAME, "Ad failed to load: " + errorMessage);
|
|
169
|
-
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(errorCode, errorMessage));
|
|
170
|
-
}
|
|
171
|
-
@Override public void onNativeAdClicked() {}
|
|
172
|
-
@Override public void onNativeAdClosed() {}
|
|
173
|
-
@Override public void onNativeAdShowFailed(int i, @NonNull String s) {}
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
String packageName = currentActivity.getPackageName();
|
|
177
|
-
AdWhaleNativeAdBinder binder = new AdWhaleNativeAdBinder.Builder(currentActivity, layoutId)
|
|
178
|
-
.setIconViewId(currentActivity.getResources().getIdentifier("view_icon", "id", packageName))
|
|
179
|
-
.setTitleViewId(currentActivity.getResources().getIdentifier("view_title", "id", packageName))
|
|
180
|
-
.setBodyTextViewId(currentActivity.getResources().getIdentifier("view_body", "id", packageName))
|
|
181
|
-
.setCallToActionViewId(currentActivity.getResources().getIdentifier("button_cta", "id", packageName))
|
|
182
|
-
.setMediaViewGroupId(currentActivity.getResources().getIdentifier("view_media", "id", packageName))
|
|
183
|
-
.build();
|
|
184
|
-
|
|
185
|
-
adView.setPlacementUid(placementUid);
|
|
186
|
-
adView.loadAdWithBinder(binder);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
private void showAd(RNWrapperView root) {
|
|
191
|
-
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(root);
|
|
192
|
-
if (adView != null) {
|
|
193
|
-
Log.d(REACT_CLASS_NAME, "Calling show().");
|
|
194
|
-
adView.show();
|
|
195
|
-
root.requestLayout();
|
|
196
|
-
} else {
|
|
197
|
-
Log.e(REACT_CLASS_NAME, "AdView not found. Cannot show ad.");
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
@Override
|
|
202
|
-
public void onDropViewInstance(@NonNull RNWrapperView view) {
|
|
203
|
-
super.onDropViewInstance(view);
|
|
204
|
-
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(view);
|
|
205
|
-
if (adView != null) {
|
|
206
|
-
adView.destroy();
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
163
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
164
|
+
@Override
|
|
165
|
+
public void onNativeAdFailedToLoad(int errorCode, String errorMessage) {
|
|
166
|
+
Log.e(REACT_CLASS_NAME, "Ad failed to load: " + errorMessage);
|
|
167
|
+
dispatchEvent(root, "onAdFailedToLoad", createErrorEvent(errorCode, errorMessage));
|
|
213
168
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
169
|
+
@Override public void onNativeAdClicked() {}
|
|
170
|
+
@Override public void onNativeAdClosed() {}
|
|
171
|
+
@Override public void onNativeAdShowFailed(int i, @NonNull String s) {}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
AdWhaleNativeAdBinder binder = binderFactory.createBinder(currentActivity);
|
|
175
|
+
adView.setPlacementUid(placementUid);
|
|
176
|
+
adView.loadAdWithBinder(binder);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private void showAd(RNWrapperView root) {
|
|
181
|
+
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(root);
|
|
182
|
+
if (adView != null) {
|
|
183
|
+
Log.d(REACT_CLASS_NAME, "Calling show().");
|
|
184
|
+
adView.show();
|
|
185
|
+
root.requestLayout();
|
|
186
|
+
} else {
|
|
187
|
+
Log.e(REACT_CLASS_NAME, "AdView not found. Cannot show ad.");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@Override
|
|
192
|
+
public void onDropViewInstance(@NonNull RNWrapperView view) {
|
|
193
|
+
super.onDropViewInstance(view);
|
|
194
|
+
AdWhaleMediationNativeAdView adView = getAdWhaleMediationNativeAdView(view);
|
|
195
|
+
if (adView != null) {
|
|
196
|
+
adView.destroy();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private AdWhaleMediationNativeAdView getAdWhaleMediationNativeAdView(RNWrapperView parent) {
|
|
201
|
+
if (parent != null && parent.getChildCount() > 0 && parent.getChildAt(0) instanceof AdWhaleMediationNativeAdView) {
|
|
202
|
+
return (AdWhaleMediationNativeAdView) parent.getChildAt(0);
|
|
203
|
+
}
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private WritableMap createErrorEvent(int errorCode, String errorMessage) {
|
|
208
|
+
WritableMap event = Arguments.createMap();
|
|
209
|
+
event.putInt("errorCode", errorCode);
|
|
210
|
+
event.putString("errorMessage", errorMessage);
|
|
211
|
+
return event;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private void dispatchEvent(View view, String eventName, @Nullable WritableMap event) {
|
|
215
|
+
ReactContext reactContext = (ReactContext) view.getContext();
|
|
216
|
+
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(view.getId(), eventName, event);
|
|
217
|
+
}
|
|
228
218
|
}
|
|
229
219
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
package com.adwhalesdkreactnative;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import androidx.annotation.NonNull;
|
|
5
|
+
import net.adwhale.sdk.mediation.ads.AdWhaleNativeAdBinder;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 간단한 네이티브 광고 바인더 팩토리 구현
|
|
9
|
+
* 레이아웃 리소스 ID와 각 View ID를 받아서 AdWhaleNativeAdBinder를 생성합니다.
|
|
10
|
+
*/
|
|
11
|
+
public class SimpleBinderFactory implements NativeAdBinderFactory {
|
|
12
|
+
private final int layoutId;
|
|
13
|
+
private final int iconViewId;
|
|
14
|
+
private final int titleViewId;
|
|
15
|
+
private final int bodyTextViewId;
|
|
16
|
+
private final int callToActionViewId;
|
|
17
|
+
private final int mediaViewGroupId;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* SimpleBinderFactory 생성자
|
|
21
|
+
*
|
|
22
|
+
* @param layoutId 레이아웃 리소스 ID (예: R.layout.custom_native_ad_main_layout)
|
|
23
|
+
* @param iconViewId 아이콘 View ID (예: R.id.main_view_icon)
|
|
24
|
+
* @param titleViewId 제목 View ID (예: R.id.main_view_title)
|
|
25
|
+
* @param bodyTextViewId 본문 View ID (예: R.id.main_view_body)
|
|
26
|
+
* @param callToActionViewId CTA 버튼 View ID (예: R.id.main_button_cta)
|
|
27
|
+
* @param mediaViewGroupId 미디어 View ID (예: R.id.main_view_media)
|
|
28
|
+
*/
|
|
29
|
+
public SimpleBinderFactory(
|
|
30
|
+
int layoutId,
|
|
31
|
+
int iconViewId,
|
|
32
|
+
int titleViewId,
|
|
33
|
+
int bodyTextViewId,
|
|
34
|
+
int callToActionViewId,
|
|
35
|
+
int mediaViewGroupId) {
|
|
36
|
+
this.layoutId = layoutId;
|
|
37
|
+
this.iconViewId = iconViewId;
|
|
38
|
+
this.titleViewId = titleViewId;
|
|
39
|
+
this.bodyTextViewId = bodyTextViewId;
|
|
40
|
+
this.callToActionViewId = callToActionViewId;
|
|
41
|
+
this.mediaViewGroupId = mediaViewGroupId;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@NonNull
|
|
45
|
+
@Override
|
|
46
|
+
public AdWhaleNativeAdBinder createBinder(@NonNull Activity activity) {
|
|
47
|
+
return new AdWhaleNativeAdBinder.Builder(activity, layoutId)
|
|
48
|
+
.setIconViewId(iconViewId)
|
|
49
|
+
.setTitleViewId(titleViewId)
|
|
50
|
+
.setBodyTextViewId(bodyTextViewId)
|
|
51
|
+
.setCallToActionViewId(callToActionViewId)
|
|
52
|
+
.setMediaViewGroupId(mediaViewGroupId)
|
|
53
|
+
.build();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
// src/
|
|
3
|
+
// src/AdWhaleAdView.tsx
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { requireNativeComponent } from 'react-native';
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
const RNAdWhaleMediationAdView = requireNativeComponent('RNAdWhaleMediationAdView');
|
|
8
|
-
export const
|
|
8
|
+
export const AdWhaleAdView = ({
|
|
9
9
|
onAdLoadFailed,
|
|
10
10
|
...restProps
|
|
11
11
|
}) => {
|
|
@@ -17,4 +17,4 @@ export const AdWhaleBannerView = ({
|
|
|
17
17
|
onAdLoadFailed: onAdLoadFailed ? handleAdLoadFailed : undefined
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
//# sourceMappingURL=
|
|
20
|
+
//# sourceMappingURL=AdWhaleAdView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","requireNativeComponent","jsx","_jsx","RNAdWhaleMediationAdView","AdWhaleAdView","onAdLoadFailed","restProps","handleAdLoadFailed","e","nativeEvent","undefined"],"sourceRoot":"../../src","sources":["AdWhaleAdView.tsx"],"mappings":";;AAAA;AACA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,sBAAsB,QAAQ,cAAc;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAyCtD,MAAMC,wBAAwB,GAC5BH,sBAAsB,CAAoB,0BAA0B,CAAC;AAEvE,OAAO,MAAMI,aAA+C,GAAGA,CAAC;EAC9DC,cAAc;EACd,GAAGC;AACL,CAAC,KAAK;EACJ,MAAMC,kBAAuD,GAAGC,CAAC,IAAI;IACnEH,cAAc,GAAGG,CAAC,CAACC,WAAW,CAAC;EACjC,CAAC;EAED,oBACEP,IAAA,CAACC,wBAAwB;IAAA,GACnBG,SAAS;IACbD,cAAc,EAAEA,cAAc,GAAGE,kBAAkB,GAAGG;EAAU,CACjE,CAAC;AAEN,CAAC","ignoreList":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
// src/
|
|
3
|
+
// src/AdWhaleMediationAds.ts
|
|
4
4
|
import { NativeModules, Platform } from 'react-native';
|
|
5
5
|
import NativeAdwhaleSdkReactNative from "./NativeAdwhaleSdkReactNative.js";
|
|
6
6
|
const LINKING_ERROR = `AdWhale Mediation SDK native modules not linked.\n` + `Make sure:\n` + ` • Android: AdwhaleSdkReactNative / RNAdWhaleMediationLoggerModule 등록 여부\n` + ` • iOS: Pod install 및 빌드 완료 여부\n` + ` • Web 환경에서 실행 중이 아닌지\n` + `Platform: ${Platform.OS}`;
|
|
@@ -13,7 +13,7 @@ const AdwhaleSdkReactNative = NativeAdwhaleSdkReactNative;
|
|
|
13
13
|
if (!AdwhaleSdkReactNative) {
|
|
14
14
|
console.warn(LINKING_ERROR);
|
|
15
15
|
} else {
|
|
16
|
-
console.log('[
|
|
16
|
+
console.log('[AdWhaleMediationAds] Native module linked:', {
|
|
17
17
|
hasInitialize: !!AdwhaleSdkReactNative.initialize,
|
|
18
18
|
hasRequestGdprConsent: !!AdwhaleSdkReactNative.requestGdprConsent,
|
|
19
19
|
hasGetConsentStatus: !!AdwhaleSdkReactNative.getConsentStatus,
|
|
@@ -22,7 +22,7 @@ if (!AdwhaleSdkReactNative) {
|
|
|
22
22
|
hasSetCoppa: !!AdwhaleSdkReactNative.setCoppa
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
-
export const
|
|
25
|
+
export const AdWhaleMediationAds = {
|
|
26
26
|
initialize() {
|
|
27
27
|
if (!AdwhaleSdkReactNative?.initialize) {
|
|
28
28
|
return Promise.reject(new Error(LINKING_ERROR));
|
|
@@ -39,46 +39,46 @@ export const AdWhaleMediationSdk = {
|
|
|
39
39
|
return RNAdWhaleMediationLoggerModule.getLogLevel();
|
|
40
40
|
},
|
|
41
41
|
setCoppa(enabled) {
|
|
42
|
-
console.log('[
|
|
42
|
+
console.log('[AdWhaleMediationAds] setCoppa called:', enabled);
|
|
43
43
|
if (!AdwhaleSdkReactNative?.setCoppa) {
|
|
44
|
-
console.warn('[
|
|
44
|
+
console.warn('[AdWhaleMediationAds] setCoppa is not implemented in native module');
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
AdwhaleSdkReactNative.setCoppa(enabled);
|
|
48
48
|
},
|
|
49
49
|
requestGdprConsent() {
|
|
50
|
-
console.log('[
|
|
50
|
+
console.log('[AdWhaleMediationAds] requestGdprConsent called');
|
|
51
51
|
if (!AdwhaleSdkReactNative?.requestGdprConsent) {
|
|
52
52
|
const error = new Error('requestGdprConsent is not implemented in native module');
|
|
53
|
-
console.error('[
|
|
53
|
+
console.error('[AdWhaleMediationAds]', error);
|
|
54
54
|
return Promise.reject(error);
|
|
55
55
|
}
|
|
56
56
|
return AdwhaleSdkReactNative.requestGdprConsent();
|
|
57
57
|
},
|
|
58
58
|
getConsentStatus() {
|
|
59
|
-
console.log('[
|
|
59
|
+
console.log('[AdWhaleMediationAds] getConsentStatus called');
|
|
60
60
|
if (!AdwhaleSdkReactNative?.getConsentStatus) {
|
|
61
61
|
const error = new Error('getConsentStatus is not implemented in native module');
|
|
62
|
-
console.error('[
|
|
62
|
+
console.error('[AdWhaleMediationAds]', error);
|
|
63
63
|
return Promise.reject(error);
|
|
64
64
|
}
|
|
65
65
|
return AdwhaleSdkReactNative.getConsentStatus();
|
|
66
66
|
},
|
|
67
67
|
resetGdprConsentStatus() {
|
|
68
|
-
console.log('[
|
|
68
|
+
console.log('[AdWhaleMediationAds] resetGdprConsentStatus called');
|
|
69
69
|
if (!AdwhaleSdkReactNative?.resetGdprConsentStatus) {
|
|
70
|
-
console.warn('[
|
|
70
|
+
console.warn('[AdWhaleMediationAds] resetGdprConsentStatus is not implemented in native module');
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
AdwhaleSdkReactNative.resetGdprConsentStatus();
|
|
74
74
|
},
|
|
75
75
|
setGdpr(consent) {
|
|
76
|
-
console.log('[
|
|
76
|
+
console.log('[AdWhaleMediationAds] setGdpr called:', consent);
|
|
77
77
|
if (!AdwhaleSdkReactNative?.setGdpr) {
|
|
78
|
-
console.warn('[
|
|
78
|
+
console.warn('[AdWhaleMediationAds] setGdpr is not implemented in native module');
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
AdwhaleSdkReactNative.setGdpr(consent);
|
|
82
82
|
}
|
|
83
83
|
};
|
|
84
|
-
//# sourceMappingURL=
|
|
84
|
+
//# sourceMappingURL=AdWhaleMediationAds.js.map
|