cordova-plugin-admob-nextgen 1.0.0
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/LICENSE +21 -0
- package/README.md +458 -0
- package/capacitor-hook-admob-ids.js +109 -0
- package/package.json +42 -0
- package/plugin.xml +53 -0
- package/src/android/AdMobNextGen.java +306 -0
- package/src/android/AppOpenAdExecutor.java +246 -0
- package/src/android/BannerExecutor.java +447 -0
- package/src/android/BannerPreloadExecutor.java +364 -0
- package/src/android/ConsentExecutor.java +279 -0
- package/src/android/GlobalSettingsExecutor.java +139 -0
- package/src/android/InterstitialExecutor.java +223 -0
- package/src/android/NativeExecutor.java +422 -0
- package/src/android/RewardedExecutor.java +239 -0
- package/src/android/RewardedInterstitialExecutor.java +210 -0
- package/src/android/hooks/admob-nextgen.gradle +12 -0
- package/www/admob-nextgen.js +118 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
package com.emi.cordova.admob.nextgen;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.os.Bundle;
|
|
5
|
+
import android.util.DisplayMetrics;
|
|
6
|
+
import android.util.Log;
|
|
7
|
+
import android.view.View;
|
|
8
|
+
import android.view.ViewGroup;
|
|
9
|
+
import android.widget.RelativeLayout;
|
|
10
|
+
|
|
11
|
+
import androidx.annotation.NonNull;
|
|
12
|
+
|
|
13
|
+
import org.apache.cordova.CallbackContext;
|
|
14
|
+
import org.apache.cordova.CordovaInterface;
|
|
15
|
+
import org.apache.cordova.CordovaWebView;
|
|
16
|
+
import org.json.JSONArray;
|
|
17
|
+
import org.json.JSONException;
|
|
18
|
+
import org.json.JSONObject;
|
|
19
|
+
|
|
20
|
+
import com.google.android.libraries.ads.mobile.sdk.banner.AdSize;
|
|
21
|
+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAd;
|
|
22
|
+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdEventCallback;
|
|
23
|
+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdPreloader;
|
|
24
|
+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdRefreshCallback;
|
|
25
|
+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdRequest;
|
|
26
|
+
import com.google.android.libraries.ads.mobile.sdk.common.AdValue;
|
|
27
|
+
import com.google.android.libraries.ads.mobile.sdk.common.FullScreenContentError;
|
|
28
|
+
import com.google.android.libraries.ads.mobile.sdk.common.LoadAdError;
|
|
29
|
+
import com.google.android.libraries.ads.mobile.sdk.common.PreloadCallback;
|
|
30
|
+
import com.google.android.libraries.ads.mobile.sdk.common.PreloadConfiguration;
|
|
31
|
+
import com.google.android.libraries.ads.mobile.sdk.common.ResponseInfo;
|
|
32
|
+
|
|
33
|
+
public class BannerPreloadExecutor {
|
|
34
|
+
|
|
35
|
+
private static final String TAG = "AdMobBannerPreload";
|
|
36
|
+
private CordovaInterface cordova;
|
|
37
|
+
private CordovaWebView webView;
|
|
38
|
+
|
|
39
|
+
private RelativeLayout adLayout;
|
|
40
|
+
private BannerAd currentBannerAd;
|
|
41
|
+
|
|
42
|
+
private boolean isPreloaderActive = false;
|
|
43
|
+
private String currentAdUnitId;
|
|
44
|
+
|
|
45
|
+
private String currentPosition = "bottom";
|
|
46
|
+
private boolean isOverlapping = true;
|
|
47
|
+
|
|
48
|
+
public BannerPreloadExecutor(CordovaInterface cordova, CordovaWebView webView) {
|
|
49
|
+
this.cordova = cordova;
|
|
50
|
+
this.webView = webView;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public void startPreload(JSONArray args, CallbackContext callbackContext) {
|
|
54
|
+
try {
|
|
55
|
+
JSONObject options = args.getJSONObject(0);
|
|
56
|
+
String adUnitId = options.getString("adUnitId");
|
|
57
|
+
|
|
58
|
+
if (isPreloaderActive && adUnitId.equals(currentAdUnitId)) {
|
|
59
|
+
callbackContext.success("Preloader already active");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
isPreloaderActive = true;
|
|
64
|
+
this.currentAdUnitId = adUnitId;
|
|
65
|
+
|
|
66
|
+
String requestedSize = "ADAPTIVE";
|
|
67
|
+
if (options.has("size")) requestedSize = options.getString("size");
|
|
68
|
+
|
|
69
|
+
boolean isCollapsible = false;
|
|
70
|
+
if (options.has("collapsible")) isCollapsible = options.getBoolean("collapsible");
|
|
71
|
+
|
|
72
|
+
String preloadPosition = "bottom";
|
|
73
|
+
if (options.has("position")) preloadPosition = options.getString("position");
|
|
74
|
+
|
|
75
|
+
final String finalSizeStr = requestedSize;
|
|
76
|
+
final boolean finalIsCollapsible = isCollapsible;
|
|
77
|
+
final String finalPosition = preloadPosition;
|
|
78
|
+
|
|
79
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
80
|
+
Context context = cordova.getActivity();
|
|
81
|
+
AdSize adSize = getAdSize(context, finalSizeStr);
|
|
82
|
+
|
|
83
|
+
BannerAdRequest.Builder requestBuilder = new BannerAdRequest.Builder(adUnitId, adSize);
|
|
84
|
+
|
|
85
|
+
if (finalIsCollapsible) {
|
|
86
|
+
Bundle extras = new Bundle();
|
|
87
|
+
String anchor = "top".equalsIgnoreCase(finalPosition) ? "top" : "bottom";
|
|
88
|
+
extras.putString("collapsible", anchor);
|
|
89
|
+
requestBuilder.setGoogleExtrasBundle(extras);
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
BannerAdRequest adRequest = requestBuilder.build();
|
|
94
|
+
PreloadConfiguration preloadConfig = new PreloadConfiguration(adRequest);
|
|
95
|
+
|
|
96
|
+
PreloadCallback preloadCallback = new PreloadCallback() {
|
|
97
|
+
@Override
|
|
98
|
+
public void onAdPreloaded(@NonNull String preloadId, @NonNull ResponseInfo responseInfo) {
|
|
99
|
+
|
|
100
|
+
fireEvent("on.preload.available", null);
|
|
101
|
+
}
|
|
102
|
+
@Override
|
|
103
|
+
public void onAdFailedToPreload(@NonNull String preloadId, @NonNull LoadAdError loadAdError) {
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
JSONObject err = new JSONObject();
|
|
107
|
+
err.put("message", loadAdError.getMessage());
|
|
108
|
+
fireEvent("on.preload.failed", err);
|
|
109
|
+
} catch (JSONException e) {}
|
|
110
|
+
}
|
|
111
|
+
@Override
|
|
112
|
+
public void onAdsExhausted(@NonNull String preloadId) {
|
|
113
|
+
|
|
114
|
+
fireEvent("on.preload.exhausted", null);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
BannerAdPreloader.start(adUnitId, preloadConfig, preloadCallback);
|
|
119
|
+
|
|
120
|
+
callbackContext.success("Preloader Started");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
} catch (JSONException e) {
|
|
124
|
+
isPreloaderActive = false;
|
|
125
|
+
callbackContext.error(e.getMessage());
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public void showPolledAd(JSONArray args, CallbackContext callbackContext) {
|
|
130
|
+
try {
|
|
131
|
+
JSONObject options = args.getJSONObject(0);
|
|
132
|
+
String adUnitId = options.getString("adUnitId");
|
|
133
|
+
|
|
134
|
+
if (options.has("position")) this.currentPosition = options.getString("position");
|
|
135
|
+
if (options.has("isOverlapping")) this.isOverlapping = options.getBoolean("isOverlapping");
|
|
136
|
+
|
|
137
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
138
|
+
BannerAd ad = BannerAdPreloader.pollAd(adUnitId);
|
|
139
|
+
|
|
140
|
+
if (ad == null) {
|
|
141
|
+
|
|
142
|
+
callbackContext.error("Pool Empty");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
destroyCurrentBanner();
|
|
147
|
+
this.currentBannerAd = ad;
|
|
148
|
+
|
|
149
|
+
setupAdEvents(ad);
|
|
150
|
+
|
|
151
|
+
renderBannerView(ad);
|
|
152
|
+
|
|
153
|
+
sendLoadedEvent(ad.getAdSize(), ad.isCollapsible());
|
|
154
|
+
|
|
155
|
+
callbackContext.success("Ad Shown from Pool");
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
} catch (JSONException e) {
|
|
159
|
+
callbackContext.error(e.getMessage());
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private void setupAdEvents(BannerAd ad) {
|
|
164
|
+
|
|
165
|
+
ad.setAdEventCallback(new BannerAdEventCallback() {
|
|
166
|
+
@Override
|
|
167
|
+
public void onAdImpression() {
|
|
168
|
+
fireEvent("on.banner.impression", null);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@Override
|
|
172
|
+
public void onAdClicked() {
|
|
173
|
+
fireEvent("on.banner.clicked", null);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@Override
|
|
177
|
+
public void onAdPaid(@NonNull AdValue adValue) {
|
|
178
|
+
try {
|
|
179
|
+
JSONObject data = new JSONObject();
|
|
180
|
+
data.put("value", adValue.getValueMicros());
|
|
181
|
+
data.put("currency", adValue.getCurrencyCode());
|
|
182
|
+
data.put("precision", adValue.getPrecisionType());
|
|
183
|
+
data.put("source", "preloader");
|
|
184
|
+
fireEvent("on.banner.revenue", data);
|
|
185
|
+
} catch (JSONException e) {}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@Override
|
|
189
|
+
public void onAdShowedFullScreenContent() {
|
|
190
|
+
|
|
191
|
+
fireEvent("on.banner.opened", null);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@Override
|
|
195
|
+
public void onAdDismissedFullScreenContent() {
|
|
196
|
+
|
|
197
|
+
fireEvent("on.banner.closed", null);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@Override
|
|
201
|
+
public void onAdFailedToShowFullScreenContent(@NonNull FullScreenContentError error) {
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
JSONObject errData = new JSONObject();
|
|
205
|
+
errData.put("message", error.getMessage());
|
|
206
|
+
fireEvent("on.banner.failed.show", errData);
|
|
207
|
+
} catch (JSONException e) {}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
ad.setBannerAdRefreshCallback(new BannerAdRefreshCallback() {
|
|
212
|
+
@Override
|
|
213
|
+
public void onAdRefreshed() {
|
|
214
|
+
|
|
215
|
+
fireEvent("on.banner.refreshed", null);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@Override
|
|
219
|
+
public void onAdFailedToRefresh(@NonNull LoadAdError loadAdError) {
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
JSONObject err = new JSONObject();
|
|
223
|
+
err.put("message", loadAdError.getMessage());
|
|
224
|
+
fireEvent("on.banner.refresh.failed", err);
|
|
225
|
+
} catch (JSONException e) {}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private void sendLoadedEvent(AdSize adSize, boolean isCollapsible) {
|
|
231
|
+
try {
|
|
232
|
+
Context context = cordova.getActivity();
|
|
233
|
+
JSONObject data = new JSONObject();
|
|
234
|
+
|
|
235
|
+
data.put("width", adSize.getWidth());
|
|
236
|
+
data.put("height", adSize.getHeight());
|
|
237
|
+
data.put("widthPixels", adSize.getWidthInPixels(context));
|
|
238
|
+
data.put("heightPixels", adSize.getHeightInPixels(context));
|
|
239
|
+
data.put("isCollapsible", isCollapsible);
|
|
240
|
+
|
|
241
|
+
fireEvent("on.banner.load", data);
|
|
242
|
+
} catch (JSONException e) {
|
|
243
|
+
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private AdSize getAdSize(Context context, String sizeStr) {
|
|
248
|
+
if ("BANNER".equalsIgnoreCase(sizeStr)) return AdSize.BANNER;
|
|
249
|
+
else if ("LARGE_BANNER".equalsIgnoreCase(sizeStr)) return AdSize.LARGE_BANNER;
|
|
250
|
+
else if ("MEDIUM_RECTANGLE".equalsIgnoreCase(sizeStr)) return AdSize.MEDIUM_RECTANGLE;
|
|
251
|
+
else if ("FULL_BANNER".equalsIgnoreCase(sizeStr)) return AdSize.FULL_BANNER;
|
|
252
|
+
else if ("LEADERBOARD".equalsIgnoreCase(sizeStr)) return AdSize.LEADERBOARD;
|
|
253
|
+
else return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, getAdWidth());
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private int getAdWidth() {
|
|
257
|
+
DisplayMetrics displayMetrics = cordova.getActivity().getResources().getDisplayMetrics();
|
|
258
|
+
return (int) (displayMetrics.widthPixels / displayMetrics.density);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private void renderBannerView(BannerAd ad) {
|
|
262
|
+
if (adLayout == null) {
|
|
263
|
+
adLayout = new RelativeLayout(cordova.getActivity());
|
|
264
|
+
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
|
|
265
|
+
RelativeLayout.LayoutParams.MATCH_PARENT,
|
|
266
|
+
RelativeLayout.LayoutParams.MATCH_PARENT);
|
|
267
|
+
adLayout.setClickable(false);
|
|
268
|
+
adLayout.setFocusable(false);
|
|
269
|
+
cordova.getActivity().addContentView(adLayout, params);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
adLayout.removeAllViews();
|
|
273
|
+
adLayout.setVisibility(View.VISIBLE);
|
|
274
|
+
|
|
275
|
+
View adView = ad.getView(cordova.getActivity());
|
|
276
|
+
RelativeLayout.LayoutParams bannerParams = new RelativeLayout.LayoutParams(
|
|
277
|
+
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
|
278
|
+
RelativeLayout.LayoutParams.WRAP_CONTENT);
|
|
279
|
+
|
|
280
|
+
bannerParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
|
|
281
|
+
|
|
282
|
+
if ("top".equalsIgnoreCase(currentPosition)) {
|
|
283
|
+
bannerParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
|
284
|
+
} else {
|
|
285
|
+
bannerParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
adLayout.addView(adView, bannerParams);
|
|
289
|
+
adLayout.bringToFront();
|
|
290
|
+
|
|
291
|
+
updateWebViewMargins(adView);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
public void stopPreloadAndClear() {
|
|
295
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
296
|
+
isPreloaderActive = false;
|
|
297
|
+
destroyCurrentBanner();
|
|
298
|
+
if (adLayout != null) {
|
|
299
|
+
adLayout.removeAllViews();
|
|
300
|
+
((ViewGroup)adLayout.getParent()).removeView(adLayout);
|
|
301
|
+
adLayout = null;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private void destroyCurrentBanner() {
|
|
307
|
+
if (currentBannerAd != null) {
|
|
308
|
+
currentBannerAd.destroy();
|
|
309
|
+
currentBannerAd = null;
|
|
310
|
+
}
|
|
311
|
+
resetWebViewMargins();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private void updateWebViewMargins(View adView) {
|
|
315
|
+
if (isOverlapping || webView == null || webView.getView() == null) {
|
|
316
|
+
resetWebViewMargins();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
adView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
|
321
|
+
int adHeight = adView.getMeasuredHeight();
|
|
322
|
+
|
|
323
|
+
View webViewView = webView.getView();
|
|
324
|
+
ViewGroup.LayoutParams lp = webViewView.getLayoutParams();
|
|
325
|
+
|
|
326
|
+
if (lp instanceof ViewGroup.MarginLayoutParams) {
|
|
327
|
+
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) lp;
|
|
328
|
+
if ("top".equalsIgnoreCase(currentPosition)) {
|
|
329
|
+
params.setMargins(0, adHeight, 0, 0);
|
|
330
|
+
} else {
|
|
331
|
+
params.setMargins(0, 0, 0, adHeight);
|
|
332
|
+
}
|
|
333
|
+
webViewView.setLayoutParams(params);
|
|
334
|
+
webViewView.requestLayout();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
private void resetWebViewMargins() {
|
|
339
|
+
if (webView == null || webView.getView() == null) return;
|
|
340
|
+
View webViewView = webView.getView();
|
|
341
|
+
ViewGroup.LayoutParams lp = webViewView.getLayoutParams();
|
|
342
|
+
if (lp instanceof ViewGroup.MarginLayoutParams) {
|
|
343
|
+
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) lp;
|
|
344
|
+
params.setMargins(0, 0, 0, 0);
|
|
345
|
+
webViewView.setLayoutParams(params);
|
|
346
|
+
webViewView.requestLayout();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private void fireEvent(String eventName, JSONObject data) {
|
|
351
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
352
|
+
StringBuilder js = new StringBuilder();
|
|
353
|
+
js.append("javascript:cordova.fireDocumentEvent('");
|
|
354
|
+
js.append(eventName);
|
|
355
|
+
js.append("'");
|
|
356
|
+
if (data != null) {
|
|
357
|
+
js.append(", ");
|
|
358
|
+
js.append(data.toString());
|
|
359
|
+
}
|
|
360
|
+
js.append(");");
|
|
361
|
+
if (webView != null) webView.loadUrl(js.toString());
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
package com.emi.cordova.admob.nextgen;
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint;
|
|
4
|
+
import android.app.Activity;
|
|
5
|
+
import android.content.Context;
|
|
6
|
+
import android.content.SharedPreferences;
|
|
7
|
+
import android.preference.PreferenceManager;
|
|
8
|
+
import android.provider.Settings;
|
|
9
|
+
import android.util.Log;
|
|
10
|
+
|
|
11
|
+
import org.apache.cordova.CallbackContext;
|
|
12
|
+
import org.apache.cordova.CordovaInterface;
|
|
13
|
+
import org.apache.cordova.CordovaWebView;
|
|
14
|
+
import org.json.JSONArray;
|
|
15
|
+
import org.json.JSONException;
|
|
16
|
+
import org.json.JSONObject;
|
|
17
|
+
|
|
18
|
+
import java.security.MessageDigest;
|
|
19
|
+
import java.security.NoSuchAlgorithmException;
|
|
20
|
+
import java.util.Locale;
|
|
21
|
+
|
|
22
|
+
import com.google.android.ump.ConsentDebugSettings;
|
|
23
|
+
import com.google.android.ump.ConsentInformation;
|
|
24
|
+
import com.google.android.ump.ConsentRequestParameters;
|
|
25
|
+
import com.google.android.ump.FormError;
|
|
26
|
+
import com.google.android.ump.UserMessagingPlatform;
|
|
27
|
+
|
|
28
|
+
public class ConsentExecutor {
|
|
29
|
+
|
|
30
|
+
private static final String TAG = "AdMobConsent";
|
|
31
|
+
private CordovaInterface cordova;
|
|
32
|
+
private CordovaWebView webView;
|
|
33
|
+
private ConsentInformation consentInformation;
|
|
34
|
+
|
|
35
|
+
public ConsentExecutor(CordovaInterface cordova, CordovaWebView webView) {
|
|
36
|
+
this.cordova = cordova;
|
|
37
|
+
this.webView = webView;
|
|
38
|
+
this.consentInformation = UserMessagingPlatform.getConsentInformation(cordova.getActivity());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public void requestConsentInfo(JSONArray args, CallbackContext callbackContext) {
|
|
42
|
+
cordova.getThreadPool().execute(() -> {
|
|
43
|
+
try {
|
|
44
|
+
JSONObject options = args.optJSONObject(0);
|
|
45
|
+
|
|
46
|
+
boolean debugMode = false;
|
|
47
|
+
String manualTestDeviceId = "";
|
|
48
|
+
boolean resetConsent = false;
|
|
49
|
+
boolean tagForUnderAgeOfConsent = false;
|
|
50
|
+
|
|
51
|
+
if (options != null) {
|
|
52
|
+
debugMode = options.optBoolean("debug", false);
|
|
53
|
+
manualTestDeviceId = options.optString("testDeviceId", "");
|
|
54
|
+
resetConsent = options.optBoolean("reset", false);
|
|
55
|
+
|
|
56
|
+
if (options.has("tagForUnderAgeOfConsent")) {
|
|
57
|
+
tagForUnderAgeOfConsent = options.getBoolean("tagForUnderAgeOfConsent");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (resetConsent) {
|
|
62
|
+
consentInformation.reset();
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
ConsentRequestParameters.Builder paramsBuilder = new ConsentRequestParameters.Builder();
|
|
67
|
+
paramsBuilder.setTagForUnderAgeOfConsent(tagForUnderAgeOfConsent);
|
|
68
|
+
|
|
69
|
+
if (debugMode) {
|
|
70
|
+
ConsentDebugSettings.Builder debugSettingsBuilder = new ConsentDebugSettings.Builder(cordova.getActivity())
|
|
71
|
+
.setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA);
|
|
72
|
+
|
|
73
|
+
if (!manualTestDeviceId.isEmpty()) {
|
|
74
|
+
debugSettingsBuilder.addTestDeviceHashedId(manualTestDeviceId);
|
|
75
|
+
|
|
76
|
+
} else {
|
|
77
|
+
String deviceId = getDeviceId();
|
|
78
|
+
if (deviceId != null) {
|
|
79
|
+
debugSettingsBuilder.addTestDeviceHashedId(deviceId);
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
paramsBuilder.setConsentDebugSettings(debugSettingsBuilder.build());
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
ConsentRequestParameters params = paramsBuilder.build();
|
|
88
|
+
Activity activity = cordova.getActivity();
|
|
89
|
+
|
|
90
|
+
activity.runOnUiThread(() -> {
|
|
91
|
+
consentInformation.requestConsentInfoUpdate(
|
|
92
|
+
activity,
|
|
93
|
+
params,
|
|
94
|
+
() -> {
|
|
95
|
+
|
|
96
|
+
fireEvent("on.consent.info.update", null);
|
|
97
|
+
|
|
98
|
+
UserMessagingPlatform.loadAndShowConsentFormIfRequired(
|
|
99
|
+
activity,
|
|
100
|
+
(FormError loadAndShowError) -> {
|
|
101
|
+
if (loadAndShowError != null) {
|
|
102
|
+
|
|
103
|
+
sendErrorEvent(loadAndShowError);
|
|
104
|
+
callbackContext.error(loadAndShowError.getMessage());
|
|
105
|
+
} else {
|
|
106
|
+
|
|
107
|
+
fireEvent("on.consent.form.dismissed", null);
|
|
108
|
+
|
|
109
|
+
sendConsentStatus(callbackContext);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
},
|
|
114
|
+
(FormError requestConsentError) -> {
|
|
115
|
+
|
|
116
|
+
sendErrorEvent(requestConsentError);
|
|
117
|
+
callbackContext.error(requestConsentError.getMessage());
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
} catch (Exception e) {
|
|
123
|
+
callbackContext.error("Exception: " + e.getMessage());
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public void getTCData(CallbackContext callbackContext) {
|
|
129
|
+
try {
|
|
130
|
+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(cordova.getActivity());
|
|
131
|
+
JSONObject tcData = new JSONObject();
|
|
132
|
+
|
|
133
|
+
String tcString = prefs.getString("IABTCF_TCString", "");
|
|
134
|
+
String purposeConsents = prefs.getString("IABTCF_PurposeConsents", "");
|
|
135
|
+
String vendorConsents = prefs.getString("IABTCF_VendorConsents", "");
|
|
136
|
+
int gdprApplies = prefs.getInt("IABTCF_gdprApplies", 0);
|
|
137
|
+
|
|
138
|
+
tcData.put("tcString", tcString);
|
|
139
|
+
tcData.put("purposeConsents", purposeConsents);
|
|
140
|
+
tcData.put("vendorConsents", vendorConsents);
|
|
141
|
+
tcData.put("gdprApplies", gdprApplies);
|
|
142
|
+
|
|
143
|
+
boolean isPersonalizedAllowed = false;
|
|
144
|
+
String statusMessage = "Unknown";
|
|
145
|
+
|
|
146
|
+
if (gdprApplies == 0) {
|
|
147
|
+
|
|
148
|
+
isPersonalizedAllowed = true;
|
|
149
|
+
statusMessage = "Not GDPR region. Personalized Ads allowed by default.";
|
|
150
|
+
} else {
|
|
151
|
+
|
|
152
|
+
if (purposeConsents != null && purposeConsents.length() > 0) {
|
|
153
|
+
char p1 = purposeConsents.charAt(0);
|
|
154
|
+
if (p1 == '1') {
|
|
155
|
+
isPersonalizedAllowed = true;
|
|
156
|
+
statusMessage = "Purpose 1 Granted. Personalized Ads allowed.";
|
|
157
|
+
} else {
|
|
158
|
+
isPersonalizedAllowed = false;
|
|
159
|
+
statusMessage = "Purpose 1 Denied. Non-Personalized / Limited Ads only.";
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
|
|
163
|
+
isPersonalizedAllowed = false;
|
|
164
|
+
statusMessage = "No consent data found (User hasn't answered yet).";
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
tcData.put("isPersonalizedAllowed", isPersonalizedAllowed);
|
|
169
|
+
tcData.put("statusMessage", statusMessage);
|
|
170
|
+
|
|
171
|
+
callbackContext.success(tcData);
|
|
172
|
+
} catch (Exception e) {
|
|
173
|
+
callbackContext.error("Failed to read TC Data: " + e.getMessage());
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private String getDeviceId() {
|
|
178
|
+
try {
|
|
179
|
+
Context context = cordova.getActivity();
|
|
180
|
+
@SuppressLint("HardwareIds") String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
|
181
|
+
if (androidId == null || androidId.isEmpty()) return null;
|
|
182
|
+
return md5(androidId).toUpperCase(Locale.getDefault());
|
|
183
|
+
} catch (Exception e) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private String md5(String s) {
|
|
189
|
+
try {
|
|
190
|
+
MessageDigest digest = MessageDigest.getInstance("MD5");
|
|
191
|
+
digest.update(s.getBytes());
|
|
192
|
+
byte messageDigest[] = digest.digest();
|
|
193
|
+
StringBuilder hexString = new StringBuilder();
|
|
194
|
+
for (byte b : messageDigest) {
|
|
195
|
+
String h = Integer.toHexString(0xFF & b);
|
|
196
|
+
while (h.length() < 2) h = "0" + h;
|
|
197
|
+
hexString.append(h);
|
|
198
|
+
}
|
|
199
|
+
return hexString.toString();
|
|
200
|
+
} catch (NoSuchAlgorithmException e) {
|
|
201
|
+
return "";
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private void sendConsentStatus(CallbackContext callbackContext) {
|
|
206
|
+
try {
|
|
207
|
+
JSONObject result = new JSONObject();
|
|
208
|
+
boolean canRequestAds = consentInformation.canRequestAds();
|
|
209
|
+
result.put("canRequestAds", canRequestAds);
|
|
210
|
+
|
|
211
|
+
ConsentInformation.PrivacyOptionsRequirementStatus requirementStatus =
|
|
212
|
+
consentInformation.getPrivacyOptionsRequirementStatus();
|
|
213
|
+
result.put("privacyOptionsRequirementStatus", requirementStatus.name());
|
|
214
|
+
result.put("isPrivacyOptionsRequired",
|
|
215
|
+
requirementStatus == ConsentInformation.PrivacyOptionsRequirementStatus.REQUIRED);
|
|
216
|
+
|
|
217
|
+
result.put("consentStatus", consentInformation.getConsentStatus());
|
|
218
|
+
|
|
219
|
+
fireEvent("on.consent.status.change", result);
|
|
220
|
+
|
|
221
|
+
if (callbackContext != null) {
|
|
222
|
+
callbackContext.success(result);
|
|
223
|
+
}
|
|
224
|
+
} catch (JSONException e) {
|
|
225
|
+
if (callbackContext != null) callbackContext.error("JSON Error");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public void canRequestAds(CallbackContext callbackContext) {
|
|
230
|
+
callbackContext.success(consentInformation.canRequestAds() ? 1 : 0);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public void showPrivacyOptionsForm(CallbackContext callbackContext) {
|
|
234
|
+
Activity activity = cordova.getActivity();
|
|
235
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
236
|
+
UserMessagingPlatform.showPrivacyOptionsForm(
|
|
237
|
+
activity,
|
|
238
|
+
(FormError formError) -> {
|
|
239
|
+
if (formError != null) {
|
|
240
|
+
sendErrorEvent(formError);
|
|
241
|
+
callbackContext.error(formError.getMessage());
|
|
242
|
+
} else {
|
|
243
|
+
|
|
244
|
+
fireEvent("on.consent.form.dismissed", null);
|
|
245
|
+
sendConsentStatus(callbackContext);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private void sendErrorEvent(FormError error) {
|
|
253
|
+
try {
|
|
254
|
+
JSONObject errData = new JSONObject();
|
|
255
|
+
errData.put("code", error.getErrorCode());
|
|
256
|
+
errData.put("message", error.getMessage());
|
|
257
|
+
fireEvent("on.consent.error", errData);
|
|
258
|
+
} catch (JSONException e) {}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private void fireEvent(String eventName, JSONObject data) {
|
|
262
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
263
|
+
StringBuilder js = new StringBuilder();
|
|
264
|
+
js.append("javascript:cordova.fireDocumentEvent('");
|
|
265
|
+
js.append(eventName);
|
|
266
|
+
js.append("'");
|
|
267
|
+
|
|
268
|
+
if (data != null) {
|
|
269
|
+
js.append(", ");
|
|
270
|
+
js.append(data.toString());
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
js.append(");");
|
|
274
|
+
|
|
275
|
+
String jsCommand = js.toString();
|
|
276
|
+
if (webView != null) webView.loadUrl(jsCommand);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|