11-自然壁纸实战教程-接入鲸鸿动能广告 原创 精华

万少skr
发布于 2025-7-8 15:10
浏览
0收藏

11-自然壁纸实战教程-接入鲸鸿动能广告

前言

​ 目前我们上架的作品都打算接入广告,当做是学习下鸿蒙的广告接入流程,也是也希望着后续做出更加优质的 作品和应用了,可以通过广告实现收益。

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

广告流程

商业上架前需进行广告的测试验证,包括媒体自测和鲸鸿动能验收两个步骤。

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

自测

自测阶段请使用测试ID,并对照《APK广告位信息表》交付件中的“转测自检项”核对检查;

  1. SDK自助测试工具

    您可以通过SDK自助测试工具检测自己的App是否正确集成了SDK、广告请求和广告返回是否成功、广告展示是否正常以及广告事件是否正常上报。如果广告请求异常或未正确获取广告,SDK自助测试工具会提供相应的解决建议。具体详情请扫描下方二维码或点击链接下载APK。

    类型 二维码 APK下载
    APK 11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区 下载
  2. 极速开屏无需自测,直接提交鲸鸿动能测试验收,但需填写信息表。

  3. 请务必检查确认关于用户隐私声明的要求,媒体需以自身的名义发布用户隐私声明,禁止以华为或鲸鸿动能等名义发布用户隐私声明,详情参考《业务规范》- 《隐私声明》的要求;

  4. 各广告位规则:请参照《业务规范》-《广告规范》

  5. 自测完成后,填写《APK广告位信息表》和《RPK广告位信息表》,其中涉及广告位信息和转测自检项,保证清晰描述广告位调用逻辑,转测自检项全部通过。

鲸鸿动能验收

在自测没有问题之后,我们要交予鲸鸿动能验收,联系人工客服,拉群进行验收(一家公司有一个群就行了)

一般就是1-2个工作日哈

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

运营配置广告

在测试验收通过之后,他们会联系运营进行配置广告,一般这个过程也需要一日

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

商品上架

在上方的步骤全部结束之后,我们就可以更换广告正式位ID,然后上架

广告开发流程

请求广告。

请求单广告位广告,需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener,来监听广告的加载状态。

请求广告关键参数如下所示:

请求广告参数名 类型 必填 说明
adType number 请求广告类型,原生广告类型为3。
adId string 广告位ID。
  • 如果仅调测广告,可使用测试广告位ID:testy63txaom86(原生视频),testu7m3hc4gvm(原生大图),testb65czjivt9(原生小图),testr6w14o0hqz(原生三图)。
  • 如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建

展示广告

  • 说明 用户关闭广告或点负反馈,需要处理AD_CLOSED回调。在您的页面中使用AdComponent组件展示原生广告

封装之后的代码

请求广告的类

NativeAdUtil.ets

import { advertising } from "@kit.AdsKit";
import { router } from "@kit.ArkUI";
import { common } from "@kit.AbilityKit";
import { hilog } from "@kit.PerformanceAnalysisKit";
import { emitter } from "@kit.BasicServicesKit";

export class NativeAdUtil {
  private ads: Array<advertising.Advertisement> = [];
  private context: common.UIAbilityContext = getContext(
    this,
  ) as common.UIAbilityContext;

  requestAd() {
    // 广告展示参数
    const adDisplayOptions: advertising.AdDisplayOptions = {
      // 是否静音,默认不静音
      mute: false,
    };
    // 原生广告配置
    const adOptions: advertising.AdOptions = {
      // 设置是否请求非个性化广告
      nonPersonalizedAd: 1,
      // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
      allowMobileTraffic: 0,
      // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
      tagForChildProtection: -1,
      // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
      tagForUnderAgeOfPromise: -1,
      // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
      adContentClassification: "A",
    };
    // 原生广告请求参数
    const nativeVideoAdReqParams: advertising.AdRequestParams = {
      // 'testu7m3hc4gvm'为测试专用的广告位ID,应用正式发布时需要改为正式的广告位ID
      //正式广告位  s3z1eig5n2
      adId: "s3z1eig5n2",
      adType: 3,
      adCount: 1,
      // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
      enableDirectReturnVideoAd: true,
    };
    // 广告请求回调监听
    const adLoaderListener: advertising.AdLoadListener = {
      // 广告请求失败回调
      onAdLoadFailure: (errorCode: number, errorMsg: string) => {
        hilog.error(
          0x0000,
          "testTag",
          "%{public}s",
          `Failed to request ad, message: ${errorMsg}, error code: ${errorCode}`,
        );
      },
      // 广告请求成功回调
      onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
        hilog.info(
          0x0000,
          "testTag",
          "%{public}s",
          `Succeeded in requesting ad`,
        );
        // 调用原生广告展示页面
        emitter.emit("NativeAdPage", {
          data: { ads: ads, adDisplayOptions: adDisplayOptions },
        });
      },
    };
    // 创建AdLoader广告对象
    const load: advertising.AdLoader = new advertising.AdLoader(this.context);
    // 调用广告请求接口
    load.loadAd(nativeVideoAdReqParams, adOptions, adLoaderListener);
  }
}

