Using AdMob in a MonoDroid Application

While MonoDroid makes it possible to write Android applications using .NET, what happens if you want to make use of existing third party Java libraries in your app? In this post I’ll talk about what your options are, and provide an example of how to serve ads from AdMob in your MonoDroid application using the standard AdMob Java library.

Talking To Java

As it exists right now, in order to use Java libraries in your MonoDroid application, you either need to access them via actual Java code or through JNI in C#. The team has said that somewhere down the line they will release support for wrapping arbitrary Java libraries in .NET, but that won’t make it into MonoDroid v1.0. It’s worth noting, however, that once that feature is released, doing that will be much nicer than what I’m going to describe here, but this should hopefully get you going in the meantime.

In this example I’m going to show you a pattern I’ve found works well to keep things somewhat clean, using both Java source and JNI calls.

Setting Up AdMob

First we need to set up AdMob in our application. To do so, include the JAR file in the project, and set its Build Action (in the Properties window) to AndroidJavaSource. You can use this build action for JAR files as well as Java source files that you want to include in your application.

Next, open up the project properties screen and go to the Android Manifest tab. We’ll want to set the package name (you’ll see why in a bit), and also specify that we require the Internet permission. It should end up looking like this:

Manifest properties

Save that, and then open the generated AndroidManifest.xml file in the project’s Properties folder. We’ll need to add some details to the application element for AdMob to work:

<application>
  <meta-data android:value="YOUR_ID_GOES_HERE" android:name="ADMOB_PUBLISHER_ID" />
  <activity
    android:name="com.admob.android.ads.AdMobActivity"
	android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
	android:configChanges="orientation|keyboard|keyboardHidden" />
  <receiver
    android:name="com.admob.android.ads.analytics.InstallReceiver"
    android:exported="true">
    <intent-filter>
      <action android:name="com.android.vending.INSTALL_REFERRER" />
    </intent-filter>
  </receiver>
</application>

Note that you’ll want to replace YOUR_ID_GOES_HERE with your actual publisher ID from AdMob. You can leave everything else alone in this file, since it was generated by the properties screen from before.

Letting C# Talk To Java

As I mentioned earlier, MonoDroid allows for you to talk directly to Java using JNI and the Android.Runtime.JNIEnv class. JNI code gets very tough to read and debug really quickly, so I generally try to keep that layer as simple as possible when I can. To do that, we will define a helper class in Java that can handle the real AdMob interaction, and exposes simple methods that we can easily hook into from C#.

Here is a basic AdMob helper class:


import android.view.View;
import com.admob.android.ads.AdManager;
import com.admob.android.ads.AdView;

public class AdMobHelper
{
  private AdMobHelper() { }

  public static void registerEmulatorAsTestDevice()
  {
    AdManager.setTestDevices(new String[] { AdManager.TEST_EMULATOR });
  }

  public static void requestFreshAd(View view)
  {
    ((AdView)view).requestFreshAd();
  }
}

Even though in this particular case the method bodies are very simple, they are much more readable than they would be in JNI. Also, it’s easy to imagine more complicated methods in a more complete implementation, and that’s where this approach will really pay off. In this class we expose two static methods. The first registers the emulator as a test device, which tells AdMob that we’re running in test mode and it should always return an ad for testing. The second method takes in a view as a parameter, assuming it is an AdView, and tells it to refresh the ad being displayed. Also, you can see that the package specified at the top is the same as the one we specified in our project properties earlier.

Now we have an easy extension point for the C# side that doesn’t really need to know anything about AdMob. We’ll define a static class in C# that mirrors the methods we exposed from Java, calling them via JNI:

public static class AdMobHelper
{
  private static IntPtr _helperClass = JNIEnv.FindClass("samples/admobtest/AdMobHelper");

  public static void RegisterEmulatorAsTestDevice()
  {
    IntPtr methodId = JNIEnv.GetStaticMethodID(_helperClass, "registerEmulatorAsTestDevice", "()V");
    JNIEnv.CallStaticVoidMethod(_helperClass, methodId);
  }

  public static void RequestFreshAd(View view)
  {
    IntPtr methodId = JNIEnv.GetStaticMethodID(_helperClass, "requestFreshAd", "(Landroid/view/View;)V");
    JNIEnv.CallStaticVoidMethod(_helperClass, methodId, new JValue(view));
  }
}

I won’t really go into details on how JNI works, but you can see how things would start getting messy if we tried to do everything through JNI. There’s plenty of documentation online if you want to dig through the JNI details and get crazy with it. Basically all we’re doing here is getting a reference to the Java class, then searching that for the method by name and method signature, and then calling it with the arguments it needs.

The Application

With the framework out of the way, now we can actually wire up an activity that displays an ad. First we’ll need a layout. In Main.axml, let’s define a simple layout that shows an ad, and also has a button for refreshing the ad:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <com.admob.android.ads.AdView
    android:id="@+id/Ad"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
  <Button
    android:id="@+id/RefreshAd"
    android:text="Refresh ad"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</LinearLayout>

Notice that the AdView is coming from the JAR file we included earlier. Now the activity:

[Activity(Label = "AdMobTest", MainLauncher = true)]
public class MainActivity : Activity
{
  private View _adView;

  protected override void OnCreate(Bundle bundle)
  {
    base.OnCreate(bundle);

    SetContentView(Resource.Layout.Main);

    AdMobHelper.RegisterEmulatorAsTestDevice();

    _adView = FindViewById(Resource.Id.Ad);

    FindViewById<Button>(Resource.Id.RefreshAd).Click += delegate
    {
      AdMobHelper.RequestFreshAd(_adView);
    };
  }
}

Once the activity is loaded it registers the emulator as a test device, and then tells it to refresh the ad whenever the button gets clicked. If you run the app, you should see something like this:

AdMob screenshot

And just like that, you’re serving AdMob ads in your MonoDroid application using the normal Java library! This approach won’t work for everything, but I’ve found it keeps things simple for cases where you have the ability to cleanly separate the library from the application code. If there was a requirement for the C# classes to inherit from types in the library, for example, you wouldn’t be able to do it like this. Hopefully this helps give you an idea of how Java/.NET interoperability can be achieved in your MonoDroid applications. What other libraries are you plugging into your MonoDroid apps?

All source code is available in my GitHub account.

comments powered by Disqus
Navigation