Complete example of admob mediation customevent (with any network)

2,858 views
Skip to first unread message

mradlmaier

unread,
Aug 6, 2012, 8:50:43 PM8/6/12
to google-adm...@googlegroups.com
Can anybody point me to a complete example/tutorial of how to integrate unsupported networks into admob mediation.

I read the developer docs, but they only show the code concerning admob, not how to implement the minimum 3 methods.
Any network would do.

Eric Leichtenschlag

unread,
Aug 7, 2012, 3:01:50 PM8/7/12
to google-adm...@googlegroups.com
Check out this custom events Google Developers Academy class for a more in depth example of how to use custom events.  The example shows how to use AdMob through a custom event, but the concepts should be similar enough that you can replace it with a different one.

Cheers,
Eric


--
 
 
  


Michael Radlmaier

unread,
Aug 7, 2012, 5:01:12 PM8/7/12
to google-adm...@googlegroups.com
Eric,
I know this documentation, but this does not help me.
From my understanding: there are 2 methods of the AdListener interface which need to be called, depending success or failure.
onReceiveAd(Ad ad)
onFailedToReceiveAd(Ad ad, ErrorCode errorCode)
My problem is, that unsupported networks have their own implementation of Ad. For example, Greystripe's version of the Ad interface is GSAd. If you look at the documentation of Greystripe, you wil find that this interface does not implement the Ad interface, so I can not pass it into these callbacks.
There is a class GSMobileBannerAdView which implements the GSAd interface. So, I would need to subclass GSMobileBannerAdView , have my sub-class implement the Ad interface.
But GSMobileBannerAdView is final, so I can not subclass it. Bad luck!
Looks like there is no decent way to implement Greystripe as a custom network?