export const nativeAdUtil = new NativeAdUtil();
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374;

广告展示组件

import { AdComponent, advertising } from '@kit.AdsKit';
import { emitter } from '@kit.BasicServicesKit';
import { nativeAdUtil } from '../utils/NativeAdUtil';


@Component
export struct NativeAdPage {
  // 广告内容
  private ads: Array<advertising.Advertisement> = [];
  private adDisplayOptions: advertising.AdDisplayOptions = {
    // 是否静音,默认不静音
    mute: false
  };
  @State isShow: boolean = false

  aboutToAppear() {
    emitter.on('NativeAdPage', (eventData: emitter.EventData) => {
      const data = eventData.data as Record<string, object>
      this.ads = data['ads'] as Array<advertising.Advertisement>
      this.adDisplayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
      this.isShow = true
    })
    nativeAdUtil.requestAd()
  }

  build() {
    if (this.isShow) {
      AdComponent({
        ads: this.ads,
        displayOptions: this.adDisplayOptions,
        interactionListener: {
          onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
            switch (status) {
              case AdStatus.AD_OPEN:
                break;
              case AdStatus.AD_CLICKED:
                break;
              case AdStatus.AD_CLOSED:
                break;
              default:
            }
          }
        }
      })
        .width('100%')
    }

  }
}

enum AdStatus {
  AD_OPEN = 'onAdOpen',
  AD_CLICKED = 'onAdClick',
  AD_CLOSED = 'onAdClose'
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455

测试位ID效果

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

补充:Ads Kit(广告服务)开发指南

​ Ads Kit(广告服务)依托华为终端平台与数据能力为您提供流量变现服务,帮助您解决流量变现的难题;同时为广告主提供广告服务,配合华为终端平台向用户提供个性化的营销活动或商业广告。

鲸鸿动能流量变现服务(以下简称流量变现服务)是广告服务依托华为终端强大的平台与数据能力为您提供的App流量变现服务,您通过该服务可以在自己的App中获取并向用户展示精美的、高价值的广告内容,并从中获得广告收益。
为满足App不同场景下的内容形式,流量变现服务提供了横幅广告、原生广告、激励广告、插屏广告、开屏广告、贴片广告六种广告形式。

广告形式 展示形式 应用场景
横幅广告 图片 以通知栏或矩形固定展示在应用内页面顶部、中部或底部,适合用于用户停留较久或者访问频繁的页面。
原生广告 图片、视频 界面内插入广告,与媒体内容无缝融合。
激励广告 视频 游戏通关、复活、获取道具、积分、继续机会、人物技能升级时等展示。
插屏广告 图片、视频 游戏或流媒体开启、暂停、过关、跳转、加载、退出时弹出。
开屏广告 图片、视频 打开App时,以开屏形式全屏展现,展示时长3s-5s,展示完毕后自动关闭并进入应用主页面。
贴片广告 图片、视频 前贴:视频播放前。中贴:视频播放中。后贴:视频播放结束后。说明:您可以根据自身需求设置广告的播放时长。

具体如何进入这项服务,我在之前的文章中专门介绍过接入广告服务,这里就不过多介绍这个,本系列文章主要介绍的是广告的使用和展示

广告展示

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

1.横幅广告

横幅广告又名Banner广告,是在应用程序顶部、中部或底部占据一个位置的矩形图片,广告内容每隔一段时间会自动刷新。

1.1 解释说明

横幅广告是所有广告里较为简单的。

  1. 获取OAID。

    若需提升广告推送精准度,可以在请求参数AdRequestParams中添加oaid属性以提升广告推送精准度和广告填充率。

    如何获取OAID参考获取OAID信息

    说明

    使用以下示例中提供的测试广告位时,必须先获取OAID信息。

    identifier.getOAID().then((data: string) => {
      this.oaid = data;
    }).catch((error: BusinessError) => {
      hilog.error(0x0000, 'testTag', 'Failed to get OAID');
    });
    
    
  2. 请求和展示广告。

    在您的页面中使用AutoAdComponent组件展示横幅广告。

    请求广告关键参数如下所示:

    请求广告参数名 类型 必填 说明
    adType number 请求广告类型,横幅广告类型为8。
    adId string 广告位ID。如果仅调测广告,可使用测试广告位ID:testw6vs28auh3。如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建
    adWidth number 广告位宽,单位vp。宽和高支持36057和360144两种尺寸。
    adHeight number 广告位高,单位vp。宽和高支持36057和360144两种尺寸。
    oaid string 开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。

    展示广告关键参数如下所示:

