How to implement MRAID 3.0 on Android

Tomasz Ciołkowski

As the number of mobile devices’ users rises, so does the importance of mobile ads. Especially rich media ads that display videos, play audio, change size etc. have gained popularity, since they are more effective and engaging than standard, static ads.

However, it is difficult for those ads to interact with mobile operating systems to provide rich media experience. Mobile devices run on different platforms (Android, iOS), have different hardware, screen sizes etc. This article describes the MRAID standard that addresses these problems. It also explains how to implement a custom MRAID 3.0 solution for Android.

What is MRAID?

In order to perform complex operations (e.g. changing its size to fullscreen) an ad needs a way to communicate with a mobile application into which the ad is served. The application needs to expose an interface for the ad. Via this interface the ad can for example query the host application about the screen size of the device and request that the ad banner is resized to that size.

MRAID (“Mobile Rich Media Ad Interface Definitions”) is the common API (Application Programming Interface) for mobile rich media ads that will run in mobile applications. It is a standard that describes the interface between an ad and a host application. It defines a set of methods (functions) that an application should expose to an ad, and a set of events that the application can send to the ad. MRAID unifies the behavior of MRAID-compliant applications regardless of whether the application runs on Android, iOS or any other system. This way, the same ad can be used on a number of different devices.

An ad that runs in the host (application) with MRAID support is able to perform the following operations:

  • query the host about the maximum size that the ad can expand/resize to (e.g. full screen size)
  • change its size / expand to full screen
  • query the host about the ad’s current position on screen
  • update its position on screen
  • offer the application’s user an option to store an image in the device's photo album or to create an event in user’s calendar application
  • query the host about the current orientation of the device
  • request that the full screen ad is open in specific device orientation (portrait or landscape)
  • send VPAID (Video Player Ad Interface Definition) events
  • check if the host supports features such as: sending SMS messages, initiating phone calls, creating calendar entries, storing pictures, communicating VPAID events, accessing location data (e.g. from GPS)
  • query the host about the current location of the device (e.g. from GPS)
  • receive notifications from the host about events such as an ad container state changes, size changes, visibility changes, audio volume changes etc.
  • communicate to the host that the ad should no longer be displayed (e.g. that it should be hidden or reloaded)
  • use the device’s native video player to play video material
  • and more

How MRAID works?

In order to better understand how MRAID works, the following components shall be distinguished:

Ad - Usually in a form of an HTML file (with CSS and JavaScript). The ad is served by the ad server and displayed in the application. The ad uses JavaScript to call MRAID methods.

mraid.js - A JavaScript file that provides a set of MRAID methods to the ad. An ad that wants to use MRAID must include a reference to mraid.js file. This file is supplied by the host when the ad is loaded into WebView.

WebView - A component that allows to display web pages and ads. On Android this will be Android System WebView.

SDK (Software Development Kit) - A part of a mobile application that implements MRAID. MRAID could be implemented by the application itself but a more practical approach is to enclose it into an SDK. An SDK is a component that can be integrated into multiple Android applications in order to equip them with MRAID functionalities. The SDK manages WebView instances and interacts with the rest of the mobile application.

The image below illustrates the hierarchy between the mentioned components:

How to implement MRAID on Android?

This part of the article will present how to get started with an Android application (written in Kotlin) that supports MRAID. The application will display a simple HTML ad that uses MRAID getVersion() method to get information about the MRAID version supported by the host.

The ad content looks as follows:

val html = """
   <!DOCTYPE html>
   <html style="background-color:blue;">
   <body>
   <script src="mraid.js"></script>
   <script>
      console.log('MRAID version is ' + mraid.getVersion())
   </script>
   </body>
   </html>
""".trimIndent()

The HTML displays a blue rectangle, declares that it requires mraid.js script, calls getVersion() method on the “mraid” object (which will be provided by the mraid.js script) and prints the result of that call.

A simple class will be used to represent the ad:

data class Ad(val html: String)

It a real-world scenario, the ad would be fetched from the server but here it will be declared locally:

val ad = Ad(html)

The ad will be displayed in the WebView:

val webView = findViewById<WebView>(R.id.webView)

When the ad’s HTML is loaded into WebView, it requests mraid.js file. This file will be provided by the MraidJsInjectingWebViewClient class:

private class MraidJsInjectingWebViewClient : WebViewClient() {
   override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest): WebResourceResponse? {
       val mraidJsFileName = "mraid.js"

       return if (request.url.toString().endsWith(mraidJsFileName)) {
           view?.context?.assets?.open(mraidJsFileName)?.let { stream ->
               WebResourceResponse("text/javascript", "UTF-8", stream)
           }
       } else null
   }
}

This class checks if the request is for the mraid.js file. If so, it provides a WebResourceResponse instance that contains an InputStream to the actual mraid.js file. That file is placed in the Android assets directory.

MraidJsInjectingWebViewClient instance is set in WebView:

webView.webViewClient = MraidJsInjectingWebViewClient()

The src/main/assets/mraid.js file’s content looks as follows:

var mraid = {
   getVersion: function() {
       return MraidController.getVersion();
   }
};

It defines a JavaScript object named “mraid” with a single getVersion() function that delegates the call to MraidController.getVersion() method.

MraidController is actually a Kotlin class:

class MraidController {
   @JavascriptInterface
   fun getVersion(): String = "3.0"
}

The getVersion() method returns the “3.0” String indicating that the host supports MRAID version 3.0. The @JavascriptInterface annotation exposes the getVersion() method to JavaScript. This allows the code in mraid.js file to call the Kotlin getVersion() method and get it’s result back to JavaScript.

In order to create this JavaScript-Kotlin bridge, an instance of MraidController class needs to be registered in WebView:

webView.addJavascriptInterface(MraidController(), "MraidController")

The second parameter passed to addJavascriptInterface() method is the name used to expose the MraidController instance to JavaScript (this name should be used when referencing MraidController methods from JavaScript).

The complete method that loads the ad into WebView looks as follows:

fun loadAd(webView: WebView, ad: Ad) {
   // Enable JavaScript execution in WebView
   webView.settings.javaScriptEnabled = true

   // Set custom WebViewClient that injects actual mraid.js into ad HTML
   webView.webViewClient = MraidJsInjectingWebViewClient()

   // Allow JavaScript code to call Kotlin methods of MraidController class
   webView.addJavascriptInterface(MraidController(), "MraidController")

   // Load the ad's HTML content into WebView
   webView.loadDataWithBaseURL("http://www.example.com/", ad.html, "text/html", "UTF-8", null)
}

The method needs be called with WebView and previously defined Ad as its arguments:

loadAd(webView, ad)

As a result, a blue rectangle ad should be displayed in WebView, and the following log should appear in LogCat:

I/chromium: [INFO:CONSOLE(6)] "MRAID version is 3.0", source: http://www.example.com/ (6)

Conclusion

This article offered a basic overview of what MRAID is and how it works. Obviously, there is a lot more to take into account when developing a real-world ad SDK with MRAID support. However, the presented code samples should provide a good base to build upon.

Previous Post Next Post