## 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.

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)
{
}
else
{
}

for (int i = 0; i < mSystemStatus.length; i++)
}


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()
{

// prevent repeated stopping
if (mStatus == eState.STOPPED)
{
return;
}

{
}

mStatus = eState.STOPPED;
}

// ------------------------------------------------------------------------
{
{
}
}


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()
{

// prevent repeated starting
if (mStatus == eState.RUNNING)
{
return;
}

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.

The setAdSystem() method is the place where several things happen:
• first it is checked if the user is online,
• 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())
{
return;
}

if (newSystem == -1)
{
return;
}

switch (newSystem)
{
break;

break;

break;
}

}


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++)
{

if (status.isFailed() &&
{
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;
}


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
// ------------------------------------------------------------------------
{
}

// ------------------------------------------------------------------------
{
}

// ------------------------------------------------------------------------
{
{
{
// mark this system as failing
}
}
}


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()
{

mHandler.postDelayed((new Runnable()
{
@Override
public void run()
{
{
}

}
}), 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;
}