    展示广告参数名 类型 必填 说明
    refreshTime number 横幅广告轮播时间。单位ms,取值范围[30000, 120000]。如果不设置或取值为非数字或小于等于0的数字,则不轮播。设置小于30000的数字取值30000,设置大于120000的数字取值120000。
      AutoAdComponent({
        adParam: this.adParam,
        adOptions: this.adOptions,
        displayOptions: this.displayOptions,
        interactionListener: {
          onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
            hilog.info(0x0000, 'testTag', '%{public}s', `status is ${status}`);
            switch (status) {
              case AdStatus.AD_OPEN:
                hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');
                break;
              case AdStatus.AD_CLICKED:
                hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');
                break;
              case AdStatus.AD_CLOSED:
                hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
                this.visibilityState = Visibility.None;
                break;
              case AdStatus.AD_LOAD:
                hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdLoad');
                break;
              case AdStatus.AD_FAIL:
                hilog.error(0x0000, 'testTag', '%{public}s', 'Status is onAdFail');
                this.visibilityState = Visibility.None;
                break;
            }
          }
        }
      })

1.2示例代码

为了小伙伴之后,可以直接使用,这边我已经将他封装成自定义组件咯

import { advertising, AutoAdComponent } from '@kit.AdsKit';
import { hilog } from '@kit.PerformanceAnalysisKit';


@Component
export struct BannerView {
 @State adParam: advertising.AdRequestParams = {
   // 广告类型:横幅广告
   adType: 8,
   // 'testw6vs28auh3'为测试专用的广告位ID,应用正式发布时需要改为正式的广告位ID
   adId: 'testw6vs28auh3',
   // 广告位宽
   adWidth: 360,
   // 广告位高
   adHeight: 57
 };
 private adOptions: advertising.AdOptions = {
   // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
   allowMobileTraffic: 0,
   // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
   tagForChildProtection: -1,
   // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
   tagForUnderAgeOfPromise: -1,
   // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
   adContentClassification: 'A'
 };
 private displayOptions: advertising.AdDisplayOptions = {
   // 广告轮播的时间间隔,单位ms,取值范围[30000, 120000]
   refreshTime: 30000
 }
 private ratio: number = 1;
 private adWidth: number = -1;
 private adHeight: number = -1;
 @State visibilityState: Visibility = Visibility.Visible;

 aboutToAppear() {
   if (this.adParam?.adWidth && typeof (this.adParam?.adWidth) === 'number' && this.adParam?.adWidth > 0) {
     this.adWidth = this.adParam?.adWidth;
   }
   if (this.adParam?.adHeight && typeof (this.adParam?.adHeight) === 'number' && this.adParam?.adHeight > 0) {
     this.adHeight = this.adParam?.adHeight;
   }
   if (this.adWidth > 0 && this.adHeight > 0) {
     this.ratio = this.adWidth / this.adHeight;
   }
 }

 build() {
   Stack({ alignContent: Alignment.Bottom }) {
     this.buildBannerView()
   }
 }

 @Builder
 buildBannerView() {
   Row() {
     AutoAdComponent({
       adParam: this.adParam,
       adOptions: this.adOptions,
       displayOptions: this.displayOptions,
       interactionListener: {
         onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
           hilog.info(0x0000, 'testTag', '%{public}s', `status is ${status}`);
           switch (status) {
             case AdStatus.AD_OPEN:
               hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');
               break;
             case AdStatus.AD_CLICKED:
               hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');
               break;
             case AdStatus.AD_CLOSED:
               hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
               this.visibilityState = Visibility.None;
               break;
             case AdStatus.AD_LOAD:
               hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdLoad');
               break;
             case AdStatus.AD_FAIL:
               hilog.error(0x0000, 'testTag', '%{public}s', 'Status is onAdFail');
               this.visibilityState = Visibility.None;
               break;
           }
         }
       }
     })
   }
   .width('100%')
   .aspectRatio(this.ratio)
   .visibility(this.visibilityState)
 }
}

enum AdStatus {
 AD_LOAD = 'onAdLoad',
 AD_FAIL = 'onAdFail',
 AD_OPEN = 'onAdOpen',
 AD_CLICKED = 'onAdClick',
 AD_CLOSED = 'onAdClose',
 AD_REWARDED = 'onAdReward',
 AD_VIDEO_START = 'onVideoPlayBegin',
 AD_COMPLETED = 'onVideoPlayEnd'
}

1.3 效果演示

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

1.4 总结

  • 广告请求:通过 AdLoader 请求广告并处理回调。
  • 广告显示:使用 AdComponent 组件展示广告数据,并通过 interactionListener 监听广告状态。

2.开屏广告

开屏广告是一种在应用启动时且在应用主界面显示之前展示的广告。它分为以下两种类型:

  • 全屏开屏广告:广告覆盖整个屏幕。
  • 半屏开屏广告:广告占据部分屏幕,并可自定义布局,通常会显示广告的图标和版权信息。

2.1 开发步骤

2.1.1 获取OAID

  • OAID(Open Advertising ID)是设备的唯一广告标识符,用于精准推送广告。建议在请求广告时传递 OAID 以提升广告投放的精准度。
  • 获取 OAID 示例代码:
