Google IMA ads in Flutter

harsh shah
4 min readMay 3, 2022

Interactive Media Ads (IMA) is a suite of SDKs that make it easy to integrate multimedia ads into your websites and apps. IMA SDKs can request ads from any VAST-compliant ad server and manage ad playback in your apps

Currently, IMA SDK is not available on flutter but actually, I have integrated IMA SDK on flutter through PlatformView

Platform views allow you to embed native views in a Flutter app, so you can apply transforms, clips, and opacity to the native view from Dart.

MethodChannel is used for "communicating with platform plugins using asynchronous method calls". This means that you use this channel to invoke methods on the native side and can return back a value and vice versa

Dart side :

Here we have pass “NativeUI” as viewType in AndroidView and UiKitView widgets. The viewType matches the name of the PlatformViewFactory key we use on native side.

String viewType = 'NativeUI';if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
viewType: viewType,
onPlatformViewCreated: onPlatformViewCreated,
creationParams: <String,dynamic>{
"x": widget.x,
"y": widget.y,
"width": widget.width,
"height": widget.height,
"videoURL":"https://storage.googleapis.com/gvabox/media/samples/stock.mp4"
},

creationParamsCodec: const StandardMessageCodec(),
);
} else {
return UiKitView(
viewType: viewType,
onPlatformViewCreated: onPlatformViewCreated,
creationParams: <String,dynamic>{
"x": widget.x,
"y": widget.y,
"width": widget.width,
"height": widget.height,
"videoURL":"https://storage.googleapis.com/gvabox/media/samples/stock.mp4"
},
creationParamsCodec: const StandardMessageCodec(),
);
}

Platform side

Android side :

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)

flutterEngine
.platformViewsController
.registry
.registerViewFactory("NativeUI", NativeViewFactory(flutterEngine.dartExecutor.binaryMessenger,this))
}

IOS side :

let factory = NativeViewFactory(messenger:registrar!.messenger())
registrar!.register(factory,withId: "NativeUI")

NativeView Factory

Android Side :

class NativeViewFactory(private val messenger: BinaryMessenger, private val mainActivity: com.example.flios.MainActivity) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
val creationParams = args as Map<String?, Any?>?
return NativeView(context, viewId, creationParams,messenger,mainActivity)
}
}

IOS Side :

func create(withFrame frame: CGRect,viewIdentifier 
viewId: Int64,arguments args: Any?) -> FlutterPlatformView {
return NativeView(frame: frame,viewIdentifier: viewId,arguments: args,binaryMessenger: messenger)
}

Controller :

we create a Controller to handle the communication back and forth between the native view and Flutter

BmsVideoPlayerController.init(int id) {
_channel = new MethodChannel('bms_video_player');
}

Future<void> loadUrl(String url) async {
assert(url != null);
return _channel.invokeMethod('loadUrl', url);
}

Future<void> pauseVideo() async {
return _channel.invokeMethod('pauseVideo', 'pauseVideo');
}

Future<void> resumeVideo() async {
return _channel.invokeMethod('resumeVideo', 'resumeVideo');
}

Let’s assume we have a simple Flutter screen with the main body as a Listview widget.Here we have videoPlayer widget set as child widget

BmsVideoPlayer videoPlayer = new BmsVideoPlayer(
onCreated: onViewPlayerCreated,
x: x,
y: y,
width: width,
height: height
);

return Scaffold(
appBar: isNormalScreen?AppBar(
title: Text("Video plugin"),
):null,
body:
ListView.builder(
itemCount: 1,
itemBuilder: (BuildContext context, int index) {
return Container(
child: videoPlayer,
width: width,
height: height,
color: Colors.black,
);
},
),
);

Platform View

The NativeView is essentially a wrapper class for our native view, in this case NativeViewFactory. In order for Flutter to know to create which native view to create.

Android side :

nternal class NativeView(context: Context, id: Int, creationParams: Map<String?, Any?>?, messenger: BinaryMessenger,
mainActivity: com.example.flios.MainActivity) : PlatformView,
MethodChannel.MethodCallHandler {

override fun getView(): View {
return playerView
}

IOS side :

public class NativeView : NSObject, FlutterPlatformView,fullScreeenDelegate, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {


init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
) {
_view = UIView()
super.init()
}

Android side we have used exoplayer plugin and ios side we have used GSPlayer.

build.gradle :

implementation 'com.google.android.exoplayer:exoplayer-core:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.16.1'

// The library adds the IMA ExoPlayer integration for ads.
implementation 'com.google.android.exoplayer:extension-ima:2.16.1'

Pod file :

pod 'GoogleAds-IMA-iOS-SDK', '~> 3.14.5'
pod 'GSPlayer'

Sample ad tags

Result :

--

--

harsh shah

Mobile Developer (Android , flutter) - 5 Years , Worked on multiple domain like pharma , financial , Ecommerce , BLE .