Question

Help me, stackoverflow, you are my only hope. I want to create an Android Live Wallpaper that displays Ads in the preference activities of the wallpaper. I almost got this working by following this example:

Android Admob advert in PreferenceActivity

This works fine, but this example uses OnCreateView() to load the ads. I noticed that OnCreateView gets called multiple times for the custom ad preference. This even happens while you are scrolling in the preferences list, so the AdRequest is triggered again and again. This problem is also mentioned here:

AdView requests new add every time SeekBar is touched

So I moved the call for the AdRequest to onAttachedToHierarchy() and use a member variable to store the adView. I then use the stored adView to add this to the view in the OnCreateView()-Event This, however, results in a strange behavior: The ad reload has stopped, but the ad is only displayed "sometimes" on top of the list of preferences. For example, when I load the preferences, the ad is not being displayed. I scroll down, and up again, suddenly the ad is there. Down again, quick up again, ad has disappeared. Sloooow up: Ad appears again. Debugging shows that from some of the multiple calls of OnCreateView() some are "successful" and the ad gets displayed, and some are not. It seems that it requires a "successful" call to happen as last call of OnCreateView() so the ad stays on the screen. What do I need to do to make sure the adView is always displayed properly? Is there maybe a different approach to display ads in the preference screen?

My code is as follows:

Preference to display the ad:

public class AdPreference extends Preference {

public AdPreference(Context context, AttributeSet attrs, int defStyle) {super    (context, attrs, defStyle);}
public AdPreference(Context context, AttributeSet attrs) {super(context, attrs);}
public AdPreference(Context context) {super(context);}

/** The view to show the ad. */
private AdView adView;

/* Your ad unit id. Replace with your actual ad unit id. */
private static final String AD_UNIT_ID = "XXXXXXXXXXXXXXX";

@Override 
public void onAttachedToHierarchy(PreferenceManager preferenceManager){
    super.onAttachedToHierarchy(preferenceManager);

    Activity activity = (Activity)getContext();

    // Create an adView.

    adView = new AdView(activity);
    adView.setAdSize(AdSize.BANNER);
    adView.setAdUnitId(AD_UNIT_ID);

    // Create an ad request. Check logcat output for the hashed device ID to
    // get test ads on a physical device.
    AdRequest adRequest = new AdRequest.Builder()
        .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
        .build();

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

@Override
protected View onCreateView(ViewGroup parent) {
    // this will create the linear layout defined in ads_layout.xml
    View view = super.onCreateView(parent);

    if (adView.getParent()!=null)
    {
        ((LinearLayout)adView.getParent()).removeAllViews();
    }
    ((LinearLayout)view).addView(adView);

    return view;    
}

}

Snippet of the preference XML:

<?xml version="1.0" encoding="UTF-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:examplens="http://example.com">
<example.AdPreference     android:layout="@layout/ad_preference" />
<Preference android:title="@string/preference1" />
    .
    .
    .
<PreferenceCategory>

</PreferenceCategory>

Layout XML for the ad preference:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/linearLayoutForAd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>

Please let me know in case the problem description is unclear and you need more code / info! Thanks in advance!

Was it helpful?

Solution 2

I got it working by making a minor change: The trick was to cache the entire "LinearLayout"-View instead only caching the AdView. The code for the AdPreference was changed to:

public class AdPreference extends Preference {

public AdPreference(Context context, AttributeSet attrs, int defStyle) {super    (context, attrs, defStyle);}
public AdPreference(Context context, AttributeSet attrs) {super(context, attrs);}
public AdPreference(Context context) {super(context);}

/** The view to show the ad. */
private static AdView adView;
private static View myCustomView;

/* Your ad unit id. Replace with your actual ad unit id. */
private static final String AD_UNIT_ID = "XXXXXXXXXXXXXXX";

@Override
protected View onCreateView(ViewGroup parent) {
    // this will create the linear layout defined in ads_layout.xml

    if (myCustomView==null)
    {

        View view = super.onCreateView(parent);

        Activity activity = (Activity)getContext();

        // Create an adView.

        adView = new AdView(activity);
        adView.setAdSize(AdSize.BANNER);
        adView.setAdUnitId(AD_UNIT_ID);
        //adView.

        ((LinearLayout)view).addView(adView);

        myCustomView = view;

        // Create an ad request. Check logcat output for the hashed device ID to
        // get test ads on a physical device.
        AdRequest adRequest = new AdRequest.Builder()
            .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
            .build();

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

    }
    return myCustomView;    
}

}

This makes it work for me as intended, no permanent ad reloading and the ad remains "stable" in the list of preferences.

OTHER TIPS

Don't show ads in preferences. This is really poor UX. And the PreferenceActvity mechanism is not well setup to handle it.

How long are your users going spend in your preferences screen? Put the ads in the main body of your app instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top