Tuesday, February 19, 2013

Creating Ads Manger for Android - Part 3 - Implementing AdMob



previous parts



 In Part 2 we finished our SBCAdManager class. Now we have system that will choose the right ad network for us as well as check whether the network is alive (sending ads) and change to another one if the network is dead. But so far we did not implement any ad network. As was said in previous parts we will step by step implement AdMob, Madvertise and Leadbolt. The system we are developing in this series is working in our real games Deadly Abyss 2 and Mahjong Tris.

 This time we will implement first of the ad networks - AdMob. (for clarity, I am using terms ad network and ad system interchangeably)


SBCAdSystem interface

 To provide common set of methods to control each of the implemented ad systems we will introduce interface class SBCAdSystem. In each of the ad systems in our ad engine we will implement the methods. Remember Part 1 and picture with all the files in com.sbcgames.sbcads package. The interface is in SBCAdSystem.java file:

package com.sbcgames.sbcads;

import android.view.KeyEvent;

public interface SBCAdSystem
{
 public void start();
 public void stop();
 public void destroy();
 public void setEventListener(SBCAdEventListener aListener);
 public boolean keyDown(final int aKeyCode, final KeyEvent aEvent);
}


Adding AdMob SDK

 Go to  Google Developers site to get the latest version of SDK. Or you may have it already as a part of downloaded SDK in "extras" directory (mine path is: D:\Android\android-sdk\extras\google\admob_ads_sdk\). To incorporate it into your project follow steps 1-3 at Google Developers (do not forget to choose "Android" in the top of the page or you will see iOS related how-to).


Adjusting manifest

 Every Ad network needs some permissions enabled. AdMob is not as hungry as other so internet access and network state reading is enough. Put the following lines into your manifest file:

    <!-- AdMob SDK requires Internet permission -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

 You also need to define AdMob activity inside your application tag:

        <!-- AdMobActivity definition -->
        <activity
            android:name="com.google.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />


Adjusting constants

 Next we will adjust our file with constants (file SBCAdsConstatns.java) . I am again referring to Part 1 where the file is listed. Bellow is only the line related to AdMob implementation. Replace the text of the constant with the ID you get from AdMob site after you register your app - click Manage Settings and you should see something like this:

 // AdMob
 public static final String ADMOB_AD_UNIT_ID = "your admob unit id here";


AdMobSystem.java

 Now you are ready to  real implementation. Start with imports and variables:

package com.sbcgames.sbcads;

import com.google.ads.*;
import com.google.ads.AdRequest.ErrorCode;
import com.sbcgames.sbcengine.SBCEngine;

import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;

public class AdMobSystem implements SBCAdSystem, AdListener
{
 private final String SYSTEM_NAME = "ADMOB ";
 private SBCAdEventListener mListener = null;
 private AdView mAdView;
 private ViewGroup mLayout;

 The class implements SBCAdSystem interface as well as AdListener interface. The AdListener interface is part of AdMob package and its implementation will work as callback for various events like when the ad is received or when the request for ad failed. Our interface is here to unify the different ad systems and to provide some common set of methods to start, stop and so on the system.

 The constructor looks like this:

 // ------------------------------------------------------------------------
 public AdMobSystem(SBCEngine aSBCEngine, ViewGroup aLayout)
 {
  mLayout = aLayout;
  
  // new view
  mAdView = new AdView(aSBCEngine, AdSize.BANNER, SBCAdsConstants.ADMOB_AD_UNIT_ID);
  mAdView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  
  // set the AdListener.
  mAdView.setAdListener(this);

  // Add the AdView to the view hierarchy. The view will have no size until the ad is loaded.
  aLayout.addView(mAdView);
 }
 
 We store the reference to aLayout which is "adsholder" element in our main.xml layout file. This file we created in first part. Next we create new ad view - this comes from AdMob SDK. We add listener to it - it is the AdListener interface implementation and finally we add this new view into prepared "adsholder" in layout.

 Now the object is created but we have to ask for ad. This is done in start method:

