Skip to content

Commit 1991fe5

Browse files
committed
Adds native video support to DFP custom rendering example. Also updates SDK version in all samples
1 parent 9e58669 commit 1991fe5

File tree

5 files changed

+225
-106
lines changed

5 files changed

+225
-106
lines changed

doubleclick/CustomRenderingExample/app/src/main/java/com/google/example/gms/customrenderingexample/MainActivity.java

Lines changed: 130 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,37 @@
2626
import android.widget.RatingBar;
2727
import android.widget.TextView;
2828
import android.widget.Toast;
29+
2930
import com.google.android.gms.ads.AdListener;
3031
import com.google.android.gms.ads.AdLoader;
32+
import com.google.android.gms.ads.VideoController;
33+
import com.google.android.gms.ads.VideoOptions;
3134
import com.google.android.gms.ads.doubleclick.PublisherAdRequest;
35+
import com.google.android.gms.ads.formats.MediaView;
3236
import com.google.android.gms.ads.formats.NativeAd;
37+
import com.google.android.gms.ads.formats.NativeAdOptions;
3338
import com.google.android.gms.ads.formats.NativeAppInstallAd;
3439
import com.google.android.gms.ads.formats.NativeAppInstallAdView;
3540
import com.google.android.gms.ads.formats.NativeContentAd;
3641
import com.google.android.gms.ads.formats.NativeContentAdView;
3742
import com.google.android.gms.ads.formats.NativeCustomTemplateAd;
38-
import java.util.List;
43+
44+
import java.util.Locale;
3945

