Skip to content

Commit

Permalink
feat: add onAdError event listener
Browse files Browse the repository at this point in the history
  • Loading branch information
avencat committed Nov 24, 2023
1 parent 0c0f317 commit 1f68ddf
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public VideoEventEmitter(ReactContext reactContext) {
private static final String EVENT_TEXT_TRACKS = "onTextTracks";
private static final String EVENT_VIDEO_TRACKS = "onVideoTracks";
private static final String EVENT_ON_RECEIVE_AD_EVENT = "onReceiveAdEvent";
private static final String EVENT_ON_AD_ERROR = "onAdError";

static public final String[] Events = {
EVENT_LOAD_START,
Expand Down Expand Up @@ -83,7 +84,8 @@ public VideoEventEmitter(ReactContext reactContext) {
EVENT_TEXT_TRACKS,
EVENT_VIDEO_TRACKS,
EVENT_BANDWIDTH,
EVENT_ON_RECEIVE_AD_EVENT
EVENT_ON_RECEIVE_AD_EVENT,
EVENT_ON_AD_ERROR
};

@Retention(RetentionPolicy.SOURCE)
Expand Down Expand Up @@ -113,7 +115,8 @@ public VideoEventEmitter(ReactContext reactContext) {
EVENT_TEXT_TRACKS,
EVENT_VIDEO_TRACKS,
EVENT_BANDWIDTH,
EVENT_ON_RECEIVE_AD_EVENT
EVENT_ON_RECEIVE_AD_EVENT,
EVENT_ON_AD_ERROR
})
@interface VideoEvents {
}
Expand Down Expand Up @@ -420,6 +423,15 @@ public void receiveAdEvent(String event) {
receiveEvent(EVENT_ON_RECEIVE_AD_EVENT, map);
}

public void receiveAdErrorEvent(AdError error) {
WritableMap map = Arguments.createMap();
map.putString("message", error.getMessage());
map.putString("code", String.valueOf(error.getErrorCode()));
map.putString("type", String.valueOf(error.getErrorType()));

receiveEvent(EVENT_ON_AD_ERROR, 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 @@ -103,6 +103,7 @@
import com.facebook.react.bridge.ReadableMap;
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.android.exoplayer2.ext.ima.ImaAdsLoader;
import com.google.common.collect.ImmutableList;

Expand All @@ -128,7 +129,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 @@ -616,7 +618,11 @@ private void initializePlayerCore(ReactExoplayerView self) {
.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);

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

MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory)
.setLocalAdInsertionComponents(unusedAdTagUri -> adsLoader, exoPlayerView);
Expand Down Expand Up @@ -2090,4 +2096,9 @@ public void setShutterColor(Integer color) {
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 InspectableProperty 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 AdErrorEventListener {
public void onAdErrorEvent(AdErrorEvent adErrorEvent);
}
}
13 changes: 12 additions & 1 deletion ios/Video/Features/RCTIMAAdsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,19 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate, I
print("AdsManager error: " + error.message!)
}

guard let _video = _video else {return}

if _video.onAdError != nil {
_video.onAdError?([
"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
7 changes: 4 additions & 3 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
@objc var onRestoreUserInterfaceForPictureInPictureStop: RCTDirectEventBlock?
@objc var onGetLicense: RCTDirectEventBlock?
@objc var onReceiveAdEvent: RCTDirectEventBlock?
@objc var onAdError: RCTDirectEventBlock?

@objc func _onPictureInPictureStatusChanged() {
onPictureInPictureStatusChanged?([ "isActive": NSNumber(value: true)])
Expand Down Expand Up @@ -145,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 @@ -1332,11 +1333,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])
}
}
1 change: 1 addition & 0 deletions ios/Video/RCTVideoManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ @interface RCT_EXTERN_MODULE(RCTVideoManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(onPictureInPictureStatusChanged, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onRestoreUserInterfaceForPictureInPictureStop, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onReceiveAdEvent, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onAdError, RCTDirectEventBlock);

RCT_EXTERN_METHOD(save:(NSDictionary *)options
reactTag:(nonnull NSNumber *)reactTag
Expand Down
14 changes: 12 additions & 2 deletions src/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ 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 {
OnAdErrorData,
OnAudioFocusChangedData,
OnAudioTracksData,
OnBandwidthUpdateData,
Expand All @@ -35,7 +35,8 @@ import type {
OnVideoAspectRatioData,
OnVideoErrorData,
OnVideoTracksData,
} from './types/events';
ReactVideoProps,
} from './types';

export type VideoSaveData = {
uri: string;
Expand Down Expand Up @@ -83,6 +84,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
onReadyForDisplay,
onPlaybackRateChange,
onVolumeChange,
onAdError,
onAudioBecomingNoisy,
onPictureInPictureStatusChanged,
onRestoreUserInterfaceForPictureInPictureStop,
Expand Down Expand Up @@ -399,6 +401,13 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
[onReceiveAdEvent],
);

const _onAdError = useCallback(
(e: NativeSyntheticEvent<OnAdErrorData>) => {
onAdError?.(e.nativeEvent);
},
[onAdError],
);

const _onVideoAspectRatio = useCallback(
(e: NativeSyntheticEvent<OnVideoAspectRatioData>) => {
onAspectRatio?.(e.nativeEvent);
Expand Down Expand Up @@ -494,6 +503,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
selectedTextTrack={_selectedTextTrack}
selectedAudioTrack={_selectedAudioTrack}
selectedVideoTrack={_selectedVideoTrack}
onAdError={_onAdError}
onGetLicense={onGetLicense}
onVideoLoad={onVideoLoad}
onVideoLoadStart={onVideoLoadStart}
Expand Down
3 changes: 2 additions & 1 deletion src/VideoNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {NativeModules, requireNativeComponent} from 'react-native';
import type ResizeMode from './types/ResizeMode';
import type FilterType from './types/FilterType';
import type Orientation from './types/Orientation';
import type {AdEvent, OnTextTracksTypeData} from './types';
import type {AdEvent, OnAdErrorData, OnTextTracksTypeData} from './types';

// -------- There are types for native component (future codegen) --------
// if you are looking for types for react component, see src/types/video.ts
Expand Down Expand Up @@ -354,6 +354,7 @@ export interface VideoNativeProps extends ViewProps {
onReceiveAdEvent?: (
event: NativeSyntheticEvent<OnReceiveAdEventData>,
) => void;
onAdError?: (event: NativeSyntheticEvent<OnAdErrorData>) => void;
onVideoPlaybackStateChanged?: (
event: NativeSyntheticEvent<OnPlaybackStateChangedData>,
) => void; // android only
Expand Down
7 changes: 7 additions & 0 deletions src/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ export type OnReceiveAdEventData = Readonly<{
event: AdEvent;
}>;

export type OnAdErrorData = Readonly<{
code: string;
message: string;
type: string;
}>;

export type OnVideoErrorData = Readonly<{
error: OnVideoErrorDataDetails;
target?: number; // ios
Expand Down Expand Up @@ -152,6 +158,7 @@ export type OnBandwidthUpdateData = Readonly<
>;

export interface ReactVideoEvents {
onAdError?: (error: OnAdErrorData) => void; // Android, iOS
onAudioBecomingNoisy?: () => void; //Android, iOS
onAudioFocusChanged?: (e: OnAudioFocusChangedData) => void; // Android
onIdle?: () => void; // Android
Expand Down

0 comments on commit 1f68ddf

Please sign in to comment.