 //------------------------------------------------------------------------
 // SBCAdSystem
 //------------------------------------------------------------------------
 @Override
 public void start()
 {
     mAdView.setVisibility(View.VISIBLE);

     // Create an ad request. Check logcat output for the hashed device ID to
     // get test ads on a physical device.
     AdRequest adRequest = new AdRequest();
     adRequest.addTestDevice(AdRequest.TEST_EMULATOR);
     //adRequest.addTestDevice("YOUR-DEVICE-ID");

     // Start loading the ad in the background.
     mAdView.loadAd(adRequest);
 }

 We first set view to be visible. Then we create request for AdMob ad. In following lines we can add test devices. I highly recommend this as this will deliver test ads into your device so clicking on them will not violate ad company policy. You can add the emulator as well as real devices you are testing your apps on.
 Finally we launch our request. You will be notified if it is or is not successful through AdListener interface implementation.


SBCAdSystem implementation

 The following 5 methods are implementation of SBCAdSystem interface.

 As we want to change from one ad network to another, we need a way how to stop and destroy the ad view:

 //------------------------------------------------------------------------
 @Override
 public void stop()
 {
  if (mAdView != null)
  {
   mAdView.stopLoading();
   mAdView.setVisibility(View.GONE);
  }
 }

 //------------------------------------------------------------------------
 @Override
 public void destroy()
 {
  if (mAdView != null)
   mAdView.destroy();
  mLayout.removeAllViews();
 }

 These two methods are the ones called from SBCAdManager from stopAndDestroyAdSystem() method. It will disable displaying the view and cancel pending requests for ads. And in destroy() method it will destroy the ad view and remove it from "adsholder", so it is empty again and ready to hold any other ad view.

 Last two methods from SBCAdSystem Interface are setEventListener() and keyDown(). The later has no implementation for AdMob, so we just say that AdMob did not consumed the sent key. The first one sets listener for events of this system. The listener is SBCAdManager class itself - it will listen for events from each ad system and based on it it will terminate network, change to another and so on:

 //------------------------------------------------------------------------
 @Override
 public void setEventListener(SBCAdEventListener aListener)
 {
  mListener = aListener;
 }
 
 //------------------------------------------------------------------------
 @Override
 public boolean keyDown(final int aKeyCode, final KeyEvent aEvent)
 {
  return false;
 }


AdListener implementation

 The implementation of Adlistener, the interface that comes with AdMob SDK is easy. In most of the methods only some debug print is implemented. Events which are reported is ad request failure and success. It is reported to listener, which is SBCAdManger. When loading of ad fails it can then stop and destroy this ad network and start another.

 //------------------------------------------------------------------------
 // AdListener
 //------------------------------------------------------------------------
 @Override
 public void onDismissScreen(Ad aAd)
 {
  Log.d("AdsSystem", SYSTEM_NAME + "onDismissScreen");
 }

 //------------------------------------------------------------------------
 @Override
 public void onFailedToReceiveAd(Ad aAd, ErrorCode aErrorCode)
 {
  String message = SYSTEM_NAME + "onFailedToReceiveAd (" + aErrorCode + ")";
  Log.d("AdsSystem", message);
  
  mListener.onFailed(this);
 }

 //------------------------------------------------------------------------
 @Override
 public void onLeaveApplication(Ad aAd)
 {
  Log.d("AdsSystem", SYSTEM_NAME + "onLeaveApplication");
 }
 
 //------------------------------------------------------------------------
 @Override
 public void onPresentScreen(Ad aAd)
 {
  Log.d("AdsSystem", SYSTEM_NAME + "onPresentScreen");
 }

 //------------------------------------------------------------------------
 @Override
 public void onReceiveAd(Ad aAd)
 {
  Log.d("AdsSystem", SYSTEM_NAME + "onReceiveAd");
  mListener.onReceived(this);
 }
}


Conclusion

 For now we have completed ad manager and also first ad network it manages. Next time I will write how to implement Madvertise or Leadbolt network.