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.



Wednesday, February 13, 2013

Creating Ads Manger for Android - Part 2 - Finishing SBCAdManager




previous parts

 Last time we started building of our ads manager, the class that will handle for you woking with ad networks. So far we set our layout, defined some settings and started the SBCAdManager class. Today we will finish it and in next parts we will implement three ad providers - AdMob, Madvertise and Leadbolt.

Construction od SBCAdManager


 Ok, let's go for SBCAdManager constructor:

 public SBCAdManager(SBCEngine aSBCEngine, ViewGroup aLayout)
 {
  mSBCEngine = aSBCEngine;
  mLayout = aLayout;
  
  float dp = aSBCEngine.getApplicationContext().getResources().getDisplayMetrics().density;
  DisplayMetrics dm = new DisplayMetrics(); 
  aSBCEngine.getWindowManager().getDefaultDisplay().getMetrics(dm); 
  int screenWidth = dm.widthPixels; 
  
  //Log.d("AdsSystem", "density:" + dp + " screenwidth:" + screenWidth);
  
  if (screenWidth > 800 && dp <= 1.0f)
  {
   mSystems = SBCAdsConstants.systemsBig;
   mProbability = SBCAdsConstants.probabilityBig;
   mSystemsNames = SBCAdsConstants.systemsNamesBig;
  }
  else
  {
   mSystems = SBCAdsConstants.systemsSmall;
   mProbability = SBCAdsConstants.probabilitySmall;
   mSystemsNames = SBCAdsConstants.systemsNamesSmall;
  }

  mSystemStatus = new SBCAdSystemStatus[mSystems.length];
  
  for (int i = 0; i < mSystemStatus.length; i++)
   mSystemStatus[i] = new SBCAdSystemStatus();
 }

 The initialization part is little bit longer than it necessary has to be. As I last time mentioned we had to choose two "configurations" for our Deadly Abyss 2 game - one for small screens and one for large screens. In constructor you can see we are measuring the size of the display and choosing the appropriate config for it. I left the code here as you can do the same or even more select different sizes of ads from your provider based on screen resolution.
 After that I am creating array of statuses for all ad systems. Statuses were aso explained last time. Its purpouse is to keep information on which ad network failed in sending ad and how long time ago it was. These information are then used when selecting ad network and the time is used to automatically revive failed ad network after some time.

Starting and stopping the Ad Manager


 Now we created the object. Before I show the start() method here is stop() method and also stopAndDestroyAdSystem() method.

 // ------------------------------------------------------------------------
 public void stop()
 {
  Log.d("AdsSystem", "stopping AdsSystem");
  
  // prevent repeated stopping
  if (mStatus == eState.STOPPED)
  {
   Log.d("AdsSystem", "AdsSystem already stopped");
   return;
  }
  
  if (mSBCAdSystem != null)
  {
   stopAndDestroyAdSystem();
  }
  
  mStatus = eState.STOPPED;
 }
 
 // ------------------------------------------------------------------------
 public void stopAndDestroyAdSystem()
 {
  if (mSBCAdSystem != null)
  {
   mSBCAdSystem.stop();
   mSBCAdSystem.destroy();
   mSBCAdSystem = null;
  }
 }

 It first checks whether the manager itself is in running state and if yes it then checks if some ad system is running. If yas again, the runnin ad system is destroyed and then also the SBCAdManaget is put into STOPPED state.

 Start() method looks like this:

 public void start()
 {
  Log.d("AdsSystem", "starting AdsSystem");
  
  // prevent repeated starting
  if (mStatus == eState.RUNNING)
  {
   Log.d("AdsSystem", "AdsSystem already started");
   return;
  }
  
  if (mSBCAdSystem == null)
   setAdSystem(); 

  if (mSBCAdSystem != null)
   mSBCAdSystem.start();
  
  mStatus = eState.RUNNING;
 }

 First it checks whether the manager was already started and if not new system is set. As the setAdSystem may set no ad network (for example if the user is offline) the result  is checked and if not null then the selected ad system is started.


