visit
expo init Media
I’m selecting the blank template. For more information on Expo and settings needed, check out .
cd Media
yarn ios
You should now see the iOS app running inside the Expo Go Client.
expo install @react-navigation/native
expo install react-native-screens react-native-safe-area-context
expo install @react-navigation/native-stack
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Create a folder “screens” and a new JS File “VideoScreen.js” in it:
import * as React from "react";
import { View, Text } from "react-native";
export default function VideoScreen() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Video Screen</Text>
</View>
);
}
import * as React from 'react';
import { View, Text, Button } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import VideoScreen from './screens/VideoScreen';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Video"
onPress={() => navigation.navigate('Video')}
/>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Video" component={VideoScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
expo run:ios
source '//github.com/CocoaPods/Specs.git'
...
# (below target 'Media' do)
pod 'GoogleAds-IMA-iOS-SDK'
...
pod install --repo-update
#import <Foundation/Foundation.h>
#import <React/RCTViewManager.h>
#import "Media-Swift.h"
@interface RNTVideoViewManager : RCTViewManager
@end
@implementation RNTVideoViewManager
RCT_EXPORT_VIEW_PROPERTY(videoUrl, NSString);
RCT_EXPORT_VIEW_PROPERTY(adTagUrl, NSString);
RCT_EXPORT_MODULE()
- (UIView *)view {
return [VideoView new];
}
@end
import UIKit
class VideoView: UIView {
weak var videoViewController: VideoViewController?
@objc var videoUrl: String? {
didSet {
setNeedsLayout()
}
}
@objc var adTagUrl: String? {
didSet {
setNeedsLayout()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) { fatalError("nope") }
override func layoutSubviews() {
super.layoutSubviews()
if (self.videoViewController==nil) {
embed()
} else {
videoViewController?.view.frame = bounds
}
}
private func embed() {
guard
let parentVC = parentViewController
else {
return
}
let vc = VideoViewController()
vc.videoUrl = videoUrl ?? ""
vc.adTagUrl = adTagUrl ?? ""
vc.videoView = self
parentVC.addChild(vc)
addSubview(vc.view)
vc.view.frame = bounds
vc.didMove(toParent: parentVC)
self.videoViewController = vc
}
}
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
import AVFoundation
import AVKit
import UIKit
import GoogleInteractiveMediaAds
class VideoViewController: UIViewController, IMAAdsLoaderDelegate,IMAAdsManagerDelegate {
var videoUrl:String = ""
var adTagUrl:String = ""
var videoView:VideoView?
var adsLoader: IMAAdsLoader!
var adsManager: IMAAdsManager!
var contentPlayhead: IMAAVPlayerContentPlayhead?
var playerViewController: AVPlayerViewController!
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.black;
setUpContentPlayer()
setUpAdsLoader()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated);
requestAds()
}
func setUpContentPlayer() {
// Load AVPlayer with path to your content.
do{
// Configure and activate the AVAudioSession
// so the video sound will play even when the iPhone is muted
try AVAudioSession.sharedInstance().setCategory(
AVAudioSession.Category.playback
)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
//error setting audio
}
let contentURL = URL(string: videoUrl)
let player = AVPlayer(url: contentURL!)
playerViewController = AVPlayerViewController()
playerViewController.player = player
// Set up your content playhead and contentComplete callback.
contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: player)
NotificationCenter.default.addObserver(
self,
selector: #selector(VideoViewController.contentDidFinishPlaying(_:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: player.currentItem);
showContentPlayer()
}
func showContentPlayer() {
self.addChild(playerViewController)
playerViewController.view.frame = self.view.bounds
self.view.insertSubview(playerViewController.view, at: 0)
playerViewController.didMove(toParent:self)
}
func hideContentPlayer() {
// The whole controller needs to be detached so that it doesn't capture events from the remote.
playerViewController.willMove(toParent:nil)
playerViewController.view.removeFromSuperview()
playerViewController.removeFromParent()
}
func setUpAdsLoader() {
adsLoader = IMAAdsLoader(settings: nil)
adsLoader.delegate = self
}
func requestAds() {
// Create ad display container for ad rendering.
let adDisplayContainer = IMAAdDisplayContainer(adContainer: self.view, viewController: self)
// Create an ad request with our ad tag, display container, and optional user context.
let request = IMAAdsRequest(
adTagUrl: adTagUrl,
adDisplayContainer: adDisplayContainer,
contentPlayhead: contentPlayhead,
userContext: nil)
adsLoader.requestAds(with: request)
}
@objc func contentDidFinishPlaying(_ notification: Notification) {
adsLoader.contentComplete()
}
// MARK: - IMAAdsLoaderDelegate
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
adsManager = adsLoadedData.adsManager
adsManager.delegate = self
adsManager.initialize(with: nil)
}
func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
showContentPlayer()
playerViewController.player?.play()
}
// MARK: - IMAAdsManagerDelegate
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
// Play each ad once it has been loaded
if event.type == IMAAdEventType.LOADED {
adsManager.start()
}
}
func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) {
// Fall back to playing content
showContentPlayer()
playerViewController.player?.play()
}
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
// Pause the content for the SDK to play ads.
playerViewController.player?.pause()
hideContentPlayer()
}
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
// Resume the content since the SDK is done playing ads (at least for now).
showContentPlayer()
playerViewController.player?.play()
}
}
// requireNativeComponent automatically resolves 'RNTVideoView' to 'RNTVideoViewManager'
import { requireNativeComponent } from "react-native";
module.exports = requireNativeComponent("RNTVideoView");
import * as React from "react";
import { View, Text, Dimensions } from "react-native";
import Constants from "expo-constants";
import VideoViewIos from "../components/VideoViewIos"
const videoLink = "//devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8";
const adTagUrl = "//pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ct%3Dlinear&correlator=";
const width=Dimensions.get("window").width;
export default function VideoScreen() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
{Constants.platform.ios && (
<VideoViewIos
videoUrl={videoLink}
adTagUrl={adTagUrl}
style={{
height: width * 0.56,
width: width,
backgroundColor: "grey",
}}
/>
)}
</View>
);
}
"ios": {
...
"config": {
"googleMobileAdsAppId": "ca-app-pub-XXXXX~XXXXX"
}
},
or in your Info.plist in your Xcode project
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-XXXXX~XXXXX</string>
Expo
Using Native Components in React Native
React Navigation
Google IMA