@jwplayer/jwplayer-react-native 1.3.0 → 1.3.2

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.
@@ -65,6 +65,19 @@ android {
65
65
  lintOptions {
66
66
  warning 'InvalidPackage'
67
67
  }
68
+
69
+ sourceSets {
70
+ main {
71
+ java {
72
+ srcDirs = ['src/main/java']
73
+ if (useIMA) {
74
+ srcDirs += ['src/ima/java']
75
+ } else {
76
+ srcDirs += ['src/noima/java']
77
+ }
78
+ }
79
+ }
80
+ }
68
81
  }
69
82
 
70
83
  allprojects {
@@ -90,14 +103,14 @@ dependencies {
90
103
  implementation 'com.facebook.react:react-native:+'
91
104
  implementation 'com.google.code.gson:gson:2.9.0'
92
105
 
93
- // JWPlayer SDK
106
+ // JWPlayer SDK Core (always required)
94
107
  implementation "com.jwplayer:jwplayer-core:${safeExtGet('jwPlayerVersion', jwPlayerVersion)}"
95
108
  implementation "com.jwplayer:jwplayer-common:${safeExtGet('jwPlayerVersion', jwPlayerVersion)}"
96
- implementation "com.jwplayer:jwplayer-ima:${safeExtGet('jwPlayerVersion', jwPlayerVersion)}"
97
109
  implementation "com.jwplayer:jwplayer-chromecast:${safeExtGet('jwPlayerVersion', jwPlayerVersion)}"
98
-
99
- // Ad dependencies
110
+
111
+ // Optional: IMA Ads support
100
112
  if (useIMA) {
113
+ implementation "com.jwplayer:jwplayer-ima:${safeExtGet('jwPlayerVersion', jwPlayerVersion)}"
101
114
  implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.36.0'
102
115
  implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
103
116
  // Core library desugaring (required for IMA SDK 3.37.0+)
@@ -0,0 +1,142 @@
1
+ package com.jwplayer.rnjwplayer;
2
+
3
+ import com.facebook.react.bridge.ReadableMap;
4
+ import com.google.ads.interactivemedia.v3.api.ImaSdkFactory;
5
+ import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
6
+ import com.jwplayer.pub.api.configuration.ads.AdvertisingConfig;
7
+ import com.jwplayer.pub.api.configuration.ads.dai.ImaDaiAdvertisingConfig;
8
+ import com.jwplayer.pub.api.configuration.ads.ima.ImaAdvertisingConfig;
9
+ import com.jwplayer.pub.api.media.ads.AdBreak;
10
+ import com.jwplayer.pub.api.media.ads.dai.ImaDaiSettings;
11
+
12
+ import java.util.List;
13
+ import java.util.Map;
14
+ import java.util.HashMap;
15
+ import java.util.Objects;
16
+
17
+ /**
18
+ * IMA-specific advertising configuration helper.
19
+ * This class is only compiled when RNJWPlayerUseGoogleIMA = true.
20
+ */
21
+ public class ImaHelper {
22
+
23
+ public static AdvertisingConfig configureImaOrDai(ReadableMap ads, List<AdBreak> adSchedule) {
24
+ String adClientType = null;
25
+ if (ads.hasKey("adClient")) {
26
+ adClientType = ads.getString("adClient");
27
+ } else if (ads.hasKey("client")) {
28
+ adClientType = ads.getString("client");
29
+ }
30
+
31
+ if (adClientType != null) {
32
+ adClientType = adClientType.toLowerCase();
33
+ }
34
+
35
+ if ("ima".equals(adClientType) || "googima".equals(adClientType)) {
36
+ return configureImaAdvertising(ads, adSchedule);
37
+ } else if ("ima_dai".equals(adClientType)) {
38
+ return configureImaDaiAdvertising(ads);
39
+ }
40
+
41
+ // Should never reach here due to validation in RNJWPlayerAds
42
+ throw new RuntimeException("Unknown IMA ad client type: " + adClientType);
43
+ }
44
+
45
+ private static ImaAdvertisingConfig configureImaAdvertising(ReadableMap ads, List<AdBreak> adSchedule) {
46
+ ImaAdvertisingConfig.Builder builder = new ImaAdvertisingConfig.Builder();
47
+ builder.schedule(adSchedule);
48
+
49
+ if (ads.hasKey("imaSettings")) {
50
+ builder.imaSdkSettings(getImaSettings(Objects.requireNonNull(ads.getMap("imaSettings"))));
51
+ }
52
+
53
+ return builder.build();
54
+ }
55
+
56
+ private static ImaDaiAdvertisingConfig configureImaDaiAdvertising(ReadableMap ads) {
57
+ ImaDaiAdvertisingConfig.Builder builder = new ImaDaiAdvertisingConfig.Builder();
58
+
59
+ if (ads.hasKey("imaSettings")) {
60
+ builder.imaSdkSettings(getImaSettings(Objects.requireNonNull(ads.getMap("imaSettings"))));
61
+ }
62
+
63
+ if (ads.hasKey("imaDaiSettings")) {
64
+ builder.imaDaiSettings(getImaDaiSettings(Objects.requireNonNull(ads.getMap("imaDaiSettings"))));
65
+ }
66
+
67
+ return builder.build();
68
+ }
69
+
70
+ private static ImaDaiSettings getImaDaiSettings(ReadableMap imaDaiSettingsMap) {
71
+ String videoId = imaDaiSettingsMap.hasKey("videoId") ? imaDaiSettingsMap.getString("videoId") : null;
72
+ String cmsId = imaDaiSettingsMap.hasKey("cmsId") ? imaDaiSettingsMap.getString("cmsId") : null;
73
+ String assetKey = imaDaiSettingsMap.hasKey("assetKey") ? imaDaiSettingsMap.getString("assetKey") : null;
74
+ String apiKey = imaDaiSettingsMap.hasKey("apiKey") ? imaDaiSettingsMap.getString("apiKey") : null;
75
+
76
+ // Validate we have either assetKey OR (videoId + cmsId)
77
+ if (assetKey == null && (videoId == null || cmsId == null)) {
78
+ throw new IllegalArgumentException(
79
+ "ImaDaiSettings requires either 'assetKey' OR both 'videoId' and 'cmsId'. " +
80
+ "Provided: assetKey=" + assetKey + ", videoId=" + videoId + ", cmsId=" + cmsId
81
+ );
82
+ }
83
+
84
+ Map<String, String> adTagParameters = null;
85
+ if (imaDaiSettingsMap.hasKey("adTagParameters") && imaDaiSettingsMap.getMap("adTagParameters") != null) {
86
+ adTagParameters = new HashMap<>();
87
+ ReadableMap adTagParamsMap = imaDaiSettingsMap.getMap("adTagParameters");
88
+ for (Map.Entry<String, Object> entry : adTagParamsMap.toHashMap().entrySet()) {
89
+ if (entry.getValue() instanceof String) {
90
+ adTagParameters.put(entry.getKey(), (String) entry.getValue());
91
+ }
92
+ }
93
+ }
94
+
95
+ ImaDaiSettings.StreamType streamType = ImaDaiSettings.StreamType.HLS;
96
+ if (imaDaiSettingsMap.hasKey("streamType")) {
97
+ String streamTypeStr = imaDaiSettingsMap.getString("streamType");
98
+ if ("DASH".equalsIgnoreCase(streamTypeStr)) {
99
+ streamType = ImaDaiSettings.StreamType.DASH;
100
+ }
101
+ }
102
+
103
+ ImaDaiSettings imaDaiSettings = (assetKey != null) ?
104
+ new ImaDaiSettings(assetKey, streamType, apiKey) :
105
+ new ImaDaiSettings(videoId, cmsId, streamType, apiKey);
106
+
107
+ if (adTagParameters != null) {
108
+ imaDaiSettings.setAdTagParameters(adTagParameters);
109
+ }
110
+
111
+ return imaDaiSettings;
112
+ }
113
+
114
+ public static ImaSdkSettings getImaSettings(ReadableMap imaSettingsMap) {
115
+ ImaSdkSettings settings = ImaSdkFactory.getInstance().createImaSdkSettings();
116
+
117
+ if (imaSettingsMap.hasKey("maxRedirects")) {
118
+ settings.setMaxRedirects(imaSettingsMap.getInt("maxRedirects"));
119
+ }
120
+ if (imaSettingsMap.hasKey("language")) {
121
+ settings.setLanguage(imaSettingsMap.getString("language"));
122
+ }
123
+ if (imaSettingsMap.hasKey("ppid")) {
124
+ settings.setPpid(imaSettingsMap.getString("ppid"));
125
+ }
126
+ if (imaSettingsMap.hasKey("playerType")) {
127
+ settings.setPlayerType(imaSettingsMap.getString("playerType"));
128
+ }
129
+ if (imaSettingsMap.hasKey("playerVersion")) {
130
+ settings.setPlayerVersion(imaSettingsMap.getString("playerVersion"));
131
+ }
132
+ if (imaSettingsMap.hasKey("sessionId")) {
133
+ settings.setSessionId(imaSettingsMap.getString("sessionId"));
134
+ }
135
+ if (imaSettingsMap.hasKey("debugMode")) {
136
+ settings.setDebugMode(imaSettingsMap.getBoolean("debugMode"));
137
+ }
138
+
139
+ return settings;
140
+ }
141
+ }
142
+
@@ -2,21 +2,13 @@ package com.jwplayer.rnjwplayer;
2
2
 
3
3
  import com.facebook.react.bridge.ReadableArray;
4
4
  import com.facebook.react.bridge.ReadableMap;
5
- import com.google.ads.interactivemedia.v3.api.FriendlyObstruction;
6
- import com.google.ads.interactivemedia.v3.api.ImaSdkFactory;
7
- import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
8
5
  import com.jwplayer.pub.api.configuration.ads.AdRules;
9
6
  import com.jwplayer.pub.api.configuration.ads.AdvertisingConfig;
10
7
  import com.jwplayer.pub.api.configuration.ads.VastAdvertisingConfig;
11
- import com.jwplayer.pub.api.configuration.ads.dai.ImaDaiAdvertisingConfig;
12
- import com.jwplayer.pub.api.configuration.ads.ima.ImaAdvertisingConfig;
13
8
  import com.jwplayer.pub.api.media.ads.AdBreak;
14
- import com.jwplayer.pub.api.media.ads.dai.ImaDaiSettings;
15
9
 
16
10
  import java.util.ArrayList;
17
- import java.util.HashMap;
18
11
  import java.util.List;
19
- import java.util.Map;
20
12
  import java.util.Objects;
21
13
 
22
14
  public class RNJWPlayerAds {
@@ -27,103 +19,43 @@ public class RNJWPlayerAds {
27
19
  return null;
28
20
  }
29
21
 
30
- String adClientType = ads.getString("adClient");
22
+ // Check both "client" (JWPlayer JSON format) and "adClient" (RN wrapper format)
23
+ String adClientType = null;
24
+ if (ads.hasKey("adClient")) {
25
+ adClientType = ads.getString("adClient");
26
+ } else if (ads.hasKey("client")) {
27
+ adClientType = ads.getString("client");
28
+ }
29
+
30
+ // Validate client type exists and is not null
31
+ if (adClientType == null) {
32
+ throw new IllegalArgumentException("Missing required 'adClient' or 'client' field in advertising config");
33
+ }
34
+
35
+ // Normalize to lowercase for case-insensitive matching
36
+ adClientType = adClientType.toLowerCase();
37
+
31
38
  switch (adClientType) {
32
39
  case "ima":
33
- try {
34
- return configureImaAdvertising(ads);
35
- } catch (Exception e) {
36
- throw new RuntimeException(e);
37
- }
40
+ case "googima": // Support legacy "googima" format
38
41
  case "ima_dai":
42
+ // Delegate to ImaHelper (implementation selected by Gradle)
43
+ // Note: Only parse adSchedule for regular IMA, not for DAI (ads are embedded in stream)
44
+ List<AdBreak> adSchedule = ("ima".equals(adClientType) || "googima".equals(adClientType))
45
+ ? getAdSchedule(ads)
46
+ : new ArrayList<>();
39
47
  try {
40
- return configureImaDaiAdvertising(ads);
41
- } catch (Exception e) {
42
- throw new RuntimeException(e);
48
+ return ImaHelper.configureImaOrDai(ads, adSchedule);
49
+ } catch (RuntimeException e) {
50
+ // IMA not enabled - log error and return null (graceful degradation)
51
+ android.util.Log.e("RNJWPlayerAds", "Failed to configure IMA ads: " + e.getMessage());
52
+ return null;
43
53
  }
44
54
  default: // Defaulting to VAST
45
55
  return configureVastAdvertising(ads);
46
56
  }
47
57
  }
48
58
 
49
- // Configure IMA Advertising
50
- private static ImaAdvertisingConfig configureImaAdvertising(ReadableMap ads) throws Exception {
51
- if (!BuildConfig.USE_IMA) {
52
- throw new Exception("Error: Google ads services is not installed. Add RNJWPlayerUseGoogleIMA = true to your app/build.gradle ext {}");
53
- }
54
-
55
- ImaAdvertisingConfig.Builder builder = new ImaAdvertisingConfig.Builder();
56
-
57
- List<AdBreak> adScheduleList = getAdSchedule(ads);
58
- builder.schedule(adScheduleList);
59
-
60
- if (ads.hasKey("imaSettings")) {
61
- builder.imaSdkSettings(getImaSettings(Objects.requireNonNull(ads.getMap("imaSettings"))));
62
- }
63
-
64
- // companionSlots
65
-
66
- return builder.build();
67
- }
68
-
69
- // Configure IMA DAI Advertising
70
- private static ImaDaiAdvertisingConfig configureImaDaiAdvertising(ReadableMap ads) throws Exception {
71
- if (!BuildConfig.USE_IMA) {
72
- throw new Exception("Error: Google ads services is not installed. Add RNJWPlayerUseGoogleIMA = true to your app/build.gradle ext {}");
73
- }
74
-
75
- ImaDaiAdvertisingConfig.Builder builder = new ImaDaiAdvertisingConfig.Builder();
76
-
77
- if (ads.hasKey("imaSettings")) {
78
- builder.imaSdkSettings(getImaSettings(Objects.requireNonNull(ads.getMap("imaSettings"))));
79
- }
80
-
81
- if (ads.hasKey("imaDaiSettings")) {
82
- builder.imaDaiSettings(getImaDaiSettings(Objects.requireNonNull(ads.getMap("imaDaiSettings"))));
83
- }
84
-
85
- return builder.build();
86
- }
87
-
88
- // You'll need to implement this method based on how you pass ImaDaiSettings from React Native
89
- private static ImaDaiSettings getImaDaiSettings(ReadableMap imaDaiSettingsMap) {
90
- String videoId = imaDaiSettingsMap.hasKey("videoId") ? imaDaiSettingsMap.getString("videoId") : null;
91
- String cmsId = imaDaiSettingsMap.hasKey("cmsId") ? imaDaiSettingsMap.getString("cmsId") : null;
92
- String assetKey = imaDaiSettingsMap.hasKey("assetKey") ? imaDaiSettingsMap.getString("assetKey") : null;
93
- String apiKey = imaDaiSettingsMap.hasKey("apiKey") ? imaDaiSettingsMap.getString("apiKey") : null;
94
-
95
- // Extracting adTagParameters from imaDaiSettingsMap if present
96
- Map<String, String> adTagParameters = null;
97
- if (imaDaiSettingsMap.hasKey("adTagParameters") && imaDaiSettingsMap.getMap("adTagParameters") != null) {
98
- adTagParameters = new HashMap<>();
99
- ReadableMap adTagParamsMap = imaDaiSettingsMap.getMap("adTagParameters");
100
- for (Map.Entry<String, Object> entry : adTagParamsMap.toHashMap().entrySet()) {
101
- if (entry.getValue() instanceof String) {
102
- adTagParameters.put(entry.getKey(), (String) entry.getValue());
103
- }
104
- }
105
- }
106
-
107
- // Handling streamType
108
- ImaDaiSettings.StreamType streamType = ImaDaiSettings.StreamType.HLS; // Default to HLS
109
- if (imaDaiSettingsMap.hasKey("streamType")) {
110
- String streamTypeStr = imaDaiSettingsMap.getString("streamType");
111
- if ("DASH".equalsIgnoreCase(streamTypeStr)) {
112
- streamType = ImaDaiSettings.StreamType.DASH;
113
- }
114
- }
115
- // Create ImaDaiSettings based on the provided values
116
- ImaDaiSettings imaDaiSettings = (assetKey != null) ?
117
- new ImaDaiSettings(assetKey, streamType, apiKey) :
118
- new ImaDaiSettings(videoId, cmsId, streamType, apiKey);
119
-
120
- if (adTagParameters != null) {
121
- imaDaiSettings.setAdTagParameters(adTagParameters);
122
- }
123
-
124
- return imaDaiSettings;
125
- }
126
-
127
59
  // Configure VAST Advertising
128
60
  private static VastAdvertisingConfig configureVastAdvertising(ReadableMap ads) {
129
61
  VastAdvertisingConfig.Builder builder = new VastAdvertisingConfig.Builder();
@@ -154,9 +86,23 @@ public class RNJWPlayerAds {
154
86
 
155
87
  private static List<AdBreak> getAdSchedule(ReadableMap ads) {
156
88
  List<AdBreak> adScheduleList = new ArrayList<>();
89
+
90
+ // Check if adSchedule exists
91
+ if (!ads.hasKey("adSchedule")) {
92
+ return adScheduleList; // Return empty list
93
+ }
94
+
157
95
  ReadableArray adSchedule = ads.getArray("adSchedule");
96
+ if (adSchedule == null) {
97
+ return adScheduleList; // Return empty list if null
98
+ }
99
+
158
100
  for (int i = 0; i < adSchedule.size(); i++) {
159
101
  ReadableMap adBreakProp = adSchedule.getMap(i);
102
+ // Skip null entries in the adSchedule array
103
+ if (adBreakProp == null) {
104
+ continue;
105
+ }
160
106
  String offset = adBreakProp.hasKey("offset") ? adBreakProp.getString("offset") : "pre";
161
107
  if (adBreakProp.hasKey("tag")) {
162
108
  AdBreak adBreak = new AdBreak.Builder()
@@ -202,38 +148,4 @@ public class RNJWPlayerAds {
202
148
  return AdRules.RULES_START_ON_SEEK_NONE;
203
149
  }
204
150
 
205
- // public static List<FriendlyObstruction> getFriendlyObstructions(ReadableArray obstructionsArray) {
206
- // List<FriendlyObstruction> obstructions = new ArrayList<>();
207
- // // Example: Parse and create FriendlyObstruction objects from obstructionsArray
208
- // return obstructions;
209
- // }
210
-
211
- public static ImaSdkSettings getImaSettings(ReadableMap imaSettingsMap) {
212
- ImaSdkSettings settings = ImaSdkFactory.getInstance().createImaSdkSettings();
213
-
214
- if (imaSettingsMap.hasKey("maxRedirects")) {
215
- settings.setMaxRedirects(imaSettingsMap.getInt("maxRedirects"));
216
- }
217
- if (imaSettingsMap.hasKey("language")) {
218
- settings.setLanguage(imaSettingsMap.getString("language"));
219
- }
220
- if (imaSettingsMap.hasKey("ppid")) {
221
- settings.setPpid(imaSettingsMap.getString("ppid"));
222
- }
223
- if (imaSettingsMap.hasKey("playerType")) {
224
- settings.setPlayerType(imaSettingsMap.getString("playerType"));
225
- }
226
- if (imaSettingsMap.hasKey("playerVersion")) {
227
- settings.setPlayerVersion(imaSettingsMap.getString("playerVersion"));
228
- }
229
- if (imaSettingsMap.hasKey("sessionId")) {
230
- settings.setSessionId(imaSettingsMap.getString("sessionId"));
231
- }
232
- if (imaSettingsMap.hasKey("debugMode")) {
233
- settings.setDebugMode(imaSettingsMap.getBoolean("debugMode"));
234
- }
235
- // Add other settings as needed
236
-
237
- return settings;
238
- }
239
151
  }
@@ -1034,6 +1034,99 @@ public class RNJWPlayerView extends RelativeLayout implements
1034
1034
  }
1035
1035
  }
1036
1036
 
1037
+ /**
1038
+ * Checks for IMA configuration when IMA is disabled and logs a warning.
1039
+ *
1040
+ * @param obj The JSONObject to check (for JSON parser path)
1041
+ * @param prop The ReadableMap to check (for legacy builder path)
1042
+ */
1043
+ private void checkAndWarnImaConfig(JSONObject obj, ReadableMap prop) {
1044
+ if (BuildConfig.USE_IMA) {
1045
+ return; // IMA is enabled, no warning needed
1046
+ }
1047
+
1048
+ String clientValue = getClientValue(obj, prop);
1049
+
1050
+ if (clientValue != null && isImaClient(clientValue)) {
1051
+ String warningMessage = "⚠️ Google IMA advertising is not enabled. " +
1052
+ "To use IMA ads, add 'RNJWPlayerUseGoogleIMA = true' to your app/build.gradle ext {} block. " +
1053
+ "Current client: " + clientValue + ". Player will load without ads.";
1054
+ Log.w(TAG, warningMessage);
1055
+ }
1056
+ }
1057
+
1058
+ /**
1059
+ * Extracts the client value from either JSONObject or ReadableMap
1060
+ */
1061
+ private String getClientValue(JSONObject obj, ReadableMap prop) {
1062
+ // Check JSON object (for JSON parser path)
1063
+ if (obj != null && obj.has("advertising")) {
1064
+ try {
1065
+ JSONObject advertising = obj.getJSONObject("advertising");
1066
+ if (advertising.has("client")) {
1067
+ return advertising.getString("client");
1068
+ } else if (advertising.has("adClient")) {
1069
+ return advertising.getString("adClient");
1070
+ }
1071
+ } catch (Exception e) {
1072
+ // Silently continue if we can't parse
1073
+ }
1074
+ }
1075
+
1076
+ // Check ReadableMap (for legacy builder path)
1077
+ if (prop != null && prop.hasKey("advertising")) {
1078
+ ReadableMap advertising = prop.getMap("advertising");
1079
+ if (advertising != null) {
1080
+ if (advertising.hasKey("client")) {
1081
+ return advertising.getString("client");
1082
+ } else if (advertising.hasKey("adClient")) {
1083
+ return advertising.getString("adClient");
1084
+ }
1085
+ }
1086
+ }
1087
+
1088
+ return null;
1089
+ }
1090
+
1091
+ /**
1092
+ * Checks if a client value indicates IMA usage
1093
+ */
1094
+ private boolean isImaClient(String clientValue) {
1095
+ if (clientValue == null) {
1096
+ return false;
1097
+ }
1098
+ return "ima".equalsIgnoreCase(clientValue) ||
1099
+ "ima_dai".equalsIgnoreCase(clientValue) ||
1100
+ "GoogleIMA".equalsIgnoreCase(clientValue) ||
1101
+ "GoogleIMADAI".equalsIgnoreCase(clientValue) ||
1102
+ "IMA_DAI".equalsIgnoreCase(clientValue) ||
1103
+ "googima".equalsIgnoreCase(clientValue);
1104
+ }
1105
+
1106
+ /**
1107
+ * Checks if advertising config contains IMA when IMA is disabled.
1108
+ * Used to determine if we should skip configureAdvertising() in legacy builder.
1109
+ */
1110
+ private boolean shouldSkipAdvertising(ReadableMap prop) {
1111
+ if (BuildConfig.USE_IMA || !prop.hasKey("advertising")) {
1112
+ return false;
1113
+ }
1114
+
1115
+ ReadableMap advertising = prop.getMap("advertising");
1116
+ if (advertising == null) {
1117
+ return false;
1118
+ }
1119
+
1120
+ String clientValue = null;
1121
+ if (advertising.hasKey("client")) {
1122
+ clientValue = advertising.getString("client");
1123
+ } else if (advertising.hasKey("adClient")) {
1124
+ clientValue = advertising.getString("adClient");
1125
+ }
1126
+
1127
+ return isImaClient(clientValue);
1128
+ }
1129
+
1037
1130
  /**
1038
1131
  * Builds a PlayerConfig from React Native props, preserving relevant old config values.
1039
1132
  * This ensures smooth transitions when reconfiguring the player.
@@ -1050,11 +1143,16 @@ public class RNJWPlayerView extends RelativeLayout implements
1050
1143
  if (!forceLegacy) {
1051
1144
  try {
1052
1145
  obj = MapUtil.toJSONObject(prop);
1146
+
1147
+ // Check for IMA config and log warning if IMA is disabled
1148
+ // Don't modify JSON - let parser handle it internally
1149
+ checkAndWarnImaConfig(obj, null);
1150
+
1053
1151
  jwConfig = JsonHelper.parseConfigJson(obj);
1054
1152
  isJwConfig = true;
1055
1153
  return jwConfig; // Return directly if valid JW config
1056
1154
  } catch (Exception ex) {
1057
- Log.d(TAG, "Not a JW config format, using legacy builder");
1155
+ Log.d(TAG, "Not a JW config format, using legacy builder: " + ex.getMessage());
1058
1156
  isJwConfig = false;
1059
1157
  }
1060
1158
  }
@@ -1063,7 +1161,13 @@ public class RNJWPlayerView extends RelativeLayout implements
1063
1161
  configurePlaylist(configBuilder, prop);
1064
1162
  configureBasicSettings(configBuilder, prop);
1065
1163
  configureStyling(configBuilder, prop);
1066
- configureAdvertising(configBuilder, prop);
1164
+
1165
+ // Check and warn about IMA config, then conditionally configure advertising
1166
+ checkAndWarnImaConfig(null, prop);
1167
+ if (!shouldSkipAdvertising(prop)) {
1168
+ configureAdvertising(configBuilder, prop);
1169
+ }
1170
+
1067
1171
  configureUI(configBuilder, prop);
1068
1172
 
1069
1173
  return configBuilder.build();
@@ -1242,6 +1346,11 @@ public class RNJWPlayerView extends RelativeLayout implements
1242
1346
  if (!forceLegacy) {
1243
1347
  try {
1244
1348
  obj = MapUtil.toJSONObject(prop);
1349
+
1350
+ // Check for IMA config and log warning if IMA is disabled
1351
+ // Don't modify JSON - let parser handle it internally
1352
+ checkAndWarnImaConfig(obj, null);
1353
+
1245
1354
  jwConfig = JsonHelper.parseConfigJson(obj);
1246
1355
  isJwConfig = true;
1247
1356
  } catch (Exception ex) {
@@ -1254,7 +1363,13 @@ public class RNJWPlayerView extends RelativeLayout implements
1254
1363
  configurePlaylist(configBuilder, prop);
1255
1364
  configureBasicSettings(configBuilder, prop);
1256
1365
  configureStyling(configBuilder, prop);
1257
- configureAdvertising(configBuilder, prop);
1366
+
1367
+ // Check and warn about IMA config, then conditionally configure advertising
1368
+ checkAndWarnImaConfig(null, prop);
1369
+ if (!shouldSkipAdvertising(prop)) {
1370
+ configureAdvertising(configBuilder, prop);
1371
+ }
1372
+
1258
1373
  configureUI(configBuilder, prop);
1259
1374
  }
1260
1375
 
@@ -0,0 +1,24 @@
1
+ package com.jwplayer.rnjwplayer;
2
+
3
+ import com.facebook.react.bridge.ReadableMap;
4
+ import com.jwplayer.pub.api.configuration.ads.AdvertisingConfig;
5
+ import com.jwplayer.pub.api.media.ads.AdBreak;
6
+
7
+ import java.util.List;
8
+
9
+ /**
10
+ * Stub implementation when IMA is disabled.
11
+ * Provides clear error messages for users attempting to use IMA without enabling it.
12
+ */
13
+ public class ImaHelper {
14
+
15
+ public static AdvertisingConfig configureImaOrDai(ReadableMap ads, List<AdBreak> adSchedule) {
16
+ // Note: adSchedule parameter is unused in stub - we always throw before using it
17
+ // Passing a valid adSchedule would cause a runtime exception if Google IMA is not enabled
18
+ throw new RuntimeException(
19
+ "Google IMA is not enabled. " +
20
+ "To use IMA ads, add 'RNJWPlayerUseGoogleIMA = true' to your app/build.gradle ext {} block."
21
+ );
22
+ }
23
+ }
24
+
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" role="img" aria-label="version: 1.3.0"><title>version: 1.3.0</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="39" height="20" fill="#007ec6"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">version</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">version</text><text aria-hidden="true" x="695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">1.3.0</text><text x="695" y="140" transform="scale(.1)" fill="#fff" textLength="290">1.3.0</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" role="img" aria-label="version: 1.3.2"><title>version: 1.3.2</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="39" height="20" fill="#007ec6"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">version</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">version</text><text aria-hidden="true" x="695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">1.3.2</text><text x="695" y="140" transform="scale(.1)" fill="#fff" textLength="290">1.3.2</text></g></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jwplayer/jwplayer-react-native",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "React-native Android/iOS plugin for JWPlayer SDK (https://www.jwplayer.com/)",
5
5
  "main": "index.js",
6
6
  "types": "./index.d.ts",