CHAPTER FIFTEEN: In App Advertising

Chapter opener image: © Fon_nongkran/Shutterstock

Introduction

An important issue when building an app is how to monetize it. With so many apps out there, most people will first try a free app whenever possible. The Android SDK provides developers with the ability to include advertising inside their apps and leverage Google’s advertising resources to upload ads at runtime.

15.1 The View, Stopwatch App, Version 0

We want to build a stopwatch app that enables users to start the clock, stop it, reset it, restart it, etc. In Version 0, we only build the GUI, reserving a space for an ad banner at the bottom. FIGURE 15.1 shows the version 3 of the app running inside the emulator. The screen is divided into three parts:

  • ▸ At the top, we have the clock.

  • ▸ In the middle, we have a start/stop toggle button and a reset button.

  • ▸ At the bottom, we have the ad banner.

FIGURE 15.1 The Stopwatch app, Version 3

For the two round buttons, we use three drawables, shown in EXAMPLES 15.1, 15.2, and 15.3. We place them in the drawable directory. For the start/stop button, we will toggle the background of the button between start_button.xml and stop_button.xml. The start button has a green circle outline and the stop button has a red circle outline (line 6 of Examples 15.1 and 15.2). The reset button has a gray circle outline (line 6 of Example 15.3).

EXAMPLE 15.1 The start_button.xml file, Stopwatch app, Version 0

EXAMPLE 15.2 The stop_button.xml file, Stopwatch app, Version 0

EXAMPLE 15.3 The reset_button.xml file, Stopwatch app, Version 0

To display the stopwatch, we use a Chronometer. The Chronometer class inherits from TextView and encapsulates the functionality of a running clock. We want to style the Chronometer so we code the textViewStyle style at lines 11–15 in the styles.xml file, shown in EXAMPLE 15.4.

EXAMPLE 15.4 The styles.xml file, Stopwatch app, Version 0

EXAMPLE 15.5 shows the activity_main.xml file, organizing the GUI. A vertical (line 10) LinearLayout (line 2) organizes the screen into three parts:

  • ▸ A Chronometer (lines 13–18).

  • ▸ A horizontal (line 21) LinearLayout (lines 20–59) contains the start/stop and reset buttons.

  • ▸ Another LinearLayout (lines 61–67), a placeholder for the ad banner (we later change this LinearLayout to a fragment as recommended by Google).

EXAMPLE 15.5 The activity_main.xml file, Stopwatch app, Version 0

We assign 4/9 (weight 4 – line 14) of the screen to the Chronometer element, 4/9 to the buttons (weight 4 – line 22), and 1/9 (weight 1 – line 63) to the LinearLayout at the bottom. We give an id to the Chronometer at line 17 because we need to access it from the MainActivity class. We style it at line 18.

The horizontal LinearLayout in the middle of the screen contains two LinearLayouts (lines 27–41 and 43–57), each containing a button (lines 33–40 and 49–56). Each button has a diameter of size 150 pixels (lines 35–36 and 51–52) and a text size of 36. Although it is generally not good practice to hard code dimension values, we do so here to keep the example simple. Furthermore, these dimensions are reasonably small and are expected to work on any device. At lines 39 and 55, we set the background of each button to its corresponding drawable resource. Clicking on the Start/Stop button will trigger a call to the startStop method (line 40) and clicking on the Reset button will trigger a call to the reset method (line 56).

In this version, we color the bottom LinearLayout in light gray (line 66) so that we can visualize where the ad banner will go.

We add do-nothing startStop and reset methods to the MainActivity class (EXAMPLE 15.6) so that the app does not crash when the user clicks on either button.

FIGURE 15.2 shows a preview of the Stopwatch, Version 0, in the environment.

EXAMPLE 15.6 The MainActivity class, Stopwatch app, Version 0

FIGURE 15.2 Preview of the Stopwatch app, Version 0

15.2 The Controller: Running the Stopwatch App, Version 1

In Version 1, we will code the startStop and reset methods to give the app its functionality. In order to do this, we use the functionality of the Chronometer class, which represents the Model for this app: the start, stop, and setBase methods of the Chronometer class, shown in TABLE 15.1, enable us to start, stop, and reset the Chronometer.

The parameter of setBase, base, is typically set using the elapsedRealtime method of the SystemClock class. Its API is:

public static long elapsedRealtime( )

