-jio-start-block-type-2
Complete GETTING STARTED section and INITIALIZE SDK section before starting this section.
-jio-style-title
1.Flutter plugin installation in MacBook for iOS
a. Refer below link for Flutter and Xcode installation setup on MacBook.
https://docs.flutter.dev/get-started/install/macos
2. After installation create project in Flutter
3. After creating project in Flutter we will get separate folder for iOS and flutter.
4. we will be writing code for Jio Ads integration in iOS folder which will be same as in native iOS code.
5. inflate iOS Native view in flutter app:
In order to inflate the native UI element into the flutter app we have to use platform view of flutter.
-jio-style-title
● Import following package.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:io';
● Implement a build()
method.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: AdView(),
);
}
}
class AdView extends StatefulWidget {
@override
_AdViewState createState() => _AdViewState();
}
class _AdViewState extends State<AdView> {
static const platform = MethodChannel('native_view_channel');
String _adType = "";
GlobalKey _adViewKey = GlobalKey();
Future<void> _loadAd(String adType) async {
try {
// Invalidate the current ad before loading a new one
await _invalidateAd();
setState(() {
_adType = adType;
_adViewKey = GlobalKey(); // Change the key to force the UiKitView to rebuild
});
await platform.invokeMethod('loadAd', {"adType": adType});
} on PlatformException catch (e) {
print("Failed to load ad: '${e.message}'.");
}
}
Future<void> _invalidateAd() async {
try {
await platform.invokeMethod('invalidateAd');
} on PlatformException catch (e) {
print("Failed to invalidate ad: '${e.message}'.");
}
}
@override
Widget build(BuildContext context) {
double containerWidth = 300; // Default width
double containerHeight = 250; // Default height
if (_adType == "infeed") {
containerWidth = 320; // Specific width for infeed ad
containerHeight = 50; // Specific height for infeed ad
}
return Scaffold(
appBar: AppBar(
title: Text('Flutter iOS Publisher App'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center, // Center-align the column
children: [
// Define a fixed size for all buttons
SizedBox(
width: 250, // Set the desired width
height: 50, // Set the desired height
child: ElevatedButton(
onPressed: () => _loadAd("instreamadview"),
child: Text("Instream Ad"),
),
),
SizedBox(height: 10), // Add spacing between buttons
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
onPressed: () => _loadAd("nativecontentstreamadview"),
child: Text("NativeContentStream Ad"),
),
),
SizedBox(height: 10),
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
onPressed: () => _loadAd("dynamicdisplayadview"),
child: Text("DynamicDisplay Ad"),
),
),
SizedBox(height: 10), // Add spacing between buttons
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
onPressed: () => _loadAd("customnative"),
child: Text("CustomNative Ad"),
),
),
SizedBox(height: 10), // Add spacing between buttons
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
onPressed: () => _loadAd("infeed"),
child: Text("Infeed Ad"),
),
),
SizedBox(height: 10), // Add spacing between buttons
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
onPressed: () => _loadAd("instreamAudio"),
child: Text("InstreamAudio Ad"),
),
),
SizedBox(height: 10), // Add spacing between buttons
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
onPressed: () => _loadAd("interstitial"),
child: Text("Interstitial Ad"),
),
),
SizedBox(height: 20), // Add spacing before the UiKitView
Center(
child: Container(
width: containerWidth, // Set the width based on ad type
height: containerHeight, // Set the height based on ad type
color: Colors.grey, // Set the background color of the UiKitView
child: UiKitView(
key: _adViewKey, // Use the key to force the UiKitView to rebuild
viewType: _adType,
),
),
),
SizedBox(height: 10), // Add spacing below the UiKitView
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
onPressed: _invalidateAd,
child: Text("Invalidate Ad"),
),
),
],
),
);
}
}
-jio-style-title
In your native code, implement the following:
Embed the Jio Ads Framework Into the Flutter iOS project and Import the JioAdsFramework in the native swift files.
Implement the factory and the platform view.
The JioFLNativeFactory
creates the platform view, and the platform view provides a reference to the UIView.
For example, JioFLNativeView.swift
.
-jio-style-title
JioFLNativeView.swift
import Foundation
import Flutter
import UIKit
import JioAdsFramework
import AVKit
class JioFLNativeView: NSObject, FlutterPlatformView {
private var _view: UIView
private var presentationController = UIViewController()
private var jioAd: JioAd?
private var instreamAdView: JioAdView
private var dynamicDisplayAdView: JioAdView
private var nativeContentStreamAdView: JioAdView
private var customNativeAdView: JioAdView
private var infeedAdView: JioAdView
private var instreamAudioAdView: JioAdView
private var interstitialAdView: JioAdView
private var customNativeView: UIView?
init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?,
adTypeStr: String
) {
_view = UIView()
instreamAdView = JioAdView()
dynamicDisplayAdView = JioAdView()
nativeContentStreamAdView = JioAdView()
customNativeAdView = JioAdView()
infeedAdView = JioAdView()
instreamAudioAdView = JioAdView()
interstitialAdView = JioAdView()
customNativeView = UIView()
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(invalidateAd), name: Notification.Name("invalidateAd"), object: nil)
// iOS views can be created here
instreamAdView.frame = CGRect(x: 0, y: 0, width: 300, height: 250)
dynamicDisplayAdView.frame = CGRect(x: 0, y: 0, width: 300, height: 250)
nativeContentStreamAdView.frame = CGRect(x: 0, y: 0, width: 300, height: 250)
customNativeAdView.frame = CGRect(x: 0, y: 0, width: 300, height: 250)
instreamAudioAdView.frame = CGRect(x: 0, y: 0, width: 300, height: 250)
infeedAdView.frame = CGRect(x: 0, y: 0, width: 300, height: 50)
customNativeView = CustomNativeContentStremView(frame: CGRect(x: 0, y: 0, width: 300, height: 250))
switch adTypeStr {
case "nativecontentstreamadview":
createAdView(view: _view, adTypeStr: adTypeStr)
case "instreamadview":
createAdView(view: _view, adTypeStr: adTypeStr)
case "dynamicdisplayadview":
createAdView(view: _view, adTypeStr: adTypeStr)
case "customnative":
createAdView(view: _view, adTypeStr: adTypeStr)
case "infeed":
createAdView(view: _view, adTypeStr: adTypeStr)
case "instreamAudio":
createAdView(view: _view, adTypeStr: adTypeStr)
case "interstitial":
createAdView(view: _view, adTypeStr: adTypeStr)
default: break
}
}
func view() -> UIView {
return _view
}
func createAdView(view _view: UIView, adTypeStr: String) {
switch adTypeStr {
case "instreamadview":
instreamAdView = JioAdView(adSpotId: "odymbh16", adType: .instreamVideo, delegate: self, forPresentionClass: presentationController, publisherContainer: _view)
self.setValueInUserDefaults(objValue: "Production", for: "currentEnvironment")
//instreamAdView.setRequestedAdDuration(adPodDuration: 200)
// instreamAdView.setRequestedAdCount(adPodCount: 5)
// instreamAdView.setCustomView(container: _view) // This is for custom layout
_view.addSubview(instreamAdView)
instreamAdView.cacheAd()
//_adView.loadCustomAd()
case "nativecontentstreamadview":
nativeContentStreamAdView = JioAdView(adSpotId: "h9tw7nj0", adType: .nativeContentStream, delegate: self, forPresentionClass: presentationController, publisherContainer: _view)
self.setValueInUserDefaults(objValue: "Production", for: "currentEnvironment")
// _adView.setCustomView(container: _view) // This is for custom layout
_view.addSubview(nativeContentStreamAdView)
nativeContentStreamAdView.cacheAd()
case "dynamicdisplayadview":
dynamicDisplayAdView = JioAdView(adSpotId: "h9tw7nj0", adType: .dynamicDisplay, delegate: self, forPresentionClass: presentationController, publisherContainer: _view)
self.setValueInUserDefaults(objValue: "Production", for: "currentEnvironment")
//_adView.setCustomView(container: _view) // This is for custom layout
dynamicDisplayAdView.setDisplayAdSize(displaySizes: [.size300x250])
_view.addSubview(dynamicDisplayAdView)
dynamicDisplayAdView.cacheAd()
case "customnative":
customNativeAdView = JioAdView(adSpotId: "h9tw7nj0", adType: .customNative, delegate: self, forPresentionClass: presentationController, publisherContainer: _view)
self.setValueInUserDefaults(objValue: "Production", for: "currentEnvironment")
customNativeAdView.setCustomImageSize(width: 320, height: 250)
customNativeAdView.setCustomView(container: customNativeView)
customNativeAdView.cacheAd()
//customNativeAdView.loadCustomAd()
case "infeed":
infeedAdView = JioAdView(adSpotId: "h9tw7nj0", adType: .infeed, delegate: self, forPresentionClass: presentationController, publisherContainer: _view)
self.setValueInUserDefaults(objValue: "Production", for: "currentEnvironment")
//_adView.setCustomView(container: _view) // This is for custom layout
_view.addSubview(infeedAdView)
infeedAdView.cacheAd()
case "instreamAudio":
instreamAudioAdView = JioAdView(adSpotId: "8axi63rs", adType: .instreamAudio, delegate: self, forPresentionClass: presentationController, publisherContainer: _view)
self.setValueInUserDefaults(objValue: "Production", for: "currentEnvironment")
//_adView.setCustomView(container: _view) // This is for custom layout
_view.addSubview(instreamAudioAdView)
instreamAudioAdView.cacheAd()
case "interstitial":
interstitialAdView = JioAdView(adSpotId: "h9tw7nj0", adType: .interstitial, delegate: self, forPresentionClass: presentationController, publisherContainer: _view)
self.setValueInUserDefaults(objValue: "Production", for: "currentEnvironment")
//_adView.setCustomView(container: _view) // This is for custom layout
_view.addSubview(interstitialAdView)
interstitialAdView.cacheAd()
default: break
}
}
@objc func invalidateAd() {
print("Ad invalidated")
instreamAdView.invalidateAd()
dynamicDisplayAdView.invalidateAd()
nativeContentStreamAdView.invalidateAd()
customNativeAdView.invalidateAd()
infeedAdView.invalidateAd()
instreamAudioAdView.invalidateAd()
interstitialAdView.invalidateAd()
}
}
extension JioFLNativeView: JIOAdViewProtocol {
func onAdReceived(adView: JioAdsFramework.JioAdView) {
print("onAdReceived")
}
func onAdPrepared(adView: JioAdsFramework.JioAdView) {
print("onAdPrepared")
DispatchQueue.main.async {
if adView == self.instreamAdView {
adView.loadAd()
} else if adView == self.nativeContentStreamAdView {
adView.loadAd()
} else if adView == self.dynamicDisplayAdView {
adView.loadAd()
} else if adView == self.customNativeAdView {
adView.loadAd()
} else if adView == self.infeedAdView {
adView.loadAd()
} else if adView == self.instreamAudioAdView {
adView.loadAd()
} else if adView == self.interstitialAdView {
adView.loadAd()
}
}
}
func onAdRender(adView: JioAdsFramework.JioAdView) {
print("onAdRender")
}
func onAdClicked(adView: JioAdsFramework.JioAdView) {
print("onAdClicked")
}
func onAdRefresh(adView: JioAdsFramework.JioAdView) {
print("onAdRefresh")
}
func onAdFailedToLoad(adView: JioAdsFramework.JioAdView, error: JioAdsFramework.JioAdError) {
print("onAdFailedToLoad")
}
func onAdMediaEnd(adView: JioAdsFramework.JioAdView) {
}
func onAdClosed(adView: JioAdsFramework.JioAdView, isVideoCompleted: Bool, isEligibleForReward: Bool) {
print("onAdClosed")
}
func onAdMediaStart(adView: JioAdsFramework.JioAdView) {
}
func onAdSkippable(adView: JioAdsFramework.JioAdView) {
}
func onAdMediaExpand(adView: JioAdsFramework.JioAdView) {
}
func onAdMediaCollapse(adView: JioAdsFramework.JioAdView) {
}
func onMediaPlaybackChange(adView: JioAdsFramework.JioAdView, mediaPlayBack: JioAdsFramework.MediaPlayBack) {
}
func onAdChange(adView: JioAdsFramework.JioAdView, trackNo: Int) {
}
func onAdDataPrepared(jioAd: JioAd?, isLastAd: Bool, jioAdView: JioAdView?) {
print("onAdDataPrepared Called!!")
let adCatogary = jioAd?.getAdCategory()
self.jioAd = jioAd
if adCatogary == .native {
let nativeAd = jioAd?.getNativeAd()
let title = nativeAd?.getTitle
let desc1 = nativeAd?.getDescription
let iConImageURL = nativeAd?.getIconImage
let mainImageURL = nativeAd?.getMainImage
let ctaText = nativeAd?.getCtaText
print("Title \(String(describing: title))")
print("desc1 \(String(describing: desc1))")
print("iConImageURL \(String(describing: iConImageURL))")
print("mainImageURL \(String(describing: mainImageURL))")
print("ctaText \(String(describing: ctaText))")
} else {
let videoAd = jioAd?.getVideoAd()
let mediaFile = videoAd?.selectedMediaFile
print("Selected Media File \(String(describing: mediaFile))")
}
}
}
extension JioFLNativeView {
func setValueInUserDefaults(objValue:String,for key:String) {
let userDefault = UserDefaults.standard
userDefault.set(objValue, forKey: key)
userDefault.synchronize()
}
}
-jio-style-title
JioFLNativeFactory.swift
Create a factory class that creates an instance of the JioFLNativeView
created earlier (for example, JioFLNativeFactory.swift
):
class JioFLNativeFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
var adTypeStr: String
init(messenger: FlutterBinaryMessenger, adType: String) {
self.messenger = messenger
self.adTypeStr = adType
super.init()
}
func create(
withFrame frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?
) -> FlutterPlatformView {
return JioFLNativeView(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger, adTypeStr: adTypeStr)
}
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec.sharedInstance()
}
}
-jio-style-title
For plugin registration, modify the plugin’s main file (for example, JioFLPlugin.swift
)
import Flutter
import UIKit
class JioFLPlugin: NSObject, FlutterPlugin {
private static var factory: JioFLNativeFactory?
public static func register(with registrar: FlutterPluginRegistrar) {
factory = JioFLNativeFactory(messenger: registrar.messenger(), adType: "instreamadview")
if let factory = self.factory {
registrar.register(factory, withId: "instreamadview")
registrar.register(factory, withId: "nativecontentstreamadview")
registrar.register(factory, withId: "dynamicdisplayadview")
registrar.register(factory, withId: "customnative")
registrar.register(factory, withId: "infeed")
registrar.register(factory, withId: "instreamAudio")
registrar.register(factory, withId: "interstitial")
}
}
static func updateAdType(adType: String) {
factory?.adTypeStr = adType
}
}
-jio-style-title
Finally, register the platform view. You can do this in an app or a plugin.
For app registration, modify the app’s AppDelegate
file.
import UIKit
import Flutter
import JioAdsFramework
import Foundation
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
private let channelName = "native_view_channel"
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger)
methodChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
if call.method == "loadAd" {
if let args = call.arguments as? [String: Any],
let adType = args["adType"] as? String {
JioFLPlugin.updateAdType(adType: adType)
result("Ad type updated to \(adType)")
} else {
result(FlutterError(code: "INVALID_ARGUMENT", message: "Ad type is missing", details: nil))
}
} else if call.method == "invalidateAd" {
NotificationCenter.default.post(name: Notification.Name("invalidateAd"), object: nil)
result("Ad invalidated")
} else {
result(FlutterMethodNotImplemented)
}
}
JioFLPlugin.register(with: self.registrar(forPlugin: "my_flutter_app")!)
JioAdSdk.setLogLevel(logLevel: .debug)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
-jio-style-title
Use the CustomNativeContentStremView.xib
and CustomNativeContentStremView
swift files for CutsomNative adtype.
Refer the sample app provided for more understanding.
https://docs.flutter.dev/platform-integration/ios/platform-views?tab=ios-platform-views-swift-tab
-jio-end-block-type-2