identifier.getOAID().then((data: string) => {
  this.oaid = data;
}).catch((error: BusinessError) => {
  hilog.error(0x0000, 'testTag', 'Failed to get OAID');
});

2.1.2 请求广告

需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener来监听广告的加载状态。测试开屏广告时,需要使用专门的测试广告位来获取测试开屏广告,示例代码中提供了两种开屏广告类型对应的广告位:半屏开屏(图片)(testq6zq98hecj)和全屏开屏(视频)(testd7c5cewoj6),测试广告位ID仅作为调试使用,不可用于广告变现。

请求广告关键参数如下所示:

请求广告参数名 类型 必填 说明
adType number 请求广告类型,开屏广告类型为1。
adId string 广告位ID。如果仅调测广告,可使用测试广告位ID:testq6zq98hecj半屏开屏(图片)和testd7c5cewoj6全屏开屏(视频)。如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建
adCount number 广告数量。
返回广告参数名 类型 说明
isFullScreen boolean 标识返回的广告是否为全屏,true为全屏广告,false为半屏广告。

说明

  1. 如果超时没有请求到广告,应用自行跳转到默认首页。
  2. 为保证开屏展示效果,建议开发者在请求广告前,设置屏幕方向为竖屏。

2.1.3 设置监听回调

  • 通过 AdLoadListener 监听广告加载的回调:
    • onAdLoadFailure:广告加载失败。
    • onAdLoadSuccess:广告加载成功。
const adLoaderListener: advertising.AdLoadListener = {
  onAdLoadFailure: (errorCode: number, errorMsg: string) => {
    hilog.error(0x0000, 'testTag', `Failed to load ad. errorCode: ${errorCode}, errorMsg: ${errorMsg}`);
  },
  onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
    hilog.info(0x0000, 'testTag', 'Ad loaded successfully!');
    // 展示广告
  }
};

2.2 开发使用

2.2.1 请求封装

将请求开屏广告(全屏和半屏)的方法进行封装

import { router } from '@kit.ArkUI';
import { advertising } from '@kit.AdsKit';
import { common } from '@kit.AbilityKit';
import { emitter } from '@kit.BasicServicesKit';


/**
 * 开屏广告
 * 1.视频  2.图片
 */

export enum AdType {
  // 开屏广告的类型
  SPLASH_AD = 1
}

class SplashAdUtil {
  private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
  private isTimeOut: boolean = false;
  // 超时时间(单位毫秒),开发者可根据实际情况修改
  private timeOutDuration: number = 1 * 1000;
  // 超时index
  private timeOutIndex: number = -1;
  // 广告展示参数
  private adDisplayOptions: advertising.AdDisplayOptions = {
    // 是否静音,默认不静音
    mute: false
  }
  // 广告配置
  private adOptions: advertising.AdOptions = {
    // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
    allowMobileTraffic: 0,
    // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
    tagForChildProtection: -1,
    // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
    tagForUnderAgeOfPromise: -1,
    // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
    adContentClassification: 'A'
  }
  // 开屏视频广告请求参数
  private splashVideoAdReqParams: advertising.AdRequestParams = {
    // 'testd7c5cewoj6'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    adId: 'testd7c5cewoj6',
    adType: AdType.SPLASH_AD,
    adCount: 1,
  }
  // 开屏图片广告请求参数
  private splashImageAdReqParams: advertising.AdRequestParams = {
    // 'testq6zq98hecj'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    adId: 'testq6zq98hecj',
    adType: AdType.SPLASH_AD,
    adCount: 1,
  }

  private requestAd(adReqParams: advertising.AdRequestParams, adOptions: advertising.AdOptions): void {
    // 广告请求回调监听
    const adLoaderListener: advertising.AdLoadListener = {
      // 广告请求失败回调
      onAdLoadFailure: (errorCode: number, errorMsg: string) => {
        clearTimeout(this.timeOutIndex);
        if (this.isTimeOut) {
          return;
        }
      },
      // 广告请求成功回调
      onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
        clearTimeout(this.timeOutIndex);
        if (this.isTimeOut) {
          return;
        }
        // 保存请求到的广告内容用于展示
        if (canIUse("SystemCapability.Advertising.Ads")) {
          if (ads[0].adType === AdType.SPLASH_AD) {
            // 调用开屏广告展示页面
            if (ads[0]?.isFullScreen === true) {
              emitter.emit('SplashFullScreenAdPage',
                { data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })

            } else {
              emitter.emit('SplashHalfScreenAdPage',
                { data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })
            }
          } else {

          }
        }
      }
    };
    // 创建AdLoader广告对象
    const load: advertising.AdLoader = new advertising.AdLoader(this.context);
    // 调用广告请求接口
    // adReqParams.oaid = this.oaid;
    this.timeOutHandler();
    load.loadAd(adReqParams, adOptions, adLoaderListener);
  }

  private timeOutHandler(): void {
    this.isTimeOut = false;
    // 超时处理
    this.timeOutIndex = setTimeout(() => {
      this.isTimeOut = true;
      const options: router.RouterOptions = {
        // 开发者可根据项目实际情况修改超时之后要跳转的目标页面
        url: 'pages/Index',
      };
      router.pushUrl(options);
    }, this.timeOutDuration);
  }

  //视频
  splashVideoAd() {
    this.requestAd(this.splashVideoAdReqParams, this.adOptions);
  }

  //图片
  splashImageAd() {
    this.requestAd(this.splashImageAdReqParams, this.adOptions);
  }
}

