简介

原生广告是与应用内容融于一体的广告,通过"和谐"的内容呈现广告信息,在不破坏用户体验的前提下,为用户提供有价值的信息,展示形式包含图片、文字和视频,支持您自由定制界面。

此codelab将引导您在应用中增加原生广告的展示。在整个过程中,将介绍添加代码的详细过程以正确展示原生广告。

您将建立什么

您将在您的应用中通过HUAWEI Ads SDK定制原生广告样式、获取原生广告和展示原生广告。

您将会学到什么

硬件要求

支持EMUI 3.0及以上的华为手机、华为平板。

软件要求

需要的知识点

Android基础开发能力。

在Android Studio中创建项目

  1. 打开Android Studio。
  2. 创建新项目,选择"Empty Activity",命名为"NativeAdExample"。
  3. 点击"完成"。

配置HUAWEI VAST SDK仓库及依赖包

  1. 配置Maven仓地址。

    Android Studio的代码库配置在Gradle 插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请根据您当前的Gradle 插件版本,选择对应的配置过程。

    7.0以下版本

    7.0版本

    7.1及以上版本

    • 7.0以下版本
      i.  打开Android Studio项目级"build.gradle"文件。


      ii.  添加Maven代码库。

      • 在"buildscript > repositories"中配置Maven仓地址。
      • 在"allprojects > repositories"中配置Maven仓地址。
      buildscript { repositories { google() jcenter() // 配置HUAWEI Ads SDK的Maven仓地址 maven {url 'https://developer.huawei.com/repo/'} } } allprojects { repositories { google() jcenter() // 配置HUAWEI Ads SDK的Maven仓地址 maven {url 'https://developer.huawei.com/repo/'} } }
    • 7.0版本
      i.  打开Android Studio项目级"build.gradle"文件。


      ii.  添加Maven代码库。

        在"buildscript > repositories"中配置Maven仓地址。

      buildscript { repositories { google() jcenter() // 配置HUAWEI Ads SDK的Maven仓地址 maven {url 'https://developer.huawei.com/repo/'} } }

      iii.  打开项目级"settings.gradle"文件,配置Maven仓地址。

      dependencyResolutionManagement { ... repositories { google() jcenter() // 配置HUAWEI Ads SDK的Maven仓地址 maven {url 'https://developer.huawei.com/repo/'} } }
    • 7.1及以上版本
      打开项目级"settings.gradle"文件,配置Maven仓地址。

      pluginManagement { repositories { gradlePluginPortal() google() mavenCentral() // 配置HUAWEI Ads SDK的Maven仓地址 maven { url 'https://developer.huawei.com/repo/' } } } dependencyResolutionManagement { ... repositories { google() mavenCentral() // 配置HUAWEI Ads SDK的Maven仓地址 maven { url 'https://developer.huawei.com/repo/' } } }
  2. 在应用级"build.gradle"文件中配置依赖包,需添加下面内容,并将{version}替换为实际的HUAWEI Ads SDK版本号,请参见版本更新说明
    dependencies { ... implementation 'com.huawei.hms:ads-lite:{version}' ... }
  3. 点击"Sync Now"等待同步完成。

配置混淆脚本

您编译APK前需要配置不要混淆HUAWEI Ads SDK,避免功能异常。
打开Android工程应用级根目录下的"app/proguard-rules.pro"混淆配置文件,添加如下两行代码,加入排除HUAWEI Ads SDK的混淆配置。

-keep class com.huawei.openalliance.ad.** { *; } -keep class com.huawei.hms.ads.** { *; }

要借助于HUAWEI Ads SDK获取广告,必须先在您的应用中调用HwAds.init()方法初始化SDK ,此过程需要在应用程序启动时完成,在应用后续运行过程中无需重复执行此过程。
在MainActivity类的onCreate()方法中调用HwAds.init()以执行HUAWEI Ads SDK初始化。

import com.huawei.hms.ads.HwAds; ... public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化HUAWEI Ads SDK HwAds.init(this); ... } ... }

定义原生广告布局

对于原生广告,HUAWEI Ads SDK提供了广告视图类NativeView,NativeView用于显示原生广告中所有的素材。SDK还提供了显示不同种类素材的视图,例如MediaView用于显示多媒体素材,这类视图应该被包含在NativeView中。
现在,您需要在NativeView中为各类广告素材视图进行布局。在本章节中,您将使用布局XML文件方式设置原生广告视图的布局。为了节省时间,您可以使用下面创建好的XML内容。

  1. 在"res/layout/"目录下新增"native_video_template.xml"文件,并在文件中添加以下列出的XML内容。
    <com.huawei.hms.ads.nativead.NativeView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/native_video_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="#FFFFFF" android:orientation="vertical"> <RelativeLayout android:id="@+id/background" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.huawei.hms.ads.nativead.MediaView android:id="@+id/ad_media" android:layout_width="match_parent" android:layout_height="wrap_content" /> <RelativeLayout android:id="@+id/left_bottom_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/ad_media"> <TextView android:id="@+id/ad_title" android:layout_width="180dp" android:layout_height="19dp" android:layout_marginStart="24dp" android:layout_marginTop="16dp" android:alpha="1" android:textColor="#000000" android:textSize="@dimen/hiad_text_13_sp" /> <TextView android:id="@+id/ad_source" android:layout_width="wrap_content" android:layout_height="19dp" android:layout_below="@id/ad_title" android:layout_marginStart="24dp" android:layout_marginTop="2dp" android:layout_marginBottom="16dp" android:alpha="0.6" android:maxWidth="158dp" android:textColor="#666666" android:textSize="@dimen/hiad_text_12_sp" /> <TextView android:id="@+id/ad_flag" android:layout_width="20dp" android:layout_height="14dp" android:layout_marginStart="8dp" android:layout_marginTop="40dp" android:layout_toEndOf="@+id/ad_source" android:background="@drawable/native_flag_rounded_corners_shape" android:gravity="center" android:text="@string/ad_flag" android:textColor="#FFFFFF" android:textSize="8sp" android:textStyle="bold" /> </RelativeLayout> <RelativeLayout android:id="@+id/right_bottom_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/ad_media" android:layout_alignParentEnd="true"> <Button android:id="@+id/ad_call_to_action" android:layout_width="72dp" android:layout_height="26dp" android:layout_alignParentEnd="true" android:layout_marginTop="23dp" android:layout_marginEnd="52dp" android:layout_marginBottom="23dp" android:background="@drawable/native_button_rounded_corners_shape" android:textColor="#FFFFFF" android:textSize="10sp" /> </RelativeLayout> </RelativeLayout> </com.huawei.hms.ads.nativead.NativeView>
  2. 在"res/layout/"目录下新增"native_small_template.xml"文件,并在文件中添加以下列出的XML内容。
    <?xml version="1.0" encoding="utf-8"?> <com.huawei.hms.ads.nativead.NativeView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/native_small_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginTop="10dp" android:background="#FFFFFF" android:orientation="vertical"> <RelativeLayout android:id="@+id/background" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:orientation="vertical"> <com.huawei.hms.ads.nativead.MediaView android:id="@+id/ad_media" android:layout_width="75dp" android:layout_height="50dp" android:layout_marginStart="24dp" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:background="#8BC34A" /> <RelativeLayout android:id="@+id/center_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="107dp" android:layout_marginTop="8dp" android:layout_marginEnd="48dp" android:layout_marginBottom="8dp" android:background="#FFFFFF"> <TextView android:id="@+id/ad_title" android:layout_width="match_parent" android:layout_height="34dp" android:layout_marginBottom="16dp" android:alpha="1" android:textColor="#000000" android:textSize="@dimen/hiad_text_13_sp" /> <TextView android:id="@+id/ad_source" android:layout_width="wrap_content" android:layout_height="14dp" android:layout_marginTop="36dp" android:alpha="0.6" android:maxWidth="132dp" android:textColor="#666666" android:textSize="@dimen/hiad_text_9_sp" /> <TextView android:id="@+id/ad_flag" android:layout_width="16dp" android:layout_height="14dp" android:layout_marginStart="8dp" android:layout_marginTop="36dp" android:layout_toEndOf="@+id/ad_source" android:background="@drawable/native_flag_rounded_corners_shape" android:gravity="center" android:text="@string/ad_flag" android:textColor="#FFFFFF" android:textSize="8sp" android:textStyle="bold" /> <Button android:id="@+id/ad_call_to_action" android:layout_width="44dp" android:layout_height="@dimen/hiad_16_dp" android:layout_alignParentEnd="true" android:layout_marginTop="34dp" android:background="@drawable/native_button_rounded_corners_shape" android:textColor="#FFFFFF" android:textSize="6sp" /> </RelativeLayout> </RelativeLayout> </com.huawei.hms.ads.nativead.NativeView>
  3. 在"res/drawable/"目录下新增"native_flag_rounded_corners_shape.xml"文件,并在文件中添加以下列出的XML内容。
    <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#CCCCCC" /> <padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" /> <corners android:bottomLeftRadius="2dp" android:bottomRightRadius="2dp" android:topLeftRadius="2dp" android:topRightRadius="2dp" /> </shape>
  4. 在"res/drawable/"目录下新增文件"native_button_rounded_corners_shape.xml",并在文件中添加以下列出的XML内容。
    <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#214EF3" /> <padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" /> <corners android:bottomLeftRadius="20dp" android:bottomRightRadius="20dp" android:topLeftRadius="20dp" android:topRightRadius="20dp" /> </shape>
  5. 在"res/values/strings.xml"中增加下面内容。
    <resources> ... <string name="app_name">NativeAdExample</string> <string name="ad_id_native">testu7m3hc4gvm</string> <string name="ad_id_native_small">testb65czjivt9</string> <string name="ad_id_native_video">testy63txaom86</string> <string name="ad_flag">Ad</string> ... </resources>

定义原生广告外层容器布局

  1. 此项目中需定义原生广告外层容器布局,用于控制和重新获取原生广告,请在"res/layout/activity_main.xml"中添加LinearLayout部分内容,添加完成后的XML内容如下所示。
    <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <TextView android:id="@+id/ad_display_form" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/activity_horizontal_margin" android:layout_marginTop="@dimen/activity_vertical_margin" android:layout_marginRight="@dimen/activity_horizontal_margin" android:text="@string/display_form" android:textColor="#000000" android:textSize="@dimen/hiad_text_16_sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioGroup android:id="@+id/radio_group_display_form" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/activity_horizontal_margin" android:layout_marginRight="@dimen/activity_horizontal_margin"> <RadioButton android:id="@+id/radio_button_large" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="@string/large" /> <RadioButton android:id="@+id/radio_button_small" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/small" /> <RadioButton android:id="@+id/radio_button_video" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/video" /> </RadioGroup> <Button android:id="@+id/btn_load" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="@dimen/activity_horizontal_margin" android:layout_marginRight="@dimen/activity_horizontal_margin" android:text="@string/load_button_text" /> </LinearLayout> <ScrollView android:id="@+id/scroll_view_ad" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
  2. 在"res/values/"目录中新增"dimens.xml"的文件,并在文件中添加以下列出的XML内容。
    <resources> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> </resources>
  3. 在"res/values/strings.xml"中增加下面内容。
    <resources> ... <string name="display_form">Display form:</string> <string name="large">Large image with text.</string> <string name="small">Small image with text.</string> <string name="video">Video with text.</string> <string name="load_button_text">LOAD AD</string> <string name="status_ad_loading">Ad loading state: being loaded.</string> <string name="status_load_ad_success">Ad loading state: loaded successfully.</string> <string name="status_load_ad_fail">Ad loading state: failed to be loaded. Error code: </string> <string name="status_play_start">Video playback state: starting to be played.</string> <string name="status_playing">Video playback state: being played.</string> <string name="status_play_end">Video playback state: playback completed.</string> <string name="ad_is_closed">Ad is closed.</string> ... </resources>

现在,您需要注册原生广告素材视图,并将原生广告中的素材填充到原生广告素材视图中。下面代码片段中的initNativeAdView()方法展示了这一过程。在完成广告视图填充后,您还需要通过setNativeAd()方法将NativeAd对象注册到原生广告视图NativeView对象中。

... import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.huawei.hms.ads.VideoOperator; import com.huawei.hms.ads.nativead.MediaView; import com.huawei.hms.ads.nativead.NativeAd; import com.huawei.hms.ads.nativead.NativeView; ... private VideoOperator.VideoLifecycleListener videoLifecycleListener = new VideoOperator.VideoLifecycleListener() { @Override public void onVideoStart() { updateStatus(getString(R.string.status_play_start), false); } @Override public void onVideoPlay() { updateStatus(getString(R.string.status_playing), false); } @Override public void onVideoEnd() { // 如果有视频,需要等待视频播放完成后再加载新的原生广告 updateStatus(getString(R.string.status_play_end), true); } }; ... /** * 注册并填充原生广告素材视图 * * @param nativeAd 包含广告素材的原生广告对象 * @param nativeView 待填充的原生广告视图 */ private void initNativeAdView(NativeAd nativeAd, NativeView nativeView) { // 注册原生广告素材视图 nativeView.setTitleView(nativeView.findViewById(R.id.ad_title)); nativeView.setMediaView((MediaView) nativeView.findViewById(R.id.ad_media)); nativeView.setAdSourceView(nativeView.findViewById(R.id.ad_source)); nativeView.setCallToActionView(nativeView.findViewById(R.id.ad_call_to_action)); // 填充原生广告素材视图,原生广告中必有标题和媒体素材 ((TextView) nativeView.getTitleView()).setText(nativeAd.getTitle()); nativeView.getMediaView().setMediaContent(nativeAd.getMediaContent()); if (null != nativeAd.getAdSource()) { ((TextView) nativeView.getAdSourceView()).setText(nativeAd.getAdSource()); } nativeView.getAdSourceView().setVisibility(null != nativeAd.getAdSource() ? View.VISIBLE : View.INVISIBLE); if (null != nativeAd.getCallToAction()) { ((Button) nativeView.getCallToActionView()).setText(nativeAd.getCallToAction()); } nativeView.getCallToActionView().setVisibility(null != nativeAd.getCallToAction() ? View.VISIBLE : View.INVISIBLE); // 获取视频控制器 VideoOperator videoOperator = nativeAd.getVideoOperator(); // 判断原生广告中是否包含视频素材 if (videoOperator.hasVideo()) { // 添加视频生命周期事件监听器 videoOperator.setVideoLifecycleListener(videoLifecycleListener); } // 注册原生广告对象 nativeView.setNativeAd(nativeAd); } /** * 更新提示信息和获取按钮的状态 * * @param text 提示信息 * @param loadBtnEnabled 获取按钮的状态 */ private void updateStatus(String text, boolean loadBtnEnabled) { if (null != text) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); } loadBtn.setEnabled(loadBtnEnabled); } ...

您将使用NativeAdLoader类获取原生广告,该类还提供了NativeAdLoader.Builder类,可用于设置广告位ID、设置自定义选项和构建NativeAdLoader对象。
新增获取原生广告的loadAd()方法,将其作为刷新按钮的响应函数,并将其添加到MainActivity类的onCreate()方法中。一旦获取完成,则可调用initNativeAdView()将获取到的广告添加到对应的广告视图中。最后您需在onDestroy()中销毁原生广告对象。

... import android.view.View; import android.widget.Button; import android.widget.ScrollView; import android.widget.RadioButton; import android.widget.TextView; import com.huawei.hms.ads.AdListener; import com.huawei.hms.ads.AdParam; import com.huawei.hms.ads.HwAds; import com.huawei.hms.ads.nativead.DislikeAdListener; import com.huawei.hms.ads.nativead.NativeAd; import com.huawei.hms.ads.nativead.NativeAdConfiguration; import com.huawei.hms.ads.nativead.NativeAdLoader; import com.huawei.hms.ads.nativead.NativeView; ... public class MainActivity extends AppCompatActivity { private RadioButton small; private RadioButton video; private Button loadBtn; private ScrollView adScrollView; private int layoutId; private NativeAd globalNativeAd; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化HUAWEI Ads SDK HwAds.init(this); small = findViewById(R.id.radio_button_small); video = findViewById(R.id.radio_button_video); loadBtn = findViewById(R.id.btn_load); adScrollView = findViewById(R.id.scroll_view_ad); loadBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loadAd(getAdId()); } }); loadAd(getAdId()); } /** * 初始化广告位ID和布局模板 * * @return 广告位ID */ private String getAdId() { String adId; layoutId = R.layout.native_video_template; if (small.isChecked()) { adId = getString(R.string.ad_id_native_small); layoutId = R.layout.native_small_template; } else if (video.isChecked()) { adId = getString(R.string.ad_id_native_video); } else { adId = getString(R.string.ad_id_native); } return adId; } /** * 获取原生广告 * * @param adId 广告位ID */ private void loadAd(String adId) { updateStatus(null, false); NativeAdLoader.Builder builder = new NativeAdLoader.Builder(this, adId); builder.setNativeAdLoadedListener(new NativeAd.NativeAdLoadedListener() { @Override public void onNativeAdLoaded(NativeAd nativeAd) { // 成功加载广告时调用此方法 updateStatus(getString(R.string.status_load_ad_success), true); // 展示原生广告 showNativeAd(nativeAd); nativeAd.setDislikeAdListener(new DislikeAdListener() { @Override public void onAdDisliked() { // 关闭广告时调用此方法 updateStatus(getString(R.string.ad_is_closed), true); } }); } }).setAdListener(new AdListener() { @Override public void onAdFailed(int errorCode) { // 广告加载失败时调用此方法 updateStatus(getString(R.string.status_load_ad_fail) + errorCode, true); } }); NativeAdConfiguration adConfiguration = new NativeAdConfiguration.Builder() // 设置自定义属性 .setChoicesPosition(NativeAdConfiguration.ChoicesPosition.BOTTOM_RIGHT) .build(); NativeAdLoader nativeAdLoader = builder.setNativeAdOptions(adConfiguration).build(); nativeAdLoader.loadAd(new AdParam.Builder().build()); updateStatus(getString(R.string.status_ad_loading), false); } /** * 展示原生广告 * * @param nativeAd包含广告素材的原生广告对象 */ private void showNativeAd(NativeAd nativeAd) { // 摧毁原始的原生广告 if (null != globalNativeAd) { globalNativeAd.destroy(); } globalNativeAd = nativeAd; // 创建NativeView NativeView nativeView = (NativeView) getLayoutInflater().inflate(layoutId, null); // 填充NativeView initNativeAdView(globalNativeAd, nativeView); // 添加广告到程序界面 adScrollView.removeAllViews(); adScrollView.addView(nativeView); } ... @Override protected void onDestroy() { if (null != globalNativeAd) { globalNativeAd.destroy(); } super.onDestroy(); } }

运行项目后,您将会在应用中看到原生广告。

祝贺您,您已经成功完成了codelab并学到了:

您可以阅读相关链接,了解更多的信息:开发指南API文档FAQ
您还可以点击源码下载

Code copied