feat: add onAdError event listener (#3381)

* feat: add onAdError event listener
* feat: remove onAdError event listener and use already existing
* feat: add ERROR event to docs
This commit is contained in:
Axel Vencatareddy 2023-12-02 13:52:01 +01:00 committed by GitHub
parent 4d9334b477
commit 596c02d2b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 73 additions and 8 deletions

View File

@ -54,6 +54,10 @@ public class ImaAdsLoader implements AdsLoader {
return this; return this;
} }
public Builder setAdErrorListener(Object ignoredReactExoplayerView) {
return this;
}
public ImaAdsLoader build() { public ImaAdsLoader build() {
return null; return null;
} }

View File

@ -12,6 +12,7 @@ import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.RCTEventEmitter; import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.ads.interactivemedia.v3.api.AdError;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
@ -434,6 +435,19 @@ public class VideoEventEmitter {
receiveEvent(EVENT_ON_RECEIVE_AD_EVENT, map); receiveEvent(EVENT_ON_RECEIVE_AD_EVENT, map);
} }
public void receiveAdErrorEvent(AdError error) {
WritableMap map = Arguments.createMap();
map.putString("event", "ERROR");
WritableMap dataMap = Arguments.createMap();
dataMap.putString("message", error.getMessage());
dataMap.putString("code", String.valueOf(error.getErrorCode()));
dataMap.putString("type", String.valueOf(error.getErrorType()));
map.putMap("data", dataMap);
receiveEvent(EVENT_ON_RECEIVE_AD_EVENT, map);
}
private void receiveEvent(@VideoEvents String type, WritableMap event) { private void receiveEvent(@VideoEvents String type, WritableMap event) {
eventEmitter.receiveEvent(viewId, type, event); eventEmitter.receiveEvent(viewId, type, event);
} }

View File

@ -108,6 +108,7 @@ import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ThemedReactContext;
import com.google.ads.interactivemedia.v3.api.AdEvent; import com.google.ads.interactivemedia.v3.api.AdEvent;
import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.net.CookieHandler; import java.net.CookieHandler;
@ -132,7 +133,8 @@ public class ReactExoplayerView extends FrameLayout implements
BandwidthMeter.EventListener, BandwidthMeter.EventListener,
BecomingNoisyListener, BecomingNoisyListener,
DrmSessionEventListener, DrmSessionEventListener,
AdEvent.AdEventListener { AdEvent.AdEventListener,
AdErrorEvent.AdErrorListener {
public static final double DEFAULT_MAX_HEAP_ALLOCATION_PERCENT = 1; public static final double DEFAULT_MAX_HEAP_ALLOCATION_PERCENT = 1;
public static final double DEFAULT_MIN_BACK_BUFFER_MEMORY_RESERVE = 0; public static final double DEFAULT_MIN_BACK_BUFFER_MEMORY_RESERVE = 0;
@ -621,8 +623,10 @@ public class ReactExoplayerView extends FrameLayout implements
.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF); .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);
// Create an AdsLoader. // Create an AdsLoader.
adsLoader = new ImaAdsLoader.Builder(themedReactContext) adsLoader = new ImaAdsLoader
.Builder(themedReactContext)
.setAdEventListener(this) .setAdEventListener(this)
.setAdErrorListener(this)
.build(); .build();
DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory); DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory);
@ -2103,4 +2107,9 @@ public class ReactExoplayerView extends FrameLayout implements
eventEmitter.receiveAdEvent(adEvent.getType().name()); eventEmitter.receiveAdEvent(adEvent.getType().name());
} }
} }
@Override
public void onAdError(AdErrorEvent adErrorEvent) {
eventEmitter.receiveAdErrorEvent(adErrorEvent.getError());
}
} }

View File

@ -0,0 +1,10 @@
package com.google.ads.interactivemedia.v3.api;
import androidx.annotation.InspectableProperty;
public abstract class AdError {
public abstract InspectableProperty getErrorCode();
public abstract InspectableProperty getErrorCodeNumber();
public abstract InspectableProperty getErrorType();
public abstract String getMessage();
}

View File

@ -0,0 +1,9 @@
package com.google.ads.interactivemedia.v3.api;
public abstract class AdErrorEvent {
public abstract AdError getError();
public interface AdErrorListener {
public void onAdError(AdErrorEvent adErrorEvent);
}
}

View File