export const splashAdUtil = new SplashAdUtil()

2.2.2 广告参数传递

当发送广告请求,得到应有的广告参数之后,我们将参数传递给全屏广告或者半屏广告(利用emitter线性通信)

            if (ads[0]?.isFullScreen === true) {
              emitter.emit('SplashFullScreenAdPage',
                { data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })

            } else {
              emitter.emit('SplashHalfScreenAdPage',
                { data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })
            }

2.2.3 开屏(全屏)广告展示

  1. 解释广告请求时间点
  aboutToAppear() {
    emitter.on('SplashFullScreenAdPage', (eventData: emitter.EventData) => {
      const data = eventData.data as Record<string, object>
      this.ads = data['ads'] as Array<advertising.Advertisement>
      this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
      this.isShow = true
    })
    splashAdUtil.splashVideoAd()
  }

  1. 全屏广告页面
import { router } from '@kit.ArkUI';
import { AdComponent, advertising } from '@kit.AdsKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { emitter } from '@kit.BasicServicesKit';
import { splashAdUtil } from '../utils/SplashAdUtil';

const TAG = 'Ads Demo-SplashFullScreenAdPage';

@Entry
@Component
struct SplashFullScreenAdPage {
  private ads: Array<advertising.Advertisement> = [];
  private displayOptions?: advertising.AdDisplayOptions;
  @State isShow: boolean = false

  aboutToAppear() {
    emitter.on('SplashFullScreenAdPage', (eventData: emitter.EventData) => {
      const data = eventData.data as Record<string, object>
      this.ads = data['ads'] as Array<advertising.Advertisement>
      this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
      this.isShow = true
    })
    splashAdUtil.splashVideoAd()
  }

  build() {
    if (this.isShow) {
      Column() {
        // 运行在提供方进程里
        AdComponent({
          ads: this.ads, displayOptions: this.displayOptions,
          interactionListener: {
            onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
              switch (status) {
                case AdStatus.AD_OPEN:
                  hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');

                  break;
                case AdStatus.AD_CLICKED:
                  hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');

                  break;
                case AdStatus.AD_CLOSED:
                  hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
                  router.replaceUrl({
                    url: 'pages/Index',
                  })
                  break;
              }
            }
          }
        })
          .width('100%')
          .height('100%')

      }
      .width('100%')
      .height('100%')
    }

  }
}

export enum AdStatus {
  AD_OPEN = 'onAdOpen',
  AD_CLICKED = 'onAdClick',
  AD_CLOSED = 'onAdClose'
}
  1. 效果展示

    11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

2.2.4 开屏(半屏)广告展示

  1. 解释广告请求时间点
  aboutToAppear() {
    emitter.on('SplashHalfScreenAdPage', (eventData: emitter.EventData) => {
      const data = eventData.data as Record<string, object>
      this.ads = data['ads'] as Array<advertising.Advertisement>
      this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
      this.isShow = true
    })
    splashAdUtil.splashImageAd()
  }
  1. 半屏广告页面

    import { router } from '@kit.ArkUI';
    import { AdComponent, advertising } from '@kit.AdsKit';
    import { splashAdUtil } from '../utils/SplashAdUtil';
    import { emitter } from '@kit.BasicServicesKit';
    
    @Entry
    @Component
    struct SplashHalfScreenAdPage {
      private ads: Array<advertising.Advertisement> = [];
      private displayOptions?: advertising.AdDisplayOptions;
      @State isShow: boolean = false
    
      aboutToAppear() {
        emitter.on('SplashHalfScreenAdPage', (eventData: emitter.EventData) => {
          const data = eventData.data as Record<string, object>
          this.ads = data['ads'] as Array<advertising.Advertisement>
          this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
          this.isShow = true
        })
        splashAdUtil.splashImageAd()
      }
    
      build() {
        if (this.isShow) {
          Column() {
            // 运行在提供方进程里
            AdComponent({
              ads: this.ads, displayOptions: this.displayOptions,
              interactionListener: {
                onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
                  switch (status) {
                    case AdStatus.AD_OPEN:
    
                      break;
                    case AdStatus.AD_CLICKED:
                      break;
                    case AdStatus.AD_CLOSED:
    
                      router.replaceUrl({
                        url: 'pages/Index',
                      })
                      break;
                  }
                }
              }
            })
              .width('100%')
              .height('87%')
    
            // 展示媒体自定义icon、应用名称、版权信息
            Column({}) {
              Text('广告')
            }.width('100%').height('100%')
          }
        }
    
      }
    }
    
    export enum AdStatus {
      AD_OPEN = 'onAdOpen',
      AD_CLICKED = 'onAdClick',
      AD_CLOSED = 'onAdClose'
    }
    
  2. 效果展示

    11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