Selecting the ad system


 The setAdSystem() method is the place where several things happen:
  • first it is checked if the user is online,
  • then reviveAdSystems is called to revive dead ad system - the ones that failed to deliver ads in past time,
  • new system is chosen,
  • based on result new ad system object is created and SBCAdManager is set as object that is listening for its events (events like - user clicked ad, ad request failed, ...)
 private void setAdSystem()
 {
  if (!isOnline())
  {
   Log.d("AdsSystem", "system is off-line");
   return;
  }
 
  Log.d("AdsSystem", "selecting new ad system");
  
  reviveAdSystems();

  int newSystem = chooseAdSystem();
  if (newSystem == -1)
  {
   mSBCAdSystem = null;
   mLastSBCAdSystem = -1;
   return;
  }
  
  switch (newSystem)
  {
  case SBCAdsConstants.ADMOB:
   mSBCAdSystem = new AdMobSystem(mSBCEngine, mLayout);
   Log.d("AdsSystem", "AdMob selected");
   break;
  
  case SBCAdsConstants.MADVERTISE:
   mSBCAdSystem = new MadvertiseSystem(mSBCEngine, mLayout);
   Log.d("AdsSystem", "Madvertise selected");
   break;
  
  case SBCAdsConstants.LEADBOLT:
   mSBCAdSystem = new LeadboltSystem(mSBCEngine, mLayout);
   Log.d("AdsSystem", "Leadbolt selected");
   break;
  }
  
  mLastSBCAdSystem = newSystem;
  if (mSBCAdSystem != null)
   mSBCAdSystem.setEventListener(this);
 }

 The isOnLine() method is short helper returning true or false:

 private boolean isOnline()
 {
  ConnectivityManager cm = (ConnectivityManager) 
    mSBCEngine.getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo nInfo = cm.getActiveNetworkInfo();
  return (nInfo != null && nInfo.isAvailable() && nInfo.isConnected());
 }

 More interesting are other two methods - reviveAdSystem() and chooseAdSystem(). The first one has listing like this:

 private void reviveAdSystems()
 {
  int systemsCount = mSystems.length;
  
  // revive all systems that failed before some time
  long currentTime = System.currentTimeMillis();
  for (int i = 0; i < systemsCount; i++)
  {
   SBCAdSystemStatus status = mSystemStatus[i];
   
   if (status.isFailed() && 
     currentTime - status.getFailedTime() > SBCAdsConstants.REVIVE_TIME)
   {
    Log.d("AdsSystem", "Reviving system " + mSystemsNames[i]);
    status.setFailedTime(0);
    status.setFailed(false);
   }
  }
 }

 It simply goes through statuses of all systems and if the system is marked as failed then it cheks time when the ad system fialed. If it is in past long time ago enough the system is marked as live again and so ready for selection.

 chooseAdSystem() method first gets random number from 0 to 99. It then loops through your configuration take from constant and set in constructor. Based on this it finds ad network. If the network is dead - it's status isFailed() is true. then it loops through othe ad networks starting with next one. If the loop completes and you return to first selected network it means that all networks are dead. In such  case null is returned. Otherwise index of selected live ad system is returned.

 private int chooseAdSystem()
 {
  int result = -1;
  int systemsCount = mSystems.length;
  
  int prob = mRnd.nextInt(100);
  int cumul = 0;
  for (int i = 0; i < systemsCount; i++)
  {
   cumul += mProbability[i];

   // possible system - check for last failures 
   if (prob < cumul)
   {
    // chosen system failed in last 2 minutes - choose next 
    if (mSystemStatus[i].isFailed())
    {
     int idx = i + 1;
     while (idx != i)
     {
      if (idx >= systemsCount)
       idx = 0;
      
      if (!mSystemStatus[idx].isFailed())
      {
       result = mSystems[idx];
       break;
      }
      
      ++ idx;
     }
    }
    else
    {
     result = mSystems[i]; 
    }
    
    break;
   }
  }
  
  return result;
 }