Actually I dont care, if I can use Greystripe or not. The main issue with Admob (and that's why I started using mediation) is, that Admob is very much centered around the american market, which leads to bad CTR/eCPM for european markets.

[Off topic]:
I love Android and Google is doing a great job, but Europe (surely the second most important market in the world: germans own an average of 1.15 handsts per head, americans only 0.9 per head) is always an after-thought for Google. 
For example, Google Play up to now doesn't accept any payment other then credit card, but credit cards are not very common in Europe, which means that, we devlopers sell very little through Google Play. That means, we rely on ads for income, here again, the same issue: Little good inventory in Admob :(


2012/8/7 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Eric Leichtenschlag

unread,
Aug 7, 2012, 5:18:02 PM8/7/12
to google-adm...@googlegroups.com
Hey Michael,

The example from the custom events class referenced above implements AdMob's AdListener because the custom event is implementing AdMob.  For Greystripe, your custom event would implement GSAdListener instead.  Then in onFetchedAd(), you would call this.bannerLIstener.onReceiveAd()  to forward the "received ad" event to the AdMob Mediation layer.  Similarly, you'd implement onFailedToFetchAd() and call this.bannerListener.onFailedToReceiveAd() to let AdMob know you didn't get an ad from GreyStripe.  You get the bannerListener object as a parameter inside requestBannerAd(), which you'll keep a reference in order to use later.

Keep in mind that the code for the custom event is completely separate from general AdMob implementation.  You'll still have to create an AdMob AdView in your main activity with a Mediation ID configured to use your custom event, and that main AdView can have it's own AdMob ad listener attached.  Perhaps the confusion from this example is that it's using AdMob Mediation to invoke a custom event that then requests an AdMob ad, vs. using AdMob directly.

Let me know if this helps,
Eric


--
 
 
  


Michael Radlmaier

unread,
Aug 7, 2012, 5:40:13 PM8/7/12
to google-adm...@googlegroups.com
I will try to figure that out.

But this actually means, I will have to write a custom event class for each unsupported network, or having the custom event class implement multiple interface, which would be very confusing?

2012/8/7 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Michael Radlmaier

unread,
Aug 7, 2012, 5:43:35 PM8/7/12
to google-adm...@googlegroups.com
What do think about this class http://stackoverflow.com/questions/11667285/custom-events-in-admob-mediattion-adding-unsupported-ad-networks as a blueprint?

2012/8/7 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Eric Leichtenschlag

unread,
Aug 7, 2012, 6:10:46 PM8/7/12
to google-adm...@googlegroups.com
Hey Michael,

The blueprint from that StackOverflow question works - it is essentially a combination of the two snippets from the custom events class I mentioned earlier.  That example still uses AdMob though, so again, remember to swap out AdListener interface with your ad network's ad listener interface, and forward the ad events to the CustomEventBannerListener accordingly.

If you want to write custom events for multiple unsupported networks, I would definitely recommend writing 1 class for each network (it's pretty much required).  Otherwise you'd have to do some unnecessary mediation logic in your requestBannerAd() method.

I'd recommend trying to write the Greystripe adapter using these examples.  I'd be happy to look over your code once you've got something to show.

Cheers,
Eric


--
 
 
  


Michael Radlmaier

unread,
Aug 8, 2012, 12:39:04 PM8/8/12
to google-adm...@googlegroups.com
Tx Eric,
Get back to you asap.

2012/8/8 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Michael Radlmaier

unread,
Aug 8, 2012, 3:15:22 PM8/8/12
to google-adm...@googlegroups.com
So, I create a class GreyStripeCustomEvent. This class implements GSAdListener. But it would have to implement Googles CustomEventBanner interface?
I dont see any corresponding interface in the Greystripe SDK?

There is another thing, that I dont understand:
If I am using Greystripes GSAdListener interface, how will Admob know that notification, and moving to the next network in the daisy chain of events will be done through the methods onFailedToFetchAd(GSAd arg0, GSAdErrorCode arg1) and onFetchedAd(GSAd arg0) ?

Maybe it is not important to understand, and I am not that experienced in Java, but I like to understand what is going on behind the scenes.

2012/8/7 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Eric Leichtenschlag

unread,
Aug 8, 2012, 4:32:25 PM8/8/12
to google-adm...@googlegroups.com
Hey Michael,

Yes, you'll still have to implement CustomEventBanner.

Once you set up your custom event network in the AdMob UI, Mediation will treat your custom event as another network when it orders the ad networks.  Let's say that mediation chooses your custom event network first.  Mediation will invoke requestBannerAd() from the CustomEventBanner interface on the fully qualified class that you provided when you configured the custom event (ex: com.michael.GreyStripeCustomEvent).  The requestBannerAd() method comes with AdMob's CustomEventBannerListener object (which you should keep a copy of), as well as your server parameter that you configured (probably a greystripe ID).  You'll implement this method and create a GreyStripe Banner view and load an ad into it.

You'll implement GreyStripes ad listener and in onFetchedAd(GSAd gsad), you'll invoke this.bannerListener.onReceiveAd(gsad).  The bannerListener is AdMob's CustomEventBannerListener that you stored in your class from the requestBannerAd method.  By invoking onReceiveAd, your telling the mediation framework "Hey, my custom event just received an ad, and here is the view for that ad.  Please display it for me."  The Mediation framework takes that view and adds it under the com.google.ads.AdView you specified in XML or in your main activity code (remember this declaration is completely separate from the custom event implentation).

If GreyStripe returns onFailedToFetchAd(), you should invoke this.bannerListener.onFailedToReceiveAd(), telling the mediation framework "Hey, my custom event didn't get an ad.  Please go on to the next network."  AdMob will timeout your custom event if you don't get an ad fast enough or you don't pass on the onFailedToReceiveAd() call.  It's good to pass on the fail call though, because the quicker mediation gets notified of a fail, the faster it can try the next network.

Cheers,
Eric


--
 
 
  

Michael Radlmaier

unread,
Aug 8, 2012, 5:01:29 PM8/8/12
to google-adm...@googlegroups.com
oic, Thank you very much for taking time to explain in detail.

2012/8/8 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Michael Radlmaier

unread,
Aug 9, 2012, 5:52:03 PM8/9/12
to google-adm...@googlegroups.com
Eric,

Here is my class:

public class GreyStripeCustomEvent implements CustomEventBanner, GSAdListener {

private CustomEventBannerListener bannerListener;
private GSMobileBannerAdView adView;
    private Activity activity;

    // interface CustomEventBanner
@Override
public void requestBannerAd(CustomEventBannerListener listener, 
Activity activity,
String label, 
String serverParameter, 
AdSize adSize, 
MediationAdRequest mediationAdRequest) {
// TODO Auto-generated method stub
// Keep the custom event listener for use later.
this.bannerListener = listener;
// find the right adsize
// in our case it is the standard banner
AdSize bestAdSize = AdSize.BANNER;

// Initialize an AdView with the bestAdSize and the publisher ID.
// The publisher ID is the server parameter that you gave when creating
// the custom event.
adView = new GSMobileBannerAdView(activity, serverParameter);
        adView.addListener(this);
        adView.refresh();
}
// interface GSAdListener
@Override
public void onAdClickthrough(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onAdDismissal(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onFailedToFetchAd(GSAd gsad, GSAdErrorCode error) {
// TODO Auto-generated method stub
this.bannerListener.onFailedToReceiveAd();

}

// interface GSAdListener
@Override
public void onFetchedAd(GSAd gsad) {
// TODO Auto-generated method stub
LinearLayout adContainer = (LinearLayout) activity.findViewById(R.id.ad_container);
adContainer.addView(adView);
this.bannerListener.onReceiveAd(gsad);

}
}

But this will not compile because in onFetchedAd(GSAd gsad), I can only pass a GSAd into this.bannerListener.onReceiveAd(), but onReiveAd only accepts Ad, and I cant cast GSAd to AD.

In onFailedToFetchAd(GSAd gsad, GSAdErrorCode error), eclipse doesn't complain if I call onFailedToReceiveAd() without parameters.

What I am missing here?

Best regards
Michael


2012/8/8 Michael Radlmaier <michael....@gmail.com>

mradlmaier

unread,
Aug 9, 2012, 5:56:13 PM8/9/12
to google-adm...@googlegroups.com
Note: 
AdSize bestAdSize = AdSize.BANNER;
in requestBannerAd is redundant.
Sorry.

Michael Radlmaier

unread,
Aug 10, 2012, 4:36:23 PM8/10/12
to google-adm...@googlegroups.com
Eric, 
I modified the class somewhat:

package com.radlmaier.heiligenkalender.rk;

import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.google.ads.AdSize;
import com.google.ads.AdView;
import com.google.ads.mediation.MediationAdRequest;
import com.google.ads.mediation.customevent.CustomEventBanner;
import com.google.ads.mediation.customevent.CustomEventBannerListener;
import com.greystripe.sdk.GSAd;
import com.greystripe.sdk.GSAdErrorCode;
import com.greystripe.sdk.GSAdListener;
import com.greystripe.sdk.GSMobileBannerAdView;

public class GreyStripeCustomEvent implements CustomEventBanner, GSAdListener {

private CustomEventBannerListener bannerListener;
private GSMobileBannerAdView adView;
    private Activity activity;
    private static final String TAG = "GreyStripeCustomEvent";

    // interface CustomEventBanner
@Override
public void requestBannerAd(CustomEventBannerListener listener, 
Activity activity,
String label, 
String serverParameter, 
AdSize adSize, 
MediationAdRequest mediationAdRequest) {
// TODO Auto-generated method stub
Log.d(TAG, "requestBannerAd()");
// Keep the custom event listener for use later.
this.bannerListener = listener;
// Initialize an AdView with the bestAdSize and the publisher ID.
// The publisher ID is the server parameter that you gave when creating
// the custom event.
adView = new GSMobileBannerAdView(activity, serverParameter);
        adView.addListener(this);
        adView.refresh();
}
// interface GSAdListener
@Override
public void onAdClickthrough(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onAdDismissal(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onFailedToFetchAd(GSAd gsad, GSAdErrorCode error) {
// TODO Auto-generated method stub
this.bannerListener.onFailedToReceiveAd();

}

// interface GSAdListener
@Override
public void onFetchedAd(GSAd gsad) {
// TODO Auto-generated method stub
Log.d(TAG, "onFetchedAd()");
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                // I am using the built-in ID android.R.id.content which refers to the content/root view of an activity 
View view = inflater.inflate( android.R.id.content, null );
LinearLayout adContainer = (LinearLayout) view.findViewById(R.id.ad_container);
adContainer.addView(adView);
                
                // this is a hack: I pass an ImageView, because onReceivedAd() expects a view and 
                // GDAd cant be cast to View
ImageView img = new ImageView(activity);
this.bannerListener.onReceivedAd(img);
}
}

This compiles, doesnt show any exception LogCat, but the ad is not shown :(

Can you please advice/review?


2012/8/9 mradlmaier <michael....@gmail.com>
--
 
 
 

Michael Radlmaier

unread,
Aug 10, 2012, 5:53:38 PM8/10/12
to google-adm...@googlegroups.com
Eric, 
I found my code keeps crashing in the onFetchedAd() method, when executing:

LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

so I replaced that with:

LayoutInflater inflater = LayoutInflater.from(activity);

But it still crashes with a NullPointerException.

The whole CustomEvent stuff works, but I dont know how to do the last thing: getting a reference to the Layout container of the banner, and adding the banner

Can you please advice? What I am missing here?

2012/8/10 Michael Radlmaier <michael....@gmail.com>

Michael Radlmaier

unread,
Aug 10, 2012, 6:59:28 PM8/10/12
to google-adm...@googlegroups.com
Eric,
This is what I am currently having:
public class GreyStripeCustomEvent implements CustomEventBanner, GSAdListener {

private CustomEventBannerListener bannerListener;
private GSMobileBannerAdView adView;
    private Activity activity;
    private static final String TAG = "GreyStripeCustomEvent";

    // interface CustomEventBanner
@Override
public void requestBannerAd(CustomEventBannerListener listener, 
Activity activity,
String label, 
String serverParameter, 
AdSize adSize, 
MediationAdRequest mediationAdRequest) {
// TODO Auto-generated method stub
Log.d(TAG, "requestBannerAd()");
//Toast.makeText(activity, "requestBannerAd()", Toast.LENGTH_LONG).show();
// Keep the custom event listener for use later.
this.bannerListener = listener;
this.activity = activity;
Log.d(TAG, "requestBannerAd() after this.activity = activity");
Log.d(TAG, "activity: " + activity.toString());
// Initialize an AdView with the bestAdSize and the publisher ID.
// The publisher ID is the server parameter that you gave when creating
// the custom event.
adView = new GSMobileBannerAdView(activity);
        adView.addListener(this);
        adView.refresh();
Log.d(TAG, "requestBannerAd() after adview.refresh()");
}
// interface GSAdListener
@Override
public void onAdClickthrough(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onAdDismissal(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onFailedToFetchAd(GSAd gsad, GSAdErrorCode error) {
// TODO Auto-generated method stub
this.bannerListener.onFailedToReceiveAd();

}

// interface GSAdListener
@Override
public void onFetchedAd(GSAd gsad) {
// TODO Auto-generated method stub
Log.d(TAG, "onFetchedAd()");
Log.d(TAG, "activity: " + activity.toString());
//Toast.makeText(activity, "onFetchedAd()", Toast.LENGTH_LONG).show();
//LayoutInflater inflater = LayoutInflater.from(activity);
//LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//View view = inflater.inflate( android.R.id.content, null );
//LinearLayout adContainer = (LinearLayout) view.findViewById(R.id.ad_container);

LinearLayout adContainer = (LinearLayout) activity.findViewById(R.id.ad_container);

Log.d(TAG, "onFetchedAd(): after findViewById");
Log.d(TAG, "adContainer: " + adContainer.toString());
adContainer.addView(adView);

Log.d(TAG, "onFetchedAd(): after addView");
ImageView img = new ImageView(activity);
this.bannerListener.onReceivedAd(img);

}
}

This executes without exceptions. But that result looks like in the attached screenshot. Note, that if I click anywhere outside of the banner (the black area), it will trigger a click, so obviously the functionality works, but my layout is messed up.

For comparison, I attached a screenshot of what it should look like.

Any idea why my layout gets skewed?
after-adview.add(adView).png
heiliger.png

Michael Radlmaier

unread,
Aug 10, 2012, 7:10:55 PM8/10/12
to google-adm...@googlegroups.com
Here is the layout xml:
Note that the layout is only skewed for the GreyStripeCustomEvent. The supported ad networks render like they should.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/layout_bg"
    android:id="@+id/root_layout" >
    
 <LinearLayout 
     android:id="@+id/ad_container"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"></LinearLayout>
 
        <LinearLayout
        android:layout_below="@id/ad_container"
        android:id="@+id/linearLayout1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <ImageButton
            android:id="@+id/button_previous_day"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/previous_saint_of_day" />

        <ImageButton
            android:id="@+id/button_previous_saint"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/previous_saint" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/text_view_date"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="@string/date"
                android:textAppearance="?android:attr/textAppearanceMedium" />

            <TextView
                android:id="@+id/text_view_saint_count"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:text="@string/saint_name"
                android:textAppearance="?android:attr/textAppearanceSmall" />
        </LinearLayout>

        <ImageButton
            android:id="@+id/button_next_saint"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/next_saint" />

        <ImageButton
            android:id="@+id/button_next_day"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/next_saint_of_day" />
    </LinearLayout>
    <TextView
        android:id="@+id/text_view_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="Medium Text"
        android:layout_below="@id/linearLayout1"
        android:textAppearance="?android:attr/textAppearanceMedium" />
    
    <WebView
        android:id="@+id/web_engine"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@id/text_view_name" /> 
        
     
        
    <com.socialize.ui.actionbar.ActionBarView
        android:id="@id/socializeActionBar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" />
        
</RelativeLayout>


2012/8/11 Michael Radlmaier <michael....@gmail.com>

Eric Leichtenschlag

unread,
Aug 13, 2012, 7:53:05 PM8/13/12
to google-adm...@googlegroups.com
Hey Michael,

Inside of onFetchedAd, you should only need to call this.bannerListener.onReceivedAd(adView).  Note that this adView is the GSMobileBannerAdView you defined in requestBannerAd. The onReceivedAd method accepts a view, and the AdMob SDK will show that view as a child of the com.google.ads.AdView that you define.  Since the AdMob SDK does this, you don't need to do adContainer.addView(adView) yourself.

Where is your com.google.ads.adView definition?  I don't see it in your XML.  Is it defined in your main activity's code?

The rest of the custom event looks good.  I would recommend adding this.bannerListener.onPresentScreen() and this.bannerListener.onDismissScreen() in onAdClickThrough() and onAdClickDismissal(), so that if you have a com.google.ads.AdListener in your main code, it will notify you of these events.

Cheers,
Eric


--
 
 
  


Michael Radlmaier

unread,
Aug 14, 2012, 12:39:56 AM8/14/12
to google-adm...@googlegroups.com
I got the unsuported networks working, with a dew different networks.
I will post a complete example with the implementations of the suggested methods later.

com.google.ads.adView? good point... have to look. Get back to you asap.

2012/8/14 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

mradlmaier

unread,
Aug 18, 2012, 6:35:39 PM8/18/12
to google-adm...@googlegroups.com
Eric,

There is one thing that bugs me. You may haver noticed the last 2 lines of onFetchedAd(GSAd):

ImageView img = new ImageView(activity);
this.bannerListener.onReceivedAd(img);

This is a hack needed because GSAd can't be cast to View.
While this works, I am not sure about what actually Admob is doing under the hood. Can I rely that this will work in future versions of the Admob SDK.

Note, that there are really a lot unsupported ad network SDKs whose ad type can't be cast to View. Actually, there are more SDKs suffering from that issue than SDKs adhereing to Admob's interface of AdListener.

What are the potential drawbacks of this hack?

Eric Leichtenschlag

unread,
Aug 20, 2012, 2:44:32 PM8/20/12
to google-adm...@googlegroups.com
Michael,

I think there is a misunderstanding where you really need to provide the ad view, but you think you have to pass the ad interface.  I'm sorry I didn't catch this last time - we may have been talking about different exmaples.  I will use the following example for reference:

public class GreyStripeCustomEvent implements CustomEventBanner, GSAdListener {
private CustomEventBannerListener bannerListener;
private GSMobileBannerAdView adView;
    private Activity activity;

    // interface CustomEventBanner
@Override
public void requestBannerAd(CustomEventBannerListener listener, 
Activity activity,
String label, 
String serverParameter, 
AdSize adSize, 
MediationAdRequest mediationAdRequest) {
// TODO Auto-generated method stub
// Keep the custom event listener for use later.
this.bannerListener = listener;
// find the right adsize
// in our case it is the standard banner
AdSize bestAdSize = AdSize.BANNER;

// Initialize an AdView with the bestAdSize and the publisher ID.
// The publisher ID is the server parameter that you gave when creating
// the custom event.
adView = new GSMobileBannerAdView(activity, serverParameter);
        adView.addListener(this);
        adView.refresh();
}

// interface GSAdListener
@Override
public void onFetchedAd(GSAd gsad) {
// TODO Auto-generated method stub
LinearLayout adContainer = (LinearLayout) activity.findViewById(R.id.ad_container);
adContainer.addView(adView);
this.bannerListener.onReceivedAd(gsad);
}
}

In this example, you are trying to pass the gsad interface, to onRecievedAd, but you really want to invoke this.bannerListener.onReceivedAd(adView), which is the adView from the requestBannerAd method that you kept a reference to.  The GreyStripe banner extends from View, so you don't have to create an ImageView wrapper.  All you need to do is this:

@Override
public void onFetchedAd(GSAd gsad) {
this.bannerListener.onReceivedAd(adView);
}

Hope this helps,
Eric



--
 
 
  


Michael Radlmaier

unread,
Aug 20, 2012, 5:13:29 PM8/20/12
to google-adm...@googlegroups.com
O.K.
Now I understand. As you said, I was trying to pass the GSAd interface type, which seemed logical to me, because it is the argument passed into onFetchedAd(). My mistake.

Tx, now I understand all details of implementing CustomEvent classes. Your help is very much appreeciated

2012/8/20 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Michael Radlmaier

unread,
Aug 20, 2012, 6:06:27 PM8/20/12
to google-adm...@googlegroups.com
Eric,
I removed the line:

                ImageView img = new ImageView(activity);
this.bannerListener.onReceivedAd(img);

and and modified to

this.bannerListener.onReceivedAd(adView); 

This compiles (as it should), but once the banner is loaded I am getting an IllegalStateException:

08-20 23:45:02.820: E/AndroidRuntime(12330): FATAL EXCEPTION: main
08-20 23:45:02.820: E/AndroidRuntime(12330): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.view.ViewGroup.addViewInner(ViewGroup.java:3337)
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.view.ViewGroup.addView(ViewGroup.java:3208)
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.view.ViewGroup.addView(ViewGroup.java:3165)
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.view.ViewGroup.addView(ViewGroup.java:3145)
08-20 23:45:02.820: E/AndroidRuntime(12330): at com.google.ads.internal.d.a(SourceFile:1015)
08-20 23:45:02.820: E/AndroidRuntime(12330): at com.google.ads.internal.d.a(SourceFile:674)
08-20 23:45:02.820: E/AndroidRuntime(12330): at com.google.ads.e$8.run(SourceFile:427)
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.os.Handler.handleCallback(Handler.java:605)
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.os.Handler.dispatchMessage(Handler.java:92)
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.os.Looper.loop(Looper.java:137)
08-20 23:45:02.820: E/AndroidRuntime(12330): at android.app.ActivityThread.main(ActivityThread.java:4424)
08-20 23:45:02.820: E/AndroidRuntime(12330): at java.lang.reflect.Method.invokeNative(Native Method)
08-20 23:45:02.820: E/AndroidRuntime(12330): at java.lang.reflect.Method.invoke(Method.java:511)
08-20 23:45:02.820: E/AndroidRuntime(12330): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-20 23:45:02.820: E/AndroidRuntime(12330): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-20 23:45:02.820: E/AndroidRuntime(12330): at dalvik.system.NativeStart.main(Native Method)

Seems like Admob is trying to add the view to adContainer a second time???
How can that be? How does the Admob SDK know to which view to add the adView? Nowhere in the code is specified which is the view in my layout, where the banner should appear???

2012/8/20 Michael Radlmaier <michael....@gmail.com>

Eric Leichtenschlag

unread,
Aug 20, 2012, 6:11:53 PM8/20/12
to google-adm...@googlegroups.com
Hey Michael,

Indeed, the SDK is trying to add the greystripe ad to the view hierarchy for you (or any view you provide to onReceivedAd).  The view is added as a subview to the com.google.ads.AdView you have in your hierarchy.  This AdView acts as the mediation container, and the SDK ads whatever view you pass into onReceivedAd to this container.

Cheers,
Eric


--
 
 
  


Michael Radlmaier

unread,
Aug 21, 2012, 12:44:06 AM8/21/12
to google-adm...@googlegroups.com
So, I dont have to add the adView manually to my  com.google.ads.AdView? 

Note, that I dont have the  com.google.ads.AdView in my layout but create it in requestBannerAd().

Now I do not get the exception, but if I omit to add the adView manually, no ad is shown, also I can see in the logcat, that I receive ads?

Doesn't work like that :(

2012/8/21 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Michael Radlmaier

unread,
Aug 21, 2012, 1:45:12 PM8/21/12
to google-adm...@googlegroups.com
Found the  correct solution:

This is the Greystripe CustomEvent class:

public class GreystripeCustomEvent implements CustomEventBanner, GSAdListener {

private CustomEventBannerListener bannerListener;
private GSMobileBannerAdView adView;
    private Activity activity;
    private static final String TAG = "GreystripeCustomEvent";

    // interface CustomEventBanner
@Override
public void requestBannerAd(CustomEventBannerListener listener, 
Activity activity,
String label, 
String serverParameter, 
AdSize adSize, 
MediationAdRequest mediationAdRequest) {
// TODO Auto-generated method stub
Log.d(TAG, "requestBannerAd()");
// Keep the custom event listener for use later.
this.bannerListener = listener;
this.activity = activity;
Log.d(TAG, "requestBannerAd() after this.activity = activity");
Log.d(TAG, "activity: " + activity.toString());
// Initialize an AdView with the publisher ID.
// The publisher ID is the server parameter that we when creating
// the custom event in the admob dashboard
adView = new GSMobileBannerAdView(activity, serverParameter);
        adView.addListener(this);
        adView.refresh();
Log.d(TAG, "requestBannerAd() after adview.refresh()");
}
// interface GSAdListener
@Override
public void onAdClickthrough(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onAdDismissal(GSAd arg0) {
// TODO Auto-generated method stub

}

// interface GSAdListener
@Override
public void onFailedToFetchAd(GSAd gsad, GSAdErrorCode error) {
// TODO Auto-generated method stub
this.bannerListener.onFailedToReceiveAd();

}

// interface GSAdListener
@Override
public void onFetchedAd(GSAd gsad) {
// TODO Auto-generated method stub
Log.d(TAG, "onFetchedAd()");
// we need to add LayoutParams, otherwise the ad skew the layou
Resources r = activity.getResources();
int pixWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 320, r.getDisplayMetrics());
int pixHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, r.getDisplayMetrics());
LinearLayout.LayoutParams params  = new LinearLayout.LayoutParams(pixWidth, pixHeight);
adView.setLayoutParams(params);
this.bannerListener.onReceivedAd(adView);

Log.d(TAG, "onFetchedAd(): after bannerListener.onReceivedAd(adView)");

}
}

This the layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/layout_bg"
    android:id="@+id/root_layout" >
    
 <LinearLayout 
     android:id="@+id/ad_container"
     android:orientation="vertical"
     android:layout_margin="0dp"

And this are the relevant lines in onCreate() of the activity:

adView = new AdView(this, AdSize.BANNER, MY_MEDIATION_ID);
// Lookup your LinearLayout assuming it's been given
// the attribute android:id="@+id/ad_container"
LinearLayout layout = (LinearLayout) findViewById(R.id.ad_container);
// Add the adView to it
layout.addView(adView);
layout.setVisibility(View.VISIBLE);
// Initiate a generic request to load it with an ad
adView.loadAd(new AdRequest());



2012/8/21 Michael Radlmaier <michael....@gmail.com>

Eric Leichtenschlag

unread,
Aug 21, 2012, 1:47:23 PM8/21/12
to google-adm...@googlegroups.com
Michael,

Let's pretend you didn't write any custom event code, but are just using mediation with already supported networks.  To use AdMob, you need to create a com.google.ads.AdView with your mediation id (say, in your main activity), and add it to your layout.  This is completely separate from your custom event code.

Now let's say your mediation ID calls a custom event network.  The AdMob SDK invokes the requestBannerAd() method of your custom event class, and you make the GreyStripe ad view. When you get the Greystripe adview, you invoke onRecievedAd(GSAdView), and the AdMob SDK adds it as a subview to the com.google.ads.AdView you created in your main activity.

Cheers,
Eric

--
 
 
  


Eric Leichtenschlag

unread,
Aug 21, 2012, 1:50:37 PM8/21/12
to google-adm...@googlegroups.com
Michael,

It looks like you just figured it out on your own!  I'm guessing this works - I would recommend not storing the activity in your custom events class though.  You don't need it after requestBannerAd(), and you don't want to run into any potential memory leak issues because you're holding a reference to the activity.

Cheers,
Eric


--
 
 
 



--

Eric Leichtenschlag | Developer Programs Engineer | eleich...@google.com | 650-776-5591


Michael Radlmaier

unread,
Aug 21, 2012, 3:03:12 PM8/21/12
to google-adm...@googlegroups.com
Right, I dont need the activity reference anymore.
Tx for the hint.

Cheers,
Michael

2012/8/21 Eric Leichtenschlag <eleich...@google.com>

--
 
 
 

Michael Radlmaier

unread,
Aug 21, 2012, 3:31:45 PM8/21/12
to google-adm...@googlegroups.com
Incorrect, in the case of Greystripe (and some other networks), I need the activity to obtain the Resources:

Resources r = activity.getResources();
int pixWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 320, r.getDisplayMetrics());
int pixHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, r.getDisplayMetrics());
LinearLayout.LayoutParams params  = new LinearLayout.LayoutParams(pixWidth, pixHeight);
adView.setLayoutParams(params);

If I dont set LayoutParams, adding the adView will skew the layout.
I have 3 more other CustomEvent classes for other SDKs, and only one will not skew the layout once the adview is added. No idea why this happens.

I will be more than happy, if you can suggest a better way.

For now, I simply set
      
      this.activity = null;

after the LayoutParams have been calculated.

Cheers,
Michael

2012/8/21 Michael Radlmaier <michael....@gmail.com>

Eric Leichtenschlag

unread,
Aug 21, 2012, 4:56:47 PM8/21/12
to google-adm...@googlegroups.com
Hey Michael,

Good point, I missed that.  Instead of holding the activity, you could optionally create the LinearLayout.LayoutParams and set the adView's layout params inside of requestBannerAd().

I'm pretty sure this happens because the com.google.ads.AdView is set to wrap content, but the default for most ad networks is fill parent.  So when the greystripe ad view gets added as a subview to the com.google.ads.AdView, the com.google.ads.AdView tries to fill the entire screen.

Another workaround is to proactively specify 320dp width and 50dp height on your AdView.  Then it should fix the problem without having to created a wrapper around each ad network's view.  Be careful with this route though - some networks have 320x53 ads, while others have 320x48.  You don't want to cut off some height off the 53, and you may not like the extra space if a 320x48 is shown.   If this applies to you, specifying the layout params for each network is probably your best bet.

Cheers,
Eric




2012/8/21 Michael Radlmaier <michael....@gmail.com>
Michael


2012/8/21 Eric Leichtenschlag <eleich...@google.com>

--
 
 
 


--
 
 
 


Michael Radlmaier

unread,
Aug 21, 2012, 5:07:15 PM8/21/12
to google-adm...@googlegroups.com
Yes, I could create the params in requestBannerAd(). But it doesn't matter a lot, or?

Exactly, AdView fills the entire screen.

And yes, I prefer to handle this on a per CustomEvent basis. So, that I can specifically have these code only if it is really necessary for a particular network.

Tx for your great support, without your help, I wouldnt have manage to stitch all together correctly.

The only really tricky CustomEvent class left now, is for Madvertise.com. But I firmly believe, the problems are caused by their unusual approach.

Cheers,
Michael

2012/8/21 Eric Leichtenschlag <eleich...@google.com>
--
 
 
 

Reply all
Reply to author
Forward
0 new messages