3.原生广告

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

3.1 广告展示

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

3.2 开发步骤

3.2.1 获取OAID。

若需提升广告推送精准度,可以在请求参数AdRequestParams中添加oaid属性。

如何获取OAID参见获取OAID信息

identifier.getOAID().then((data: string) => {
  this.oaid = data;
}).catch((error: BusinessError) => {
  hilog.error(0x0000, 'testTag', 'Failed to get OAID');
});

3.2.2 请求广告。

请求单广告位广告,需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener,来监听广告的加载状态。

若需提升广告推送精准度,可以在请求参数AdRequestParams中添加oaid属性。

请求广告参数名 类型 必填 说明
adType number 请求广告类型,原生广告类型为3。
adId string 广告位ID。如果仅调测广告,可使用测试广告位ID:testy63txaom86(原生视频),testu7m3hc4gvm(原生大图),testb65czjivt9(原生小图),testr6w14o0hqz(原生三图)。如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建
oaid string 开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。

3.2.3 广告监听

  • 通过 AdLoadListener 监听广告加载的回调:
    • onAdLoadFailure:广告加载失败。
    • onAdLoadSuccess:广告加载成功。
    // 广告请求回调监听
    const adLoaderListener: advertising.AdLoadListener = {
      // 广告请求失败回调
      onAdLoadFailure: (errorCode: number, errorMsg: string) => {
        hilog.error(0x0000, 'testTag', '%{public}s',
          `Failed to request ad, message: ${errorMsg}, error code: ${errorCode}`);
      },
      // 广告请求成功回调
      onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
        hilog.info(0x0000, 'testTag', '%{public}s', `Succeeded in requesting ad`);
        // 调用原生广告展示页面
        promptAction.showToast({ message: '成功·' })
        emitter.emit('NativeAdPage',
          { data: { 'ads': ads, 'adDisplayOptions': adDisplayOptions } })
      }
    };

3.2.4 封装请求

import { advertising } from '@kit.AdsKit';
import { promptAction } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { emitter } from '@kit.BasicServicesKit';

export class NativeAdUtil {
  private ads: Array<advertising.Advertisement> = [];
  private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;

  requestAd() {
    // 广告展示参数
    const adDisplayOptions: advertising.AdDisplayOptions = {
      // 是否静音,默认不静音
      mute: false
    }
    // 原生广告配置
    const adOptions: advertising.AdOptions = {
      // 设置是否请求非个性化广告
      nonPersonalizedAd: 1,
      // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
      allowMobileTraffic: 0,
      // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
      tagForChildProtection: -1,
      // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
      tagForUnderAgeOfPromise: -1,
      // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
      adContentClassification: 'A'
    }
    // 原生广告请求参数
    const nativeVideoAdReqParams: advertising.AdRequestParams = {
      // 'testu7m3hc4gvm'为测试专用的广告位ID,应用正式发布时需要改为正式的广告位ID
      adId: 'testu7m3hc4gvm',
      adType: 3,
      adCount: 1,
      // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
      enableDirectReturnVideoAd: true
    }
    // 广告请求回调监听
    const adLoaderListener: advertising.AdLoadListener = {
      // 广告请求失败回调
      onAdLoadFailure: (errorCode: number, errorMsg: string) => {
        hilog.error(0x0000, 'testTag', '%{public}s',
          `Failed to request ad, message: ${errorMsg}, error code: ${errorCode}`);
      },
      // 广告请求成功回调
      onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
        hilog.info(0x0000, 'testTag', '%{public}s', `Succeeded in requesting ad`);
        // 调用原生广告展示页面
        promptAction.showToast({ message: '成功·' })
        emitter.emit('NativeAdPage',
          { data: { 'ads': ads, 'adDisplayOptions': adDisplayOptions } })
      }
    };
    // 创建AdLoader广告对象
    const load: advertising.AdLoader = new advertising.AdLoader(this.context);
    // 调用广告请求接口
    load.loadAd(nativeVideoAdReqParams, adOptions, adLoaderListener);
  }
}

export const nativeAdUtil = new NativeAdUtil()