Callbacks - SBCAdEventListener


 In the end of setAdSystem() method we set listener for events comming from ad network. As the listener we set SBCAdEventListener interface that is implemented by SBCAdSystem class. The interface methods are callbacks that are called when some event in ad system occures. The implementation of them is like this:

 // ------------------------------------------------------------------------
 // CALLBACKS 
 // ------------------------------------------------------------------------
 public void onClick(SBCAdSystem aSBCAdSystem)
 {
 }

 // ------------------------------------------------------------------------
 public void onReceived(SBCAdSystem aSBCAdSystem)
 {
 }

 // ------------------------------------------------------------------------
 public void onFailed(SBCAdSystem aSBCAdSystem)
 {
  if (aSBCAdSystem == mSBCAdSystem)
  {
   if (mLastSBCAdSystem != -1)
   {
    // mark this system as failing
    mSystemStatus[mLastSBCAdSystem].setFailed(true);
    mSystemStatus[mLastSBCAdSystem].setFailedTime(System.currentTimeMillis());
   }
   changeAdSystem();
  }
 }

 As you can see, currently I have only onFailed implemented. If the ad system says that it failed I just mark it as dead. I record the time of death and try to chnge the system with changeAdSystem() method which has this listing:

 private void changeAdSystem()
 {
  long delayTime = allAdSystemsFailed() ? SBCAdsConstants.NEXT_TRY_TIME : 0;
  
  Log.d("AdsSystem", "Change Ad System in " + delayTime + " millis");
  
  mHandler.postDelayed((new Runnable()
  {
   @Override
   public void run()
   {
    Log.d("AdsSystem", "Changing ad system");
    if (mSBCAdSystem != null)
    {
     stopAndDestroyAdSystem();
    }

    setAdSystem();
    if (mSBCAdSystem != null)
     mSBCAdSystem.start();
   }
  }), delayTime);
 }

 This is kind of thin ice for me as I am not too experienced Java/Android coder. So, any improvements or suggestions are welcome. What the mehod does is that it first calculates when the system should change - immediately or if all systems are dead than after time defined in constatnts (I use 2 minutes). Next the actual ad system changing method is scheduled. It deletes any previous ad system sets new and starts it.

 For completness here is also the allAdSystemsFailed() method. As the name says it just returns true  if all systems are dead.

 private boolean allAdSystemsFailed()
 {
  boolean result = true;
  int systemsCount = mSystems.length - 1;
  
  while (systemsCount >= 0 && result)
  {
   result = (result && mSystemStatus[systemsCount].isFailed());
   -- systemsCount;
  }
  
  return result;
 }


Conclusion


 Ok, now the SBCAdSystem is finished. But for now we have no ad networks implemented to choose from yet. Next time we will start with AdMob. During reading you probably imagined thousands of enhancements - like storing the network the user clicks on ads most often. Maintain some ad network preference list on your server and ask for it during construction instead of pure random selection. Enhance the selection taht it will take into account also some priorities you assign to ad networks and so on ... I will be happy to hear about your ideas or code enhancements in comments.


Tuesday, February 12, 2013

