Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add onAdError event listener #3381

Merged
merged 6 commits into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public Builder setAdEventListener(Object ignoredReactExoplayerView) {
return this;
}

public Builder setAdErrorListener(Object ignoredReactExoplayerView) {
return this;
}

public ImaAdsLoader build() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.ads.interactivemedia.v3.api.AdError;

import java.io.PrintWriter;
import java.io.StringWriter;
Expand Down Expand Up @@ -434,6 +435,19 @@ public void receiveAdEvent(String event) {
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) {
eventEmitter.receiveEvent(viewId, type, event);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.uimanager.ThemedReactContext;
import com.google.ads.interactivemedia.v3.api.AdEvent;
import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
import com.google.common.collect.ImmutableList;

import java.net.CookieHandler;
Expand All @@ -132,7 +133,8 @@ public class ReactExoplayerView extends FrameLayout implements
BandwidthMeter.EventListener,
BecomingNoisyListener,
DrmSessionEventListener,
AdEvent.AdEventListener {
AdEvent.AdEventListener,
AdErrorEvent.AdErrorListener {

public static final double DEFAULT_MAX_HEAP_ALLOCATION_PERCENT = 1;
public static final double DEFAULT_MIN_BACK_BUFFER_MEMORY_RESERVE = 0;
Expand Down Expand Up @@ -621,8 +623,10 @@ private void initializePlayerCore(ReactExoplayerView self) {
.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);

// Create an AdsLoader.
adsLoader = new ImaAdsLoader.Builder(themedReactContext)
adsLoader = new ImaAdsLoader
.Builder(themedReactContext)
.setAdEventListener(this)
.setAdErrorListener(this)
.build();

DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory);
Expand Down Expand Up @@ -2103,4 +2107,9 @@ public void onAdEvent(AdEvent adEvent) {
eventEmitter.receiveAdEvent(adEvent.getType().name());
}
}

@Override
public void onAdError(AdErrorEvent adErrorEvent) {
eventEmitter.receiveAdErrorEvent(adErrorEvent.getError());
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
1 change: 1 addition & 0 deletions docs/pages/component/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
| `CUEPOINTS_CHANGED` | iOS | Cuepoints changed for VOD stream (only used for dynamic ad insertion). |
| `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. |
| `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. |
Expand Down
16 changes: 15 additions & 1 deletion ios/Video/Features/RCTIMAAdsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,22 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate, I
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
_video?.setPaused(false)
_video.setPaused(false)
}

func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
Expand Down
6 changes: 3 additions & 3 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
name: UIApplication.willResignActiveNotification,
object: nil
)

NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidBecomeActive(notification:)),
Expand Down Expand Up @@ -1346,11 +1346,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
_playerObserver.removePlayerTimeObserver()
}
}

@objc func handleAVPlayerAccess(notification:NSNotification!) {
let accessLog:AVPlayerItemAccessLog! = (notification.object as! AVPlayerItem).accessLog()
let lastEvent:AVPlayerItemAccessLogEvent! = accessLog.events.last

onVideoBandwidthUpdate?(["bitrate": lastEvent.observedBitrate, "target": reactTag])
}
}
4 changes: 2 additions & 2 deletions src/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import NativeVideoComponent, {
} from './VideoNativeComponent';

import type {StyleProp, ImageStyle, NativeSyntheticEvent} from 'react-native';
import type {ReactVideoProps} from './types/video';
import {getReactTag, resolveAssetSourceForVideo} from './utils';
import {VideoManager} from './VideoNativeComponent';
import type {
Expand All @@ -35,7 +34,8 @@ import type {
OnVideoAspectRatioData,
OnVideoErrorData,
OnVideoTracksData,
} from './types/events';
ReactVideoProps,
} from './types';

export type VideoSaveData = {
uri: string;
Expand Down
4 changes: 4 additions & 0 deletions src/types/Ads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ export enum AdEvent {
* Android only: Fires when the ad's duration changes.
*/
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.
*/
Expand Down
Loading