3.2.5 封装原生广告组件

  1. 请求广告

     nativeAdUtil.requestAd()
    
  2. 获取广告参数信息

      aboutToAppear() {
        emitter.on('NativeAdPage', (eventData: emitter.EventData) => {
          const data = eventData.data as Record<string, object>
          this.ads = data['ads'] as Array<advertising.Advertisement>
          this.adDisplayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
          this.isShow = true
        })
        nativeAdUtil.requestAd()
      }
    
  3. 广告封装组件

    import { AdComponent, advertising } from '@kit.AdsKit';
    import { emitter } from '@kit.BasicServicesKit';
    import { nativeAdUtil } from '../utils/NativeAdUtil';
    
    @Component
    export struct NativeAdView {
      @State isShow: boolean = false
      @State isShowClose: boolean = false
      // 广告内容
      private ads: Array<advertising.Advertisement> = [];
      private adDisplayOptions: advertising.AdDisplayOptions = {
        // 是否静音,默认不静音
        mute: false
      };
    
      aboutToAppear() {
        emitter.on('NativeAdPage', (eventData: emitter.EventData) => {
          const data = eventData.data as Record<string, object>
          this.ads = data['ads'] as Array<advertising.Advertisement>
          this.adDisplayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
          this.isShow = true
        })
        nativeAdUtil.requestAd()
      }
    
      build() {
        if (this.isShow) {
          Column() {
            AdComponent({
              ads: this.ads,
              displayOptions: this.adDisplayOptions,
              interactionListener: {
                onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
                  switch (status) {
                    case AdStatus.AD_OPEN:
                      this.isShowClose = true
                      break;
                    case AdStatus.AD_CLICKED:
                      break;
                    case AdStatus.AD_CLOSED:
                      this.isShowClose = false
                      this.isShow = false
                      break;
                    default:
                  }
                }
              }
            })
              .width('100%')
            if (this.isShowClose) {
              Row() {
                Text('关闭')
                  .fontSize(12)
                  .onClick(() => {
                    this.isShow = false
                  })
              }
              .width('100%')
            }
          }
        }
    
      }
    }
    
    enum AdStatus {
      AD_OPEN = 'onAdOpen',
      AD_CLICKED = 'onAdClick',
      AD_CLOSED = 'onAdClose'
    }
    
  4. 效果展示

    11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

4. 插屏广告

插屏广告是一种在应用开启、暂停或退出时以全屏或半屏的形式弹出的广告形式,展示时机巧妙避开用户对应用的正常体验,尺寸大,曝光效果好。

4.1 广告展示

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

4.2 订阅广告监听

开发者需要在App中订阅com.huawei.hms.pps.action.PPS_INTERSTITIAL_STATUS_CHANGED事件来监听插屏广告页面变化并接收插屏信息。示例代码中的订阅方法registerPPSReceiver()需要在每次展示广告前调用 。
在订阅到公共事件后,可以从CommonEventData的parameters参数中使用"interstitial_ad_status"作为key值获取插屏广告页面变化状态。

import { BusinessError, commonEventManager } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const KEY_INTERSTITIAL_STATUS = 'interstitial_ad_status';

export class InterstitialAdUtil {
  // 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
  private subscriber: commonEventManager.CommonEventSubscriber | null = null;

  // 订阅方法,需要在每次展示广告前调用
  public registerPPSReceiver(): void {
    if (this.subscriber) {
      this.unRegisterPPSReceiver();
    }
    // 订阅者信息
    const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
      events: ['com.huawei.hms.pps.action.PPS_INTERSTITIAL_STATUS_CHANGED'],
      publisherBundleName: 'com.huawei.hms.adsservice'
    };
    // 创建订阅者回调
    commonEventManager.createSubscriber(subscribeInfo,
      (err: BusinessError, commonEventSubscriber: commonEventManager.CommonEventSubscriber) => {
        if (err) {
          hilog.error(0x0000, 'testTag', '%{public}s', `CreateSubscriber error, ${err.code}, message: ${err.message}}`);
          return;
        }
        hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in creating subscriber');
        this.subscriber = commonEventSubscriber;
        // 订阅公共事件回调
        if (!this.subscriber) {
          hilog.warn(0x0000, 'testTag', '%{public}s', 'Need to create subscriber');
          return;
        }
        commonEventManager.subscribe(this.subscriber,
          (err: BusinessError, commonEventData: commonEventManager.CommonEventData) => {
            if (err) {
              hilog.error(0x0000, 'testTag', '%{public}s', `Subscribe error, ${err.code}, message: ${err.message}`);
            } else {
              // 订阅者成功接收到公共事件
              // 获取插屏广告页面变化状态
              const status: string = commonEventData?.parameters?.[KEY_INTERSTITIAL_STATUS];
              switch (status) {
                case AdStatus.AD_OPEN:
                  console.info('onAdOpen');
                  break;
                case AdStatus.AD_CLICKED:
                  console.info('onAdClick');
                  break;
                case AdStatus.AD_CLOSED:
                  console.info('onAdClose');
                  this.unRegisterPPSReceiver();
                  break;
                case AdStatus.AD_VIDEO_START:
                  console.info('onAdVideoStart');
                  break;
                case AdStatus.AD_COMPLETED:
                  console.info('onAdCompleted');
                  break;
                default:
                  break;
              }
            }
          });
      });
  }

  // 取消订阅
  public unRegisterPPSReceiver(): void {
    commonEventManager.unsubscribe(this.subscriber, (err: BusinessError) => {
      if (err) {
        hilog.error(0x0000, 'testTag', '%{public}s', `Unsubscribe error, ${err.code}, message: ${err.message}}`);
      } else {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in unsubscribing');
        this.subscriber = null;
      }
    });
  }
}

