Skip to content

Commit

Permalink
feat: add ads localize (#4113)
Browse files Browse the repository at this point in the history
* add prop adLanguage; add docs

* add native code ios&android for adLanguage props

* add missing function to adsLoader and imafactory

* Update docs/pages/component/ads.md

Language correction

Co-authored-by: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>

---------

Co-authored-by: Guy <guyha@reshet.tv>
Co-authored-by: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>
  • Loading branch information
3 people authored Aug 29, 2024
1 parent 9c38d9f commit 703ed43
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@
import androidx.media3.exoplayer.source.ads.AdsLoader;
import androidx.media3.exoplayer.source.ads.AdsMediaSource;

import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;

import java.io.IOException;

public class ImaAdsLoader implements AdsLoader {
private final ImaSdkSettings imaSdkSettings;

public ImaAdsLoader(ImaSdkSettings imaSdkSettings) {
this.imaSdkSettings = imaSdkSettings;
}

public void setPlayer(ExoPlayer ignoredPlayer) {
}

Expand Down Expand Up @@ -45,6 +53,7 @@ public void handlePrepareError(@NonNull AdsMediaSource adsMediaSource, int i, in
}

public static class Builder {
private ImaSdkSettings imaSdkSettings;
public Builder(Context ignoredThemedReactContext) {
}

Expand All @@ -56,6 +65,11 @@ public Builder setAdErrorListener(Object ignoredReactExoplayerView) {
return this;
}

public Builder setImaSdkSettings(ImaSdkSettings imaSdkSettings) {
this.imaSdkSettings = imaSdkSettings;
return this;
}

public ImaAdsLoader build() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@
import com.google.ads.interactivemedia.v3.api.AdError;
import com.google.ads.interactivemedia.v3.api.AdEvent;
import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
import com.google.ads.interactivemedia.v3.api.ImaSdkFactory;
import com.google.common.collect.ImmutableList;

import java.net.CookieHandler;
Expand Down Expand Up @@ -251,6 +253,7 @@ public class ReactExoplayerView extends FrameLayout implements
private boolean mReportBandwidth = false;
private boolean controls;
private Uri adTagUrl;
private String adLanguage;

private boolean showNotificationControls = false;
// \ End props
Expand Down Expand Up @@ -754,9 +757,13 @@ private void initializePlayerCore(ReactExoplayerView self) {
.setEnableDecoderFallback(true)
.forceEnableMediaCodecAsynchronousQueueing();

ImaSdkSettings imaSdkSettings = ImaSdkFactory.getInstance().createImaSdkSettings();
imaSdkSettings.setLanguage(adLanguage);

// Create an AdsLoader.
adsLoader = new ImaAdsLoader
.Builder(themedReactContext)
.setImaSdkSettings(imaSdkSettings)
.setAdEventListener(this)
.setAdErrorListener(this)
.build();
Expand Down Expand Up @@ -1851,6 +1858,10 @@ public void setAdTagUrl(final Uri uri) {
adTagUrl = uri;
}

public void setAdLanguage(final String language) {
adLanguage = language;
}

public void setTextTracks(SideLoadedTextTrackList textTracks) {
this.textTracks = textTracks;
reloadSource(); // FIXME Shall be moved inside source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ReactExoplayerViewManager(private val config: ReactExoplayerConfig) : View
private const val REACT_CLASS = "RCTVideo"
private const val PROP_SRC = "src"
private const val PROP_AD_TAG_URL = "adTagUrl"
private const val PROP_AD_LANGUAGE = "adLanguage"
private const val PROP_RESIZE_MODE = "resizeMode"
private const val PROP_REPEAT = "repeat"
private const val PROP_SELECTED_AUDIO_TRACK = "selectedAudioTrack"
Expand Down Expand Up @@ -110,6 +111,16 @@ class ReactExoplayerViewManager(private val config: ReactExoplayerConfig) : View
videoView.setAdTagUrl(adTagUrl)
}

@ReactProp(name = PROP_AD_LANGUAGE)
fun setAdLanguage(videoView: ReactExoplayerView, languageString: String?) {
if (TextUtils.isEmpty(languageString)) {
videoView.setAdLanguage(null) // Maybe "en" default?
return
}

videoView.setAdLanguage(languageString)
}

@ReactProp(name = PROP_RESIZE_MODE)
fun setResizeMode(videoView: ReactExoplayerView, resizeMode: String) {
when (resizeMode) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.google.ads.interactivemedia.v3.api;

public abstract class ImaSdkFactory {
private static ImaSdkFactory instance;

public abstract ImaSdkSettings createImaSdkSettings();

public static ImaSdkFactory getInstance() {
if (instance == null) {
instance = new ConcreteImaSdkFactory();
}
return instance;
}
}

class ConcreteImaSdkFactory extends ImaSdkFactory {

@Override
public ImaSdkSettings createImaSdkSettings() {
return new ConcreteImaSdkSettings();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.google.ads.interactivemedia.v3.api;

import androidx.annotation.InspectableProperty;

public abstract class ImaSdkSettings {
public abstract String getLanguage();
public abstract void setLanguage(String language);
}

// Concrete Implementation
class ConcreteImaSdkSettings extends ImaSdkSettings {

private String language;

@Override
public String getLanguage() {
return language;
}

@Override
public void setLanguage(String language) {
this.language = language;
}
}
13 changes: 13 additions & 0 deletions docs/pages/component/ads.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,16 @@ Example:
onReceiveAdEvent={event => console.log(event)}
...
```

### Localization
To change the language of the IMA SDK, you need to pass `adLanguage` prop to `Video` component. List of supported languages, you can find [here](https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/localization#locale-codes)

By default, ios will use system language and android will use `en`

Example:

```jsx
...
adLanguage="fr"
...
```
7 changes: 6 additions & 1 deletion ios/Video/Features/RCTIMAAdsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
}

func setUpAdsLoader() {
adsLoader = IMAAdsLoader(settings: nil)
guard let _video else { return }
let settings = IMASettings()
if let adLanguage = _video.getAdLanguage() {
settings.language = adLanguage
}
adsLoader = IMAAdsLoader(settings: settings)
adsLoader.delegate = self
}

Expand Down
5 changes: 5 additions & 0 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH

/* IMA Ads */
private var _adTagUrl: String?
private var _adLanguage: String?
#if USE_GOOGLE_IMA
private var _imaAdsManager: RCTIMAAdsManager!
/* Playhead used by the SDK to track content video progress and insert mid-rolls. */
Expand Down Expand Up @@ -1222,6 +1223,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH

// MARK: - RCTIMAAdsManager

func getAdLanguage() -> String? {
return _adLanguage
}

func getAdTagUrl() -> String? {
return _adTagUrl
}
Expand Down
1 change: 1 addition & 0 deletions ios/Video/RCTVideoManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ @interface RCT_EXTERN_MODULE (RCTVideoManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(src, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(drm, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(adTagUrl, NSString);
RCT_EXPORT_VIEW_PROPERTY(adLanguage, NSString);
RCT_EXPORT_VIEW_PROPERTY(maxBitRate, float);
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString);
RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL);
Expand Down
1 change: 1 addition & 0 deletions src/specs/VideoNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ export type OnControlsVisibilityChange = Readonly<{
export interface VideoNativeProps extends ViewProps {
src?: VideoSrc;
adTagUrl?: string;
adLanguage?: string;
allowsExternalPlayback?: boolean; // ios, true
disableFocus?: boolean; // android
maxBitRate?: Float;
Expand Down
1 change: 1 addition & 0 deletions src/types/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
drm?: Drm;
style?: StyleProp<ViewStyle>;
adTagUrl?: string;
adLanguage?: ISO639_1;
audioOutput?: AudioOutput; // Mobile
automaticallyWaitsToMinimizeStalling?: boolean; // iOS
bufferConfig?: BufferConfig; // Android
Expand Down

0 comments on commit 703ed43

Please sign in to comment.