Creating Ads Manger for Android - Part 1 - First part of SBCAdManager




 This is first post on series of articles on how to implement your own simple Ad Manager to monetize your game or app. After lots of dreamless nights you finally finished your app and now you would be glad if it made some money for you. This is where ads come into play. There is plenty of advertising companies in the internet, but usually it is not good to rely only on one of them. If you choose only one you may encounter various unpleasant facts like: the chosen ads provider is focused only on small geographical locality or he has not enough ads for region where your player is located or for all regions at all and the fill rate is thus very low. These are the reasons why you should consider to build some system that will rotate the ads provides based on some rules to be sure that some ad is displayed every time.

 The Ad Manger that I will describe later in the first two parts is written in Java but through JNI you can start and stop it from your native app as well. The system may not be the best one in the world but it works for me and you can see it in our games Deadly Abyss 2 and Mahjong Tris in action. Beside this I have some ideas how to enhance it in future. In next parts I will also describe how I implemented ads from AdMob, Madvertise and Leadbolt.

 On the following picture you can see structure of final package that takes care of managing ads:


 First three classes are concrete implementations of general SBCAdSystem interface. SBCAdManager is the core class that is managing all the rest. It also implements SBCAdEventListener interface that gets notified on some events from particular ad systems. These events are information on whether the ad was loaded or whether the loading failed and so on. Based on these events the manager can change ad system to other. Last file, the SBCAdsConstants is file where we will store and set some parameters for the manager like percentage distribution of requests among available systems.


 Layout

  Our games are based on combination of NDK and Java using GLSurfaceView. Our layout file main.xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.sbcgames.sbcengine.SBCGLView
        android:id="@+id/sbcglview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/adsholder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:orientation="vertical" >
    </LinearLayout>

</FrameLayout>

 The first part is SBCGLView which is class derived from GLSurfaceView and second part is "adsholder" which is element that will hold the ads in case some is to be visible. If no ads are visible this element is invisible.


 Constants

 First here is listing of SBCAdsConstants.java. these constants will be referred by the SBCAdManager later. I will explain it when we encounter the usage first time:
package com.sbcgames.sbcads; 
 
public class SBCAdsConstants
{
 // Common
 public static final int ADMOB         = 0;
 public static final int MADVERTISE    = 1;
 public static final int LEADBOLT      = 2;

 // systems big
 public static final int systemsBig[]         = { MADVERTISE ,  ADMOB ,  LEADBOLT };
 public static final int probabilityBig[]     = {25     , 45          , 30        };
 public static final String systemsNamesBig[] = {"Madvertise", "Admob", "LeadBolt"};
 // systems small
 public static final int systemsSmall[]         = {LEADBOLT };
 public static final int probabilitySmall[]     = {100};
 public static final String systemsNamesSmall[] = {"LeadBolt"};
 
 // 2 minutes
 public static final long REVIVE_TIME = 1000 * 60 * 2;
 // 2 minutes if all ad systems fialed
 public static final long NEXT_TRY_TIME = 1000 * 60 * 2;
 
 // AdMob
 public static final String ADMOB_AD_UNIT_ID = "your admob unit id here";
 
 // Leadbolt
 public static final String LEADBOLT_UNIT_ID = "your leadbolt unit id here";
 public static final long LEADBOLT_REFRESH_RATE = 1000 * 90 * 1;
  
 // Madvertise
 // !!! change ID in manifest !!!
 // your madvertise unit id here
}


 EventListener

The SBCAdEventListener interface that the manager will implement is very simple:

package com.sbcgames.sbcads;

public interface SBCAdEventListener
{
 public void onClick(SBCAdSystem aSystem);
 public void onReceived(SBCAdSystem aSystem);
 public void onFailed(SBCAdSystem aSystem);
}
 So, our Ads Manager will get informed when ad is received, clicked or when request for ad failed for currently active ad system.


Ad Manager

 Now comes the most important part - the manager itself. This class is quite a long one so it will be divided into parts and described separately. It is so long that in this article we will only start with the implementation and will describe all the features in detail in the next article. The main idea behind the manager is:
  • check if player is online,
  • if not, do nothing; if yes choose randomly ad system with probability based on your settings in file with constants
  • ask for ad,
  • if ad is delivered from ad provider, continue with this provider until it fails. If it fails at first try, mark this provider as dead for time defined in constants (REVIVE_TIME) and try different ad provider
  • if all providers are dead do nothing until NEXT_TRY_TIME expires and then try again.
 Status of every ad system is kept in class SBCAdSystemStatus that is in the same file as the SBCAdManager. The class is very simple and it is more or less a bunch of getters / setters:

