Download presentation
Presentation is loading. Please wait.
1
Chapter 15: In App Advertising
2
Learning Objectives Use Google Play Services
Include advertising in an app Manage the life cycle of an ad inside an app
3
Advertising A significant issue is how to monetize an app.
There are many free apps in Google Play. People are accustomed to free apps. We can have two apps: A $0.99 app with no ads A free app with ads
4
Stopwatch App We build a simple Stopwatch app and place an advertising banner at the bottom of the screen. We start with the Stopwatch. We will add the advertising banner in Version 3.
5
Version 0 There is no ad in Version 0.
We divide the screen into three parts: A Chronometer at the top Two Buttons (start/stop and reset) A place for the ad at the bottom
6
Drawables for the Buttons (1 of 4)
We create three drawable resources for the buttons (we only show two buttons at the time: start and reset or stop and reset). start_button.xml, stop_button.xml, and reset_button.xml. They are identical except for their outline color (green, start, gray).
7
Drawables for the Buttons (2 of 4)
The outline color in start_button.xml is green. <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android= " android:shape="oval"> <solid android:color="#FFFF" /> <stroke android:width="2dp" android:color="#F0F0" /> </shape>
8
Drawables for the Buttons (3 of 4)
stop_button.xml and reset_button.xml are identical to start_button.xml except for their outline colors. The outline color in stop_button.xml is red ( FF00). The outline color in reset_button.xml is gray ( F444).
9
Drawables for the Buttons (4 of 4)
We add a style that we will use for the buttons’ text. <style name="textViewStyle" parent = <item name = "android:gravity">center</item> <item name = "android:textStyle">bold</item> <item name = "android:textSize">96sp</item> </style>
10
Chronometer Class The Chronometer class encapsulates a chronometer, which includes its visual representation. Thus we can use a Chronometer element in the activity_main.xml file. We use a LinearLayout to place the two buttons in it. We use another LinearLayout to hold space for the ad.
11
activity_main.xml (1 of 5)
We use a LinearLayout to manage the screen. The Chronometer class encapsulates a chronometer, which includes its visual representation. Thus we can use a Chronometer element in the activity_main.xml file. We specify 4/9 of the vertical space for it. We use a LinearLayout to place the two buttons in it. We specify 4/9 of the vertical space for it. We use another LinearLayout to hold space for the ad. We specify 1/9 of the vertical space for it.
12
activity_main.xml (2 of 5)
… <Chronometer android:layout_weight="4" android:layout_width="match_parent" android:layout_height="0dp" />
13
activity_main.xml (3 of 5)
… <LinearLayout android:orientation="horizontal" android:layout_weight="4" android:layout_width="match_parent" android:layout_height="0dp" android:gravity="center" > We place the two buttons inside that LinearLayout.
14
activity_main.xml (4 of 5)
Inside that LinearLayout, we place two LinearLayout, each containing a Button element. When we start, the left button says START and uses the start_button.xml drawable resource for it background. The right button says RESET and uses the reset_button.xml drawable resource for it background.
15
activity_main.xml (5 of 5)
We give the LinearLayout that will hold the ad a gray color so we can see it. See Example 15.5 for the full code for activity_main.xml.
16
MainActivity The two buttons specify startStop and reset as the two methods called when the user clicks on them. We code the startStop and reset methods inside MainActivity as do-nothing methods for now. We code them in Version 1.
17
Version 1 (1 of 2) In Version 1, we enable the user to make the chronometer by using the start/stop button and the reset button.
18
Version 1 (2 of 2) When the user clicks on the start button (and change the appearance of the start button so that it looks like a stop button). We stop the chronometer when the user clicks on the stop button (and change the appearance of the stop button so that it looks like a start button). We reset the chronometer when the user clicks on the reset button.
19
MainActivity There is no change in the user interface.
The only changes are in the MainActivity class. We add two instance variables: chrono, a reference to the Chronometer started, a boolean variable: it keeps track of whether the chronometer is running or not. false not running; true running
20
Chronometer Class The Chronometer class includes the following methods: 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
21
startStop Method (1 of 3) public void startStop( View view ) { // get a reference to the start_stop button if( started ) { // the chronometer was running // stop the chronometer and assign false to started // update the button so that it looks like a start button } else { // the chronometer was not running // start the chronometer and assign true to started // update the button so that it looks like a stop button } }
22
startStop Method (2 of 3) public void startStop( View view ) { Button startStopButton = ( Button ) findViewById( R.id.start_stop ); if( started ) { chrono.stop( ); started = false; startStopButton.setText( "START" ); startStopButton.setBackgroundResource( R.drawable.start_button ); } …
23
startStop Method (3 of 3) …
} else { chrono.start( ); started = true; startStopButton.setText( "STOP" ); startStopButton.setBackgroundResource( R.drawable.stop_button ); } }
24
Reset Method (1 of 3) Inside the reset method:
We only want to reset the chronometer if the chronometer was running and has been stopped (i.e., started is false). We need to call the setBase method of Chronometer with the appropriate argument.
25
Reset Method (2 of 3) 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
26
Reset Method (3 of 3) public void reset( View view ) { if( !started ) chrono.setBase( SystemClock.elapsedRealtime( ) ); }
27
Version 2 (1 of 3) 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.
28
Version 2 (2 of 3) 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, that includes a method that we can use to do that.
29
Version 2 (3 of 3) Example 15.8 shows the ClockUtility class.
Its milliseconds static method converts a String that is formatted like a String displayed inside a Chronometer to its equivalent number of milliseconds. The format of that String is expected to be hh:mm:sss or mm:ss. We use that method each time we restart the chronometer. 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.
30
MainActivity (1 of 2) We add the resetChrono method: it resets the base of the Chronometer to the time that we last stopped it. public void resetChrono( ) { String chronoText = chrono.getText( ).toString(); long idleMilliseconds = ClockUtility.milliseconds( chronoText ); chrono.setBase( SystemClock.elapsedRealtime( ) – idleMilliseconds ); }
31
MainActivity (2 of 2) Whenever the user restarts the Chronometer, we call resetChrono to reset its base time. public void startStop( View view ) { … } else { resetChrono( ); … }
32
Version 3: Advertising Now that we have a working app, we can place the ad at the bottom of the screen inside the last LinearLayout. Google allows us to place a fake ad at the development stage so that we can test our app.
33
Classes for Displaying and Managing a Google Ad
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
34
AdView, AdSize, and AdRequest
These three classes are part of the com.google.android.gms.ads package. 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 them, we edit the build.gradle file.
35
Editing build.gradle We edit the build.gradle file as follows: …
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.google.android.gms:play-services:9.0.1' } Note: We should check what the latest version of Google Play services is and use that one.
36
Editing activity_main.xml
We need to access the LinearLayout where we place the ad (that is the last LinearLayout in activity_main.xml). Thus, we give it an id <LinearLayout android:orientation="horizontal" …
37
MainActivity We add the ad in the onCreate method.
We create an AdView, set its size and its ad unit id. We defined the AdRequest and add it to the AdView. We retrieve the LinearLayout and add the AdView to it. We request an ad from Google.
38
Selected AdView Methods
Description public AdView( Context context ) Constructs for 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
39
Creating the AdView Inside MainActivity, this is an Activity and therefore a Context. We use it as the argument of the AdView constructor. AdView adView = new AdView( this ); To set the size of the banner, we use one of the constants from the AdSize class.
40
AdSize Constants Constant Data Type Description AUTO_HEIGHT int
Causes the height of the ad to scale based on the height of the device. FULL_WIDTH 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 Dynamically sized to full width and auto height.
41
Setting the Banner Size
We want the banner ad to fill the available width so we use the SMART_BANNER constant. AdView adView = new AdView( this ); // Set ad size adView.setAdSize( AdSize.SMART_BANNER );
42
Setting the Ad Unit id If we are a registered Android developer, we can get an ad unit id from Google. If we are not registered and want to test an app containing an AdView, Google provides a test ad unit id for this. Its value is ca-app-pub / String adUnitId = "ca-app-pub / "; adView.setAdUnitId( adUnitId );
43
Creating the AdRequest
Now we create the AdRequest. By doing this, we can target an ad to a more specific demographics, one that typically matches the nature of the app. Builder, a static inner class of AdRequest, includes methods to define the AdRequest and build it. These methods include specifying keywords, gender, location, and other attributes.
44
Selected Methods of AdRequest.Builder
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.
45
Creating the AdRequest
// Create the ad request using an AdRequest.Builder object AdRequest.Builder adRequestBuilder = new AdRequest.Builder( ); // Define target data for adRequest (this is optional) adRequestBuilder.addKeyword( "fitness" ); adRequestBuilder.addKeyword ( "workout" ); Note that all the AdRequest.Builder methods return the AdRequest.Builder that calls them, so method calls can be chained. The build method returns the AdRequest.
46
More Selected Methods of AdRequest.Builder
Description 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
47
Creating the AdRequest
AdRequest.Builder adRequestBuilder = new AdRequest.Builder( ); … // Create the AdRequest AdRequest adRequest = adRequestBuilder.build( );
48
Testing the App and the Ad (1 of 3)
The addTestDevice method enables us to test our app on either the emulator or an Android device with fake ads served by Google. It is against Google policy to test an app with live ads. To test using the emulator: adRequestBuilder.addTestDevice( AdRequest.DEVICE_ID_EMULATOR );
49
Testing the App and the Ad (2 of 3)
We can test on an Android device. 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.
50
Testing the App and the Ad (3 of 3)
Here is the output (the device id is partially hidden) when running with the author’s tablet connected.
51
Adding the AdView (1 of 2) To add the AdView, we first retrieve the LinearLayout using its id, then we add the AdView to it. LinearLayout adLayout = ( LinearLayout ) findViewById( R.id.ad_view ); adLayout.addView( adView );
52
Adding the AdView (2 of 2) Method Description
To request an ad from Google, we call the loadAd method with the AdView. adView.loadAd( adRequest ); Method Description public void loadAd( AdRequest request ) Loads the ad on a background thread
53
AndroidManifest.xml (1 of 3)
We need to edit the AndroidManifest.xml and declare that the app is using the Internet, Google Play Services, and also includes an AdActivity. <!-- required permissions for Google Mobile Ads --> <uses-permission android:name="android.permission.INTERNET"/>
54
AndroidManifest.xml (2 of 3)
<application … > <meta-data android:name="com.google.android.gms.version" />
55
AndroidManifest.xml (3 of 3)
… <activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation| screenLayout|uiMode|screenSize|smallestScreenSize" /> </application> Note that the android:configChanges="..." should be on one line.
56
Version 4 (1 of 2) Google recommends that an AdView be placed inside a fragment. In Version 4, we place the AdView in a fragment rather than a LinearLayout.
57
Version 4 (2 of 2) We need to do the following:
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
58
Fragment XML Layout File: fragment.ad.xml
We place an AdView element inside a RelativeLayout. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout …> <com.google.android.gms.ads.AdView …> </com.google.android.gms.ads.AdView> </RelativeLayout>
59
fragment_ad.xml We need to define banner_ad_unit_id in strings.xml
<com.google.android.gms.ads.AdView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" ads:adSize="SMART_BANNER" </com.google.android.gms.ads.AdView> We need to define banner_ad_unit_id in strings.xml
60
strings.xml <resources> <string name="app_name">StopWatchV4</string> <string name="banner_ad_unit_id"> ca-app-pub / </string> </resources> This is the test unit id provided by Google for non-developer.
61
activity_main.xml We replace the last LinearLayout with a fragment element. <fragment android:name="com.jblearning.stopwatchv4.AdFragment" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" />
62
AdFragment Class (1 of 2) We defined the type of fragment to be AdFragment. android:name="com.jblearning.stopwatchv4.AdFragment” We need to code the AdFragment class. public class AdFragment extends Fragment {
63
AdFragment Class (2 of 2) Inside onActivityCreated:
We retrieve the AdView specified in the fragment using its id. We build an AdRequest. We load it into the AdView. The code is similar to the Version 3 code in MainActivity. See Example
64
onActivityCreated Method
AdView adView = ( AdView ) getView( ).findViewById( R.id.ad_view ); // build the ad request AdRequest.Builder adRequestBuilder = new AdRequest.Builder( ); // Define target data for the ad request (optional) adRequestBuilder.addKeyword ( "workout" ); // request test (not live) ads for emulator adRequestBuilder.addTestDevice( AdRequest.DEVICE_ID_EMULATOR ); AdRequest adRequest = adRequestBuilder.build( ); // load the ad adView.loadAd( adRequest );
65
MainActivity Class Be careful to use test ads and not live ads when testing your app. Clicking on a live ad while testing an app on a device is against Google’s policy. When we are ready to publish our app, we should comment out the code that specifies the emulator or a specific device id to test the app.
66
Test Ads versus Live Ads
Since all the banner ad–related code is in AdFragment, the MainActivity class is the same as the one in Version 2. It sets the GUI and manages the Chronometers.
67
Version 5 When the app goes in the background, there is no need to request an ad from Google. The AdView class provides life cycle methods so that we can manage the life cycle of the AdView. In Version 5, we update our code so that we only request an ad when the app is running.
68
Life Cycle Methods of AdView
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
69
Life Cycle of the AdView (1 of 3)
When the app goes in the background, we want to stop processing associated with the AdView. When the app comes back in the foreground, we want to resume processing associated with the AdView. When the user closes the app, we want to destroy the AdView.
70
Life Cycle of the AdView (2 of 3)
When the app goes in the background, the onPause method of the Fragment class is automatically called (then the onPause method of the Activity class is automatically called). Inside the onPause method of the Fragment class, we want to call the onPause method of the AdView. We want to do something similar inside the onResume and onDestroy methods.
71
Life Cycle of the AdView (3 of 3)
Since we want to call methods of the AdView with the AdView of the app inside these three methods, it is convenient to have a reference to the AdView. Thus we make it an instance variable. private AdView adView; Inside onActivityCreated, we instantiate it. adView = ( AdView ) getView( ).findViewById( R.id.ad_view );
72
onPause When the app goes in the background, the onPause methods of the Fragment and Activity classes are automatically called in that order. We want to pause the processing of the AdView (which is inside the Fragment) before pausing the Fragment itself. Thus, we call the super method last. public void onPause( ) { if( adView != null ) adView.pause( ); super.onPause( ); }
73
onResume When the app comes back in the foreground, the onResume methods of the Activity and Fragment classes are automatically called in that order. We want to resume of the Fragment before resuming the processing of the AdView (which is inside the Fragment). Thus, we call the super method first. public void onResume( ) { super.onResume( ); if( adView != null ) adView.resume( ); }
74
onDestroy When the user closes the app, the onDestroy methods of the Fragment and Activity classes are automatically called in that order. We want to destroy the AdView (which is inside the Fragment) before destroying the Fragment. Thus we call the super method last. public void onDestroy( ) { if( adView != null ) adView.destroy( ); super.onDestroy(); }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.