4046
/**
4147
* A simple activity class that displays native ad formats.
4248
*/
4349
public class MainActivity extends ActionBarActivity {
4450

4551
private static final String DFP_AD_UNIT_ID = "/6499/example/native";
46-
private static final String SIMPLE_TEMPLATE_ID = "10063170";
52+
private static final String SIMPLE_TEMPLATE_ID = "10104090";
4753

4854
private Button mRefresh;
4955
private CheckBox mRequestAppInstallAds;
5056
private CheckBox mRequestContentAds;
5157
private CheckBox mRequestCustomTemplateAds;
58+
private CheckBox mStartVideoAdsMuted;
59+
private TextView mVideoStatus;
5260

5361
@Override
5462
protected void onCreate(Bundle savedInstanceState) {
@@ -59,6 +67,8 @@ protected void onCreate(Bundle savedInstanceState) {
5967
mRequestAppInstallAds = (CheckBox) findViewById(R.id.cb_appinstall);
6068
mRequestContentAds = (CheckBox) findViewById(R.id.cb_content);
6169
mRequestCustomTemplateAds = (CheckBox) findViewById(R.id.cb_customtemplate);
70+
mStartVideoAdsMuted = (CheckBox) findViewById(R.id.cb_start_muted);
71+
mVideoStatus = (TextView) findViewById(R.id.tv_video_status);
6272

6373
mRefresh.setOnClickListener(new View.OnClickListener() {
6474
@Override
@@ -82,13 +92,15 @@ public void onClick(View v) {
8292
private void populateAppInstallAdView(NativeAppInstallAd nativeAppInstallAd,
8393
NativeAppInstallAdView adView) {
8494
adView.setHeadlineView(adView.findViewById(R.id.appinstall_headline));
85-
adView.setImageView(adView.findViewById(R.id.appinstall_image));
8695
adView.setBodyView(adView.findViewById(R.id.appinstall_body));
8796
adView.setCallToActionView(adView.findViewById(R.id.appinstall_call_to_action));
8897
adView.setIconView(adView.findViewById(R.id.appinstall_app_icon));
8998
adView.setPriceView(adView.findViewById(R.id.appinstall_price));
9099
adView.setStarRatingView(adView.findViewById(R.id.appinstall_stars));
91100
adView.setStoreView(adView.findViewById(R.id.appinstall_store));
101+
// The MediaView will display a video asset if one is present in the ad, and the first image
102+
// asset otherwise.
103+
adView.setMediaView((MediaView) adView.findViewById(R.id.appinstall_media));
92104

93105
// Some assets are guaranteed to be in every NativeAppInstallAd.
94106
((TextView) adView.getHeadlineView()).setText(nativeAppInstallAd.getHeadline());
@@ -97,13 +109,36 @@ private void populateAppInstallAdView(NativeAppInstallAd nativeAppInstallAd,
97109
((ImageView) adView.getIconView()).setImageDrawable(nativeAppInstallAd.getIcon()
98110
.getDrawable());
99111

100-
List<NativeAd.Image> images = nativeAppInstallAd.getImages();
101-
102-
if (images.size() > 0) {
103-
((ImageView) adView.getImageView()).setImageDrawable(images.get(0).getDrawable());
112+
// Get the video controller for the ad. One will always be provided, even if the ad doesn't
113+
// have a video asset.
114+
VideoController vc = nativeAppInstallAd.getVideoController();
115+
116+
// Apps can check the VideoController's hasVideoContent property to determine if the
117+
// NativeAppInstallAd has a video asset.
118+
if (vc.hasVideoContent()) {
119+
mVideoStatus.setText(String.format(Locale.getDefault(),
120+
"Video status: Ad contains a %.2f:1 video asset.",
121+
vc.getAspectRatio()));
122+
123+
// Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The
124+
// VideoController will call methods on this object when events occur in the video
125+
// lifecycle.
126+
vc.setVideoLifecycleCallbacks(new VideoController.VideoLifecycleCallbacks() {
127+
public void onVideoEnd() {
128+
// Publishers should allow native ads to complete video playback before
129+
// refreshing or replacing them with another ad in the same UI location.
130+
mRefresh.setEnabled(true);
131+
mVideoStatus.setText("Video status: Video playback has ended.");
132+
super.onVideoEnd();
133+
}
134+
});
135+
} else {
136+
mRefresh.setEnabled(true);
137+
mVideoStatus.setText("Video status: Ad does not contain a video asset.");
104138
}
105139

106-
// Some aren't guaranteed, however, and should be checked.
140+
// These assets aren't guaranteed to be in every NativeAppInstallAd, so it's important to
141+
// check before trying to display them.
107142
if (nativeAppInstallAd.getPrice() == null) {
108143
adView.getPriceView().setVisibility(View.INVISIBLE);
109144
} else {
@@ -141,25 +176,50 @@ private void populateAppInstallAdView(NativeAppInstallAd nativeAppInstallAd,
141176
private void populateContentAdView(NativeContentAd nativeContentAd,
142177
NativeContentAdView adView) {
143178
adView.setHeadlineView(adView.findViewById(R.id.contentad_headline));
144-
adView.setImageView(adView.findViewById(R.id.contentad_image));
145179
adView.setBodyView(adView.findViewById(R.id.contentad_body));
146180
adView.setCallToActionView(adView.findViewById(R.id.contentad_call_to_action));
147181
adView.setLogoView(adView.findViewById(R.id.contentad_logo));
148182
adView.setAdvertiserView(adView.findViewById(R.id.contentad_advertiser));
183+
// The MediaView will display a video asset if one is present in the ad, and the first image
184+
// asset otherwise.
185+
adView.setMediaView((MediaView) adView.findViewById(R.id.contentad_media));
149186

150187
// Some assets are guaranteed to be in every NativeContentAd.
151188
((TextView) adView.getHeadlineView()).setText(nativeContentAd.getHeadline());
152189
((TextView) adView.getBodyView()).setText(nativeContentAd.getBody());
153190
((TextView) adView.getCallToActionView()).setText(nativeContentAd.getCallToAction());
154191
((TextView) adView.getAdvertiserView()).setText(nativeContentAd.getAdvertiser());
155192

156-
List<NativeAd.Image> images = nativeContentAd.getImages();
157-
158-
if (images.size() > 0) {
159-
((ImageView) adView.getImageView()).setImageDrawable(images.get(0).getDrawable());
193+
// Get the video controller for the ad. One will always be provided, even if the ad doesn't
194+
// have a video asset.
195+
VideoController vc = nativeContentAd.getVideoController();
196+
197+
// Apps can check the VideoController's hasVideoContent property to determine if the
198+
// NativeContentAd has a video asset.
199+
if (vc.hasVideoContent()) {
200+
mVideoStatus.setText(String.format(Locale.getDefault(),
201+
"Video status: Ad contains a %.2f:1 video asset.",
202+
vc.getAspectRatio()));
203+
204+
// Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The
205+
// VideoController will call methods on this object when events occur in the video
206+
// lifecycle.
207+
vc.setVideoLifecycleCallbacks(new VideoController.VideoLifecycleCallbacks() {
208+
public void onVideoEnd() {
209+
// Publishers should allow native ads to complete video playback before
210+
// refreshing or replacing them with another ad in the same UI location.
211+
mRefresh.setEnabled(true);
212+
mVideoStatus.setText("Video status: Video playback has ended.");
213+
super.onVideoEnd();
214+
}
215+
});
216+
} else {
217+
mRefresh.setEnabled(true);
218+
mVideoStatus.setText("Video status: Ad does not contain a video asset.");
160219
}
161220

162-
// Some aren't guaranteed, however, and should be checked.
221+
// These assets aren't guaranteed to be in every NativeContentAd, so it's important to
222+
// check before trying to display them.
163223
NativeAd.Image logoImage = nativeContentAd.getLogo();
164224

165225
if (logoImage == null) {
@@ -182,22 +242,54 @@ private void populateContentAdView(NativeContentAd nativeContentAd,
182242
*/
183243
private void populateSimpleTemplateAdView(final NativeCustomTemplateAd nativeCustomTemplateAd,
184244
View adView) {
185-
ImageView mainImage = (ImageView) adView.findViewById(R.id.simplecustom_image);
186245
TextView headline = (TextView) adView.findViewById(R.id.simplecustom_headline);
187246
TextView caption = (TextView) adView.findViewById(R.id.simplecustom_caption);
188247

189248
headline.setText(nativeCustomTemplateAd.getText("Headline"));
190249
caption.setText(nativeCustomTemplateAd.getText("Caption"));
191250

192-
mainImage.setImageDrawable(
193-
nativeCustomTemplateAd.getImage("MainImage").getDrawable());
251+
FrameLayout mediaPlaceholder =
252+
(FrameLayout) adView.findViewById(R.id.simplecustom_media_placeholder);
253+
254+
// Get the video controller for the ad. One will always be provided, even if the ad doesn't
255+
// have a video asset.
256+
VideoController vc = nativeCustomTemplateAd.getVideoController();
257+
258+
// Apps can check the VideoController's hasVideoContent property to determine if the
259+
// NativeCustomTemplateAd has a video asset.
260+
if (vc.hasVideoContent()) {
261+
mediaPlaceholder.addView(nativeCustomTemplateAd.getVideoMediaView());
262+
mVideoStatus.setText(String.format(Locale.getDefault(),
263+
"Video status: Ad contains a %.2f:1 video asset.",
264+
vc.getAspectRatio()));
265+
266+
// Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The
267+
// VideoController will call methods on this object when events occur in the video
268+
// lifecycle.
269+
vc.setVideoLifecycleCallbacks(new VideoController.VideoLifecycleCallbacks() {
270+
public void onVideoEnd() {
271+
// Publishers should allow native ads to complete video playback before
272+
// refreshing or replacing them with another ad in the same UI location.
273+
mRefresh.setEnabled(true);
274+
mVideoStatus.setText("Video status: Video playback has ended.");
275+
super.onVideoEnd();
276+
}
277+
});
278+
} else {
279+
ImageView mainImage = new ImageView(this);
280+
mainImage.setAdjustViewBounds(true);
281+
mainImage.setImageDrawable(nativeCustomTemplateAd.getImage("MainImage").getDrawable());
194282

195-
mainImage.setOnClickListener(new View.OnClickListener() {
196-
@Override
197-
public void onClick(View v) {
198-
nativeCustomTemplateAd.performClick("MainImage");
199-
}
200-
});
283+
mainImage.setOnClickListener(new View.OnClickListener() {
284+
@Override
285+
public void onClick(View v) {
286+
nativeCustomTemplateAd.performClick("MainImage");
287+
}
288+
});
289+
mediaPlaceholder.addView(mainImage);
290+
mRefresh.setEnabled(true);
291+
mVideoStatus.setText("Video status: Ad does not contain a video asset.");
292+
}
201293
}
202294

203295
/**
@@ -216,6 +308,8 @@ private void refreshAd(boolean requestAppInstallAds, boolean requestContentAds,
216308
return;
217309
}
218310

311+
mRefresh.setEnabled(false);
312+
219313
AdLoader.Builder builder = new AdLoader.Builder(this, DFP_AD_UNIT_ID);
220314

221315
if (requestAppInstallAds) {
@@ -272,14 +366,27 @@ public void onCustomClick(NativeCustomTemplateAd ad, String s) {
272366
});
273367
}
274368

369+
VideoOptions videoOptions = new VideoOptions.Builder()
370+
.setStartMuted(mStartVideoAdsMuted.isChecked())
371+
.build();
372+
373+
NativeAdOptions adOptions = new NativeAdOptions.Builder()
374+
.setVideoOptions(videoOptions)
375+
.build();
376+
377+
builder.withNativeAdOptions(adOptions);
378+
275379
AdLoader adLoader = builder.withAdListener(new AdListener() {
276380
@Override
277381
public void onAdFailedToLoad(int errorCode) {
382+
mRefresh.setEnabled(true);
278383
Toast.makeText(MainActivity.this, "Failed to load native ad: "
279384
+ errorCode, Toast.LENGTH_SHORT).show();
280385
}
281386
}).build();
282387

283388
adLoader.loadAd(new PublisherAdRequest.Builder().build());
389+
390+
mVideoStatus.setText("");
284391
}
285392
}

doubleclick/CustomRenderingExample/app/src/main/res/layout/activity_main.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
android:checked="true"
3838
android:text="Request Custom Template Ads" />
3939

40+
<CheckBox
41+
android:id="@+id/cb_start_muted"
42+
android:layout_width="wrap_content"
43+
android:layout_height="wrap_content"
44+
android:checked="true"
45+
android:text="Start video ads muted" />
46+
4047
<Button
4148
android:id="@+id/btn_refresh"
4249
android:layout_width="wrap_content"
@@ -46,6 +53,14 @@
4653
android:layout_marginTop="16dp"
4754
android:text="Refresh Ad" />
4855

56+
<TextView
57+
android:id="@+id/tv_video_status"
58+
android:layout_width="match_parent"
59+
android:layout_height="wrap_content"
60+
android:layout_marginLeft="@dimen/activity_horizontal_margin"
61+
android:layout_marginRight="@dimen/activity_horizontal_margin"
62+
android:text="Video status: "
63+
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
4964

5065
</LinearLayout>
5166
</ScrollView>

0 commit comments

Comments
 (0)