@ -370,6 +370,7 @@ Enum `AdEvent` possible values for [Android](https://developers.google.com/inter
| `CONTENT_RESUME_REQUESTED` | Android | Fires when content should be resumed. This usually happens when an ad finishes or collapses. | | `CONTENT_RESUME_REQUESTED` | Android | Fires when content should be resumed. This usually happens when an ad finishes or collapses. |
| `CUEPOINTS_CHANGED` | iOS | Cuepoints changed for VOD stream (only used for dynamic ad insertion). | | `CUEPOINTS_CHANGED` | iOS | Cuepoints changed for VOD stream (only used for dynamic ad insertion). |
| `DURATION_CHANGE` | Android | Fires when the ad's duration changes. | | `DURATION_CHANGE` | Android | Fires when the ad's duration changes. |
| `ERROR` | Android, iOS | Fires when an error occurred while loading the ad and prevent it from playing. |
| `FIRST_QUARTILE` | Android, iOS | Fires when the ad playhead crosses first quartile. | | `FIRST_QUARTILE` | Android, iOS | Fires when the ad playhead crosses first quartile. |
| `IMPRESSION` | Android | Fires when the impression URL has been pinged. | | `IMPRESSION` | Android | Fires when the impression URL has been pinged. |
| `INTERACTION` | Android | Fires when an ad triggers the interaction callback. Ad interactions contain an interaction ID string in the ad data. | | `INTERACTION` | Android | Fires when an ad triggers the interaction callback. Ad interactions contain an interaction ID string in the ad data. |

View File

@ -118,8 +118,22 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate, I
print("AdsManager error: " + error.message!) print("AdsManager error: " + error.message!)
} }
guard let _video = _video else {return}
if _video.onReceiveAdEvent != nil {
_video.onReceiveAdEvent?([
"event": "ERROR",
"data": [
"message": error.message ?? "",
"code": error.code,
"type": error.type,
],
"target": _video.reactTag!
])
}
// Fall back to playing content // Fall back to playing content
_video?.setPaused(false) _video.setPaused(false)
} }
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) { func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {

View File

@ -146,7 +146,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
name: UIApplication.willResignActiveNotification, name: UIApplication.willResignActiveNotification,
object: nil object: nil
) )
NotificationCenter.default.addObserver( NotificationCenter.default.addObserver(
self, self,
selector: #selector(applicationDidBecomeActive(notification:)), selector: #selector(applicationDidBecomeActive(notification:)),
@ -1346,11 +1346,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
_playerObserver.removePlayerTimeObserver() _playerObserver.removePlayerTimeObserver()
} }
} }
@objc func handleAVPlayerAccess(notification:NSNotification!) { @objc func handleAVPlayerAccess(notification:NSNotification!) {
let accessLog:AVPlayerItemAccessLog! = (notification.object as! AVPlayerItem).accessLog() let accessLog:AVPlayerItemAccessLog! = (notification.object as! AVPlayerItem).accessLog()
let lastEvent:AVPlayerItemAccessLogEvent! = accessLog.events.last let lastEvent:AVPlayerItemAccessLogEvent! = accessLog.events.last
onVideoBandwidthUpdate?(["bitrate": lastEvent.observedBitrate, "target": reactTag]) onVideoBandwidthUpdate?(["bitrate": lastEvent.observedBitrate, "target": reactTag])
} }
} }

View File

@ -13,7 +13,6 @@ import NativeVideoComponent, {
} from './VideoNativeComponent'; } from './VideoNativeComponent';
import type {StyleProp, ImageStyle, NativeSyntheticEvent} from 'react-native'; import type {StyleProp, ImageStyle, NativeSyntheticEvent} from 'react-native';
import type {ReactVideoProps} from './types/video';
import {getReactTag, resolveAssetSourceForVideo} from './utils'; import {getReactTag, resolveAssetSourceForVideo} from './utils';
import {VideoManager} from './VideoNativeComponent'; import {VideoManager} from './VideoNativeComponent';
import type { import type {
@ -35,7 +34,8 @@ import type {
OnVideoAspectRatioData, OnVideoAspectRatioData,
OnVideoErrorData, OnVideoErrorData,
OnVideoTracksData, OnVideoTracksData,
} from './types/events'; ReactVideoProps,
} from './types';
export type VideoSaveData = { export type VideoSaveData = {
uri: string; uri: string;

View File

@ -63,6 +63,10 @@ export enum AdEvent {
* Android only: Fires when the ad's duration changes. * Android only: Fires when the ad's duration changes.
*/ */
DURATION_CHANGE = 'DURATION_CHANGE', DURATION_CHANGE = 'DURATION_CHANGE',
/**
* Fires when an error is encountered and the ad can't be played.
*/
ERROR = 'ERROR',
/** /**
* Fires when the ad playhead crosses first quartile. * Fires when the ad playhead crosses first quartile.
*/ */