class SBCAdSystemStatus
{
 private boolean mFailed;
 private long mFailedTime;
 
 // ------------------------------------------------------------------------
 public SBCAdSystemStatus()
 {
  clear(); 
 }

 // ------------------------------------------------------------------------
 public void clear()
 {
  mFailed = false;
  mFailedTime = 0;
 }
 
 // ------------------------------------------------------------------------
 public boolean isFailed()
 {
  return mFailed;
 }

 // ------------------------------------------------------------------------
 public void setFailed(boolean aFailed)
 {
  mFailed = aFailed;
 }

 // ------------------------------------------------------------------------
 public long getFailedTime()
 {
  return mFailedTime;
 }

 // ------------------------------------------------------------------------
 public void setFailedTime(long aFailedTime)
 {
  mFailedTime = aFailedTime;
 }
}
 the real function of the class is to say in its field mFailed whether the system is live (sending ads) or dead (request for ad failed) and when it failed (filed mFailedTime).

 Now, really to the core class. It starts with some imports and definition of variables:

package com.sbcgames.sbcads;

import java.util.Random;

import com.sbcgames.sbcengine.SBCEngine;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.ViewGroup;

public class SBCAdManager implements SBCAdEventListener
{
 // references to app context and xml layout
 private enum eState {STOPPED, RUNNING};
 private eState mStatus = eState.STOPPED;
 private final ViewGroup mLayout;
 private SBCEngine mSBCEngine;
 private Handler mHandler = new Handler();
 private Random mRnd = new Random();
 // actual ads system
 private SBCAdSystem mSBCAdSystem;
 private int mLastSBCAdSystem = -1;
 private SBCAdSystemStatus mSystemStatus[] = null;
 // systems
 private int mSystems[] = null;
 private int mProbability[] = null;
 private String mSystemsNames[] = null;

 First, there is defined enum that simply says whether the SBCAdManager is running or stopped. The current state is stored in mStatus field. In ViewGroup the reference to our "adsholder" - element defined in main.xml layout - will be stored. SBCEngine is reference to my game engine. The class is derived from Activity class. But I have to use here SBCEngine class instead of Activity as Leadbolt implementation needs some communication with engine.
 Handler will be used to post some requests with delay later and mRnd is there to generate random numbers when choosing ad system.
 Currently used ad system is stored in mSBCAdSystem. ID of last chosen system is in mLastSBCAdSystem and mSystemStatus array will contain as many statuses as we have systems (3 in our case - AdMob, Madvertise, Leadblot)
 Last three variables will hold arrays defined in file with constants. Look at the listing of constants. there are two blocks commented as "system big", "system small". The variables will refer to the first or second. This is not necessary, but it is exact implementation as we had in Deadly Abyss 2. The game was port from bada OS where only paid version without ads existed. For standard 480x800 screens the ads from AdMob and Madvertise were to big so we could use only Leadbolt with smaller ads. For tablets with big screens we can use all of them. I will repeat here the block commented as "system big":

// systems big
public static final int systemsBig[]         = { MADVERTISE ,  ADMOB ,  LEADBOLT };
public static final int probabilityBig[]     = {25          , 45     , 30        };
public static final String systemsNamesBig[] = {"Madvertise", "Admob", "LeadBolt"};
  • the first array is list of systems used for this "configuration",
  • the second array sums up to 100. And the numbers are probability that the system will be randomly chosen,
  • last array is list of names of the systems in easy to read form
 So, this is the place where you can choose how much requests will be in average sent to each implemented ads provider.

Next part

 As rest of the manager contains still a lot of code it will be finished in the next part. As for now you should have your layout prepared, you should know how to create settings in your constants class to distribute requests later.