The elapsedRealTime method returns, in milliseconds, the amount of time since the last boot, including sleep time.

TABLE 15.1 Selected methods from the Chronometer class

Method Description
void start( ) Start counting ( or restart counting ).
void stop( ) Stop counting.
void setBase( long base ) Set the time of reference for the count.

EXAMPLE 15.7 shows the updated MainActivity class. Since the Start/Stop button toggles between two states, we keep track of that state with a boolean instance variable, started (line 12). Since we need access to the Chronometer in both methods, we add an instance variable for it, chrono (line 11). Inside the onCreate method, we instantiate it at line 18 using the findViewbyId method.

EXAMPLE 15.7 The MainActivity class, Stopwatch app, Version 1

The startStop method is coded at lines 21–34. If the Chronometer has already started (line 23), then the Start/Stop button is in its “started” state and we do the following:

  • ▸ Stop the Chronometer: we do this by calling stop with chrono at line 24.

  • ▸ Turn started to false (line 25) to specify that the button is now in a “stopped” state.

  • ▸ Change the text of the button to START (line 26).

  • ▸ Switch the background of the button to the drawable defined in start_button.xml (line 27).

Otherwise (line 28), the Chronometer has not started yet or was stopped, the button is in its “start” state and we do the following:

  • ▸ Start the Chronometer: we do this by calling start with chrono at line 29.

  • ▸ Turn started to true (line 30) to specify that the button is now in a “started” state.

  • ▸ Change the text of the button to STOP (line 31).

  • ▸ Switch the background of the button to the drawable defined in stop_button.xml (line 32).

The reset method (lines 36–39) resets chrono to 00:00 by calling the setBase method, passing the current time in milliseconds. Thus, when we call reset at time t, 00:00 is considered to be time t.

FIGURE 15.3 The Stopwatch app, Version 1

FIGURE 15.3 shows the Stopwatch, Version 1, running inside the emulator. The clock is running and the Start/Stop button has a red circle outline and says STOP.

15.3 Improving the Stopwatch App, Version 2

There is one issue with Version 1: if we stop the clock and restart it later, it does not restart where we stopped it. In fact, when we stop the Chronometer, it keeps running in the background. In Version 2, we fix that problem so that when we stop the Chronometer at time t, it restarts at time t.

To implement this, when we start or restart the Chronometer, we need to subtract the time elapsed since we stopped the Chronometer from the value returned by the elapsedRealtime method. Rather than doing this inside the MainActivity class, the Controller, we create a utility class, ClockUtility, shown in EXAMPLE 15.8. The Model for this app is now comprised of the Chronometer and ClockUtility classes. Furthermore, the functionality of the ClockUtility class is reusable in other apps.

The ClockUtility contains one static method, milliseconds: it converts a String that is formatted like a String displayed inside a Chronometer to its equivalent number of milliseconds. The format of the String clock (line 10) is expected to be hh:mm:ss or mm:ss where hh represents the number of hours (between 00 and 23), mm the number of minutes (between 00 and 59), and ss the number of seconds (between 00 and 59). In order to convert the String clock to a number of milliseconds, we use the parseInt method of the Integer class, which throws a NumberFormatException. Although it is not mandatory because NumberFormatException is unchecked, we prefer to use try and catch blocks (lines 15–26).

EXAMPLE 15.8 The ClockUtility class, Stopwatch app, Version 2

We convert clock to an array at line 12. If there are three elements in that array (line 16), the number of milliseconds is equal to hh * 60 * 60 * 1000 + mm * 60 * 1000 + ss * 1000 (lines 17–19). If there are two elements in that array (line 20), the number of milliseconds is equal to mm * 60 * 1000 + ss * 1000 (lines 21–22). If clock does not have the proper formatting, the method returns 0.

EXAMPLE 15.9 shows the updated MainActivity class. Inside the startStop method, if we restart the Chronometer (lines 29–33), we first reset it to where it had previously stopped at line 29 by calling the resetChrono method. Inside resetChrono (lines 42–46), we convert the current value of chrono to a number of milliseconds at lines 43–44. At line 45, we reset its base (i.e., its starting value) to its value when it stopped. TABLE 15.2 shows possible values returned by the elapsedRealtime and milliseconds methods when the user clicks on START, then STOP when chrono shows 10:00, then START again.

EXAMPLE 15.9 The MainActivity class, Stopwatch app, Version 2