export const InterstitialAd = new InterstitialAdUtil()

enum AdStatus {
  AD_OPEN = 'onAdOpen',
  AD_CLICKED = 'onAdClick',
  AD_CLOSED = 'onAdClose',
  AD_VIDEO_START = 'onVideoPlayBegin',
  AD_COMPLETED = 'onVideoPlayEnd'
}

4.3 开发使用

4.3.1 请求广告

private requestAd(adLoader: advertising.AdLoader): void {
    const adRequestParam: advertising.AdRequestParams = {
      // 广告类型:插屏广告
      adType: 12,
      // 'testb4znbuh3n2'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
      adId: 'testb4znbuh3n2',
      // 开放匿名设备标识符
      oaid: this.oaid
    };
    const adOption: advertising.AdOptions = {
      // 设置是否请求非个性化广告
      nonPersonalizedAd: 0,
      // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
      allowMobileTraffic: 0,
      // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
      tagForChildProtection: -1,
      // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
      tagForUnderAgeOfPromise: -1,
      // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
      adContentClassification: 'A'
    };
    const adLoaderListener: advertising.AdLoadListener = {
      onAdLoadFailure: (errorCode: number, errorMsg: string) => {
        hilog.error(0x0000, 'testTag', '%{public}s',
          `Failed to request ad, message: ${errorMsg}, error code: ${errorCode}`);
      },
      onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in requesting ad!');
        this.ads = [];
        this.ads.push(...ads);
      },
    };
    adLoader.loadAd(adRequestParam, adOption, adLoaderListener);
  }

4.3.2 展示广告

  1. 展示时期

由于我们不清楚广告参数什么时候请求成功,我们可以监听存储广告参数的数组ads,当ads的长度不为空时,就可以展示广告advertising.showAd

import { advertising, identifier } from '@kit.AdsKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct Index {
  private ads: Array<advertising.Advertisement> = [];
  private context = getContext(this) as common.UIAbilityContext;
  private oaid: string = '';
  private displayOptions: advertising.AdDisplayOptions = {
    // 插屏广告视频播放是否静音
    mute: true
  };
  @State index: number = 0

  aboutToAppear() {
    try {
      // 使用Promise回调方式获取OAID
      identifier.getOAID().then((data) => {
        this.oaid = data;
        hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in getting adsIdentifierInfo by promise');
      }).catch((error: BusinessError) => {
        hilog.error(0x0000, 'testTag', '%{public}s', `Failed to get adsIdentifierInfo, message: ${error.message}`);
      })
    } catch (error) {
      hilog.error(0x0000, 'testTag', '%{public}s', `Catch err, code: ${error.code}, message: ${error.message}`);
    }
    let load: advertising.AdLoader = new advertising.AdLoader(this.context);
    this.requestAd(load);

    //监听广告数组长度来判断广告的出现时期
    this.showAd()

  }

  build() {
    Column() {

    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  private showAd() {
    // 请在此处自行增加步骤3中的,注册插屏广告状态监听器
    // ...
    // InterstitialAd.registerPPSReceiver()
    // 此处ads[0]表示请求到的第一个广告,用户根据实际情况选择
    advertising.showAd(this.ads[0], this.displayOptions, this.context);
  }

  private requestAd(adLoader: advertising.AdLoader): void {
    const adRequestParam: advertising.AdRequestParams = {
      // 广告类型:插屏广告
      adType: 12,
      // 'testb4znbuh3n2'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
      adId: 'testb4znbuh3n2',
      // 开放匿名设备标识符
      oaid: this.oaid
    };
    const adOption: advertising.AdOptions = {
      // 设置是否请求非个性化广告
      nonPersonalizedAd: 0,
      // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
      allowMobileTraffic: 0,
      // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
      tagForChildProtection: -1,
      // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
      tagForUnderAgeOfPromise: -1,
      // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
      adContentClassification: 'A'
    };
    const adLoaderListener: advertising.AdLoadListener = {
      onAdLoadFailure: (errorCode: number, errorMsg: string) => {
        hilog.error(0x0000, 'testTag', '%{public}s',
          `Failed to request ad, message: ${errorMsg}, error code: ${errorCode}`);
      },
      onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in requesting ad!');
        this.ads = [];
        this.ads.push(...ads);
      },
    };
    adLoader.loadAd(adRequestParam, adOption, adLoaderListener);
  }
}
  1. 效果展示

    11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

如何获取资料

获取资料的途径,可以关注我们 官网的公众号 青蓝逐码 ,输入 项目名称 《自然壁纸》 即可获得以上资料。

关于我们

关于青蓝逐码组织

如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯甚至你想要做出一款属于自己的应用!欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。

11-自然壁纸实战教程-接入鲸鸿动能广告-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
收藏
回复
举报
回复
    相关推荐