@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.
- package/android/build.gradle +17 -4
- package/android/src/ima/java/com/jwplayer/rnjwplayer/ImaHelper.java +142 -0
- package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerAds.java +41 -129
- package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerView.java +118 -3
- package/android/src/noima/java/com/jwplayer/rnjwplayer/ImaHelper.java +24 -0
- package/badges/version.svg +1 -1
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
41
|
-
} catch (
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
|
package/badges/version.svg
CHANGED
|
@@ -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.
|
|
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>
|