TABLE 15.2 Values returned by elapsedRealtime and milliseconds assuming a START, STOP, START sequence

Action Chrono Time Value Returned by elapsedRealtime Value Returned by milliseconds
Start 00:00 t1 695064 0
Stop 00:10 t2 705777 10000
Start 00:10 t3 859134 10000

Now, when we run the app, we can stop the Chronometer and it will restart where it was stopped. For example, if the Chronometer says 00:15 when we stop it and we wait 10 seconds before clicking on the Start/Stop button, the Chronometer will restart at 00:15, not 00:25.

15.4 Placing the Ad, Stopwatch App, Version 3

In Version 3, we place an ad at the bottom of the screen. The com.google.android.gms.ads package provides a set of classes to display an ad and manage the ad. TABLE 15.3 shows some of these classes.

TABLE 15.3 Selected classes from the com.google.android.gms.ads package

Class Description
AdView A subclass of View to display an ad banner.
AdSize Encapsulates the size of a banner ad.
AdRequest Encapsulates a set of marketing characteristics such as location, birthday, keywords, etc., so that the ad can target demographics related to the app.

However, the com.google.android.gms.ads package is not part of the standard Android SDK, but it is part of Google Play services. Thus, in order to use it, we edit the build.gradle file as shown in EXAMPLE 15.10. Since we edited the build.gradle file, we need to sync the project.

EXAMPLE 15.10 The edited build.gradle file

We edit the activity_main.xml file and give an id to the last LinearLayout, where we place the ad, as shown at line 60 in EXAMPLE 15.11. Since we do not fully control the size of the ad that will be served, we want the width of the screen to be maximal. Thus, we delete lines 7 and 8 of Example 15.5 so that we do not have any left and right padding for the overall LinearLayout.

EXAMPLE 15.11 The end of the activity_main.xml file

The AdSize class encapsulates the size of a banner ad. It provides constants to match various industry standard sizes, as well as constants to cause the width and height to be relative to the device’s width and height. TABLE 15.4 shows some of these constants. We can use the FULL_WIDTH and AUTO_HEIGHT constants to create an AdSize object using an AdSize constructor, whereas we can use the other constants, such as SMART_BANNER, to specify a premade AdSize object.

The AdView class includes methods to create and manage a banner ad. Its direct superclass is ViewGroup, itself a subclass of View. Thus, AdView inherits from View. TABLE 15.5 shows some methods of the AdView class.

We must set the size and ad unit id of an AdView before we can load an ad into the AdView. Otherwise, an (unchecked) IllegalStateException will be thrown when we try to load the ad. In order to obtain an ad unit id from Google, we must be a registered Android developer. Among other things, the developer uses the ad unit id to generate ad revenues. The ad unit id is a String that we can obtain from AdMob, the platform that Google uses for managing ads, at the following URL:

TABLE 15.4 Selected constants of the AdSize class

Constant Data Type Description
AUTO_HEIGHT int Causes the height of the ad to scale based on the height of the device.
FULL_WIDTH int Causes the width of the ad to match the width of the device.
BANNER AdSize Mobile Marketing Association ad size of 320 × 50 dip.
SMART_BANNER AdSize Dynamically sized to full width and auto height.

TABLE 15.5 Selected methods of the AdView class

Method Description
public AdView( Context context ) Constructs an AdView.
public void setAdSize( AdSize adSize ) Sets the size of the banner ad. The argument can be one of the constants of the AdSize class.
public void setAdUnitId( String adUnitId ) Sets the ad unit id.
public void loadAd( AdRequest request ) Loads the ad on a background thread.
https://support.google.com/admob/v2/answer/3052638

AdMob ad unit ids have the following format:

ca-app-pub-XXXXXXXXXXXXXXXX/NNNNNNNNNN.

For developers who are not registered and want to test an app containing an AdView, Google provides a test ad unit id. We include it in the strings.xml file, shown in EXAMPLE 15.12 (lines 3–4). We actually do not use that String in Version 3, but we do use it in Versions 4 and 5.

EXAMPLE 15.12 The strings.xml file, Stopwatch app, Version 3

The following shows a code sequence creating an AdView, setting its size and setting its ad unit id, assuming we are inside an Activity class:

// Create a banner ad; assume this is an Activity reference
AdView adView = new AdView( this );
// Set ad size
adView.setAdSize( AdSize.SMART_BANNER );
// Set the ad unit id; use the default String from Google
String adUnitId = "ca-app-pub-3940256099942544/6300978111";
adView.setAdUnitId( adUnitId );

