Google IMA ads in Flutter
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 :
Here is reference project link available in github