TABLE 15.6 Selected methods of the AdRequest.Builder class

Method Description
public AdRequest.Builder( ) Default constructor.
public AdRequest.Builder addKeyword( String keyword ) Adds a keyword for targeting purposes and can be called several times to add several keywords.
public AdRequest.Builder setGender( int gender ) Sets the user’s gender for targeting purposes.
public AdRequest.Builder setBirthday( Date birthday ) Sets the user’s birthday for targeting purposes.
public AdRequest.Builder setLocation( Location location ) Sets the user’s location for targeting purposes.
public AdRequest.Builder addTestDevice( String deviceId ) Sets up a device to receive test ads rather than live ads. Use the constant DEVICE_ID_EMULATOR from the AdRequest class to use the emulator.
public AdRequest build( ) Constructs and returns an AdRequest with the attributes specified by this AdRequest.Builder.

Once we have created an AdView, set its size and ad unit id, we need to create an ad request and load it into the AdView. The AdRequest class encapsulates the concept of an ad request. It includes a static inner class, Builder, that we can use to set the characteristics of an AdRequest. TABLE 15.6 shows some methods of the AdRequest.Builder class. The addKeyword allows us to add keywords, one per method call, that relate to the app, so that the ad can be better targeted at the typical app user. The setGender method allows us to target the ad at women, men, or both. The AdRequest class provides three int constants, GENDER_FEMALE, GENDER_MALE, and GENDER_UNKNOWN, which we can use as arguments of that method. We can use the setLocation method to target the ad based on a location. The app can access the GPS, retrieve the location of the user dynamically, and include it in the ad request so that Google services can use the location to better choose and target the ad. All these methods return the AdRequest.Builder reference that called them so that method calls can be chained. Once all the characteristics of the ad request are set, we can use the build method to create an AdRequest object.

The following shows a code sequence creating an AdRequest, and loading it onto an AdView:

FIGURE 15.4 Logcat output showing the device id

// Create the AdRequest
AdRequest adRequest = adRequestBuilder.build( );
// load the ad
adView.loadAd( adRequest );

If we want to use the emulator to test our app, we add this line before calling build to create the AdRequest:

adRequestBuilder.addTestDevice( AdRequest.DEVICE_ID_EMULATOR );

If we are a registered developer and we have obtained a valid ad unit id from Google, we can add this line before calling build to create the AdRequest for testing purposes. In the final version of the app, before submitting our app to Google Play, we should either delete that line or comment it out.

We can obtain the device id, a 32-digit hexadecimal string, for a device we use to test our app. We can obtain it by looking at the Logcat output when running the app on a connected device. For the author’s device, here is the Logcat output, also shown in FIGURE 15.4 (if you cannot find it in Logcat, screen the messages using the Ads tag as shown):

Use AdRequest.Builder.addTestDevice( "DE4?????????????????7A" ) to
get test ads on this device.

Thus, for the author’s device, we can include the following code to test the app on the tablet (for security and privacy reasons, the device id is partially hidden on Figure 15.4 and has been filled with ? characters below).

String deviceId = "DE4?????????????????7A"
adRequestBuilder.addTestDevice( deviceId );

EXAMPLE 15.13 The MainActivity class, Stopwatch app, Version 3

EXAMPLE 15.13 shows the updated MainActivity class, which includes creating an AdView, then an AdRequest, and loading the ad. The only edits are at lines 25–48 of the onCreate method. At lines 25–30, we create an AdView and set its size using SMART_BANNER and unit ad id using the default Google supplied ad unit id. At lines 32–41, we create and define an AdRequest. The ads served will target users interested in fitness and workout (lines 36—37). If we run the ad on the emulator, we ask for test ads, not live ads, to be sent (lines 38–39). We call build with the AdRequest.Builder reference adRequestBuilder at line 41 to create an AdRequest. At lines 43–45, we retrieve the LinearLayout whose id is ad_view and place the AdView in it. At lines 47–48, we load an ad conforming to adRequest inside the AdView.

There are three things to add to the AndroidManifest.xml file, shown in EXAMPLE 15.14. A uses-permission element to access the Internet (lines 5–6), a required meta-data element in order to use Google services (lines 15–17), and another activity element as shown at lines 29–32. Note that lines 30 and 31 should be in a single line in the AndroidManifest.xml file.

Figure 15.1, at the beginning of this chapter, shows the Stopwatch app, Version 3, running, including the banner ad at the bottom of the screen. If we are a registered developer and are using our own app unit id, we should not click on the live ad for testing purposes: it is against Google policy to do so. If we want to test the functionality of the banner ad, then we should use test ads, which we can get as follows:

  • ▸ Use the Google provided test ad unit id, or

  • ▸ Request test ads by using AdRequest.Builder.addTestDevice.

EXAMPLE 15.14 The AndroidManifest.xml file, Stopwatch app, Version 3

In both cases, we can run on the emulator or a device.

15.5 Placing the Ad in a Fragment, Stopwatch App, Version 4

Google recommends using a fragment in which to place the AdView. A benefit is that a fragment’s XML layout file is reusable in other apps. In Version 4, we place the AdView inside a fragment instead of a LinearLayout. Going from Version 3 to 4 involves the following steps:

  • ▸ Create an XML layout file for the fragment.

  • ▸ Change the last LinearLayout in the activity_main.xml file to a fragment.

  • ▸ Code the fragment class.

  • ▸ Update the MainActivity class.

EXAMPLE 15.15 shows the XML layout file for our fragment. We place the AdView element (lines 7–15) inside a RelativeLayout element (line 2). We give the AdView an id at line 8 so we can retrieve it inside the fragment class using the findViewById method. We specify the size and the ad unit id of the AdView at lines 13–14. At lines 11–12, we center the AdView horizontally and vertically within the RelativeLayout.

EXAMPLE 15.15 The fragment_ad.xml file, Stopwatch app, Version 4

EXAMPLE 15.16 shows the updated activity_main.xml file: we have replaced the last LinearLayout element with a fragment element (lines 59–64). We give it an id at line 60 and specify that it is an instance of the AdFragment class at line 61. Although we are not using its id in this app, the app will crash at runtime if we do not give a fragment either an id or a tag.

EXAMPLE 15.16 The activity_main.xml file, Stopwatch app, Version 4

EXAMPLE 15.17 shows our fragment class, which we name AdFragment. Inside the onCreateView method, we inflate the fragment_ad.xml file at line 15. Inside the onActivityCreated method, we retrieve the AdView specified in the fragment using its id (lines 21–22), we build an AdRequest (lines 23–31), and load it into the AdView (line 32–33).

EXAMPLE 15.17 The AdFragment class, Stopwatch app, Version 4

Since all banner ad–related code is in the AdFragment class, the MainActivity class is the same as the one in Version 2.

15.6 Managing the Life Cycle of the AdView, Stopwatch App, Version 5

The AdView class includes life-cycle methods, shown in TABLE 15.7, so that we can avoid unnecessary processing when the app goes to the background or is exited. Inside the fragment class, the onPause, onResume, and onDestroy life-cycle methods are automatically called as the parent’s activity goes into the background, the foreground, or is exited. Thus, we can call the AdView life-cycle methods from the fragment’s life-cycle methods.

EXAMPLE 15.18 shows the updated AdFragment class of our app, Version 5. All the other classes and files remain identical. Because we need to access the AdView from onPause (lines 38–42), onResume (lines 44–48), and onDestroy (lines 50–54), we make the AdView an instance variable (line 12) so that we can have a direct reference to it. Inside the three methods, we pause, resume, or destroy the AdView and call the super method. Note that inside onPause and onDestroy, we first pause or destroy the AdView before calling the super method: we want to pause the processing of the AdView or destroy the AdView inside the fragment before pausing or destroying the fragment itself. Inside onResume, we call the super method before calling resume with the instance variable adView: we want to resume the processing of the fragment before resuming the processing of the AdView, which is inside the fragment.

TABLE 15.7 The life-cycle methods of the AdView class

Method Description
public void pause( ) Pauses any extra processing associated with this AdView.
public void resume( ) Resumes processing associated with this AdView following a call to pause.
public void destroy( ) Destroys this AdView. 1package com.jblearning.stopwatchv5;

EXAMPLE 15.18 The AdFragment class, Stopwatch app, Version 5

Note that the AdFragment is not reusable as is because the gender and the keywords of this ad request are specific to this app. We could make the ad request builder an instance variable and provide methods inside AdFragment to set these parameters. This is left as an exercise.

Chapter Summary

  • The Chronometer class encapsulates a stopwatch.

  • elapsedRealtime, a static method of the SystemClock class, returns, in milliseconds, the amount of time since the last boot, including sleep time.

  • The com.google.android.gms.ads package provides a set of classes to display an ad and manage the ad.

  • The com.google.android.gms.ads package is part of Google Play services. In order to use it, we need to edit the build.gradle file accordingly.

  • The AdView class, which inherits from View, encapsulates a View that can display an ad banner.

  • The AdSize class encapsulates the size of a banner ad. It includes constants for various industry standard banner sizes.

  • The AdRequest.Builder class provides methods to define data, such as gender, location, and keywords, that enable an ad to target a certain type of demographic.

  • The build method of the AdRequest.Builder class returns an AdRequest reference.

  • We can use the following ad unit id for testing purposes: ca-app-pub-3940256099942544/6300978111

  • We must set the size and ad unit id of an AdView before the AdView calls the loadAd method to load an ad.

  • We can use a fragment for the banner ad, per Google’s recommendations.

  • Including a Google ad requires three additions to the AndroidManifest.xml file:

    • The INTERNET permission is required since the Internet is used in any app that displays a Google ad.

    • A meta-data element showing use of Google play services is also required.

    • An additional activity element for AdActivity is required.

Exercises, Problems, and Projects

Multiple-Choice Exercises

  1. The com.google.android.gms.ads package is part of Google Play services

    • True

    • False

  2. What class is not in the com.google.android.gms.ads package?

    • AdView

    • AdBuilder

    • AdSize

    • AdRequest

  3. The Builder class is an inner static class of which class?

    • AdView

    • AdRequest

    • AdSize

    • AdListener

  4. What method can we use to be sure that we only receive test ads and not live ads during testing?

    • addTest

    • addDevice

    • addTestDevice

    • addEmulator

  5. If we are not an Android developer and therefore cannot obtain an ad unit id from Google, we cannot test an app that includes banner ads.

    • True

    • False: we could use a default ad unit id provided by Google

  6. What method is not one of the methods that can specify the target demographics of an ad request?

    • setLocation

    • setBirthday

    • setGender

    • setKeyword

  7. What Exception is thrown by the loadAd method when the size or the ad unit id of the AdView has not been set?

    • IOException

    • IllegalStateException

    • LoadException

    • AdViewException

  8. What element is not one that we need to include in the AndroidManifest.xml file for an app that uses banner ads?

    • activity

    • uses-permission

    • meta-data

    • uses-storage

Fill in the Code

  1. Inside an Activity class, create an AdView and set its size so that it meets the IAB leaderboard ad size (you need to look at the AdSize class for that).

  2. Inside an Activity class, create an AdView and set its ad unit id to the default String provided by Google for testing purposes.

  3. Create a simple AdRequest so that we use test ads and not live ads.

  4. Create an AdRequest for men, using the two keywords game and video.

  5. Create an AdRequest for women, using a birthday of 1/1/2000.

  6. Create an AdRequest, considering that we will test the app in the emulator, and we only want test ads, not live ads.

  7. Assuming the AdView myAdView has been created, its size and ad unit id have been set, and the AdRequest myRequest has been built, load the ad into myAdView.

  8. Inside the AndroidManifest.xml, code the permission-related element for an app that includes banner ads.

  9. Inside the AndroidManifest.xml, code the extra activity element for an app that includes banner ads.

  10. Inside the AndroidManifest.xml, code the metadata-related element for an app that includes banner ads.

Write an App

  1. Make a simple flashlight app with a banner ad at the bottom. The flashlight is a yellow View taking the whole screen except the banner ad.

  2. Make a flashlight app with a banner ad at the top. The flashlight is a yellow View taking the whole screen except the banner ad and a SeekBar. The yellow View is dimmable, which you should implement with the SeekBar. Include a Model.

  3. Make an app of your choice (it should have some functionality) with a banner ad whose display is triggered by an event, for example the user clicking on a button.

  4. Make an app of your choice (it should have some functionality) with a banner ad that shows 50% of the time the user runs the app.

  5. Make an app of your choice (it should have some functionality) with a banner ad. The app should include some form of user input (either an EditText, or some list to pick from). You need to use the user input as a keyword for the ad request.

  6. Modify the Stopwatch app, Version 5, making the AdFragment class fully reusable (i.e., it should not set specific gender and keywords). Limit the customization of the ad to gender and keywords.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.212.27