HarmonyOS 鸿蒙Next 打造开放、合规的广告生态 - 贴片广告

发布于 1周前 作者 yibo5220 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 打造开放、合规的广告生态 - 贴片广告 场景介绍

贴片广告是一种在视频播放前、视频播放中或视频播放结束后插入的视频或图片广告。

接口说明

接口名 描述
loadAd(adParam: AdRequestParams, adOptions: AdOptions, listener: AdLoadListener): void 请求单广告位广告,通过AdRequestParams、AdOptions进行广告请求参数设置,通过AdLoadListener监听广告请求回调。
AdComponent(ads: advertising.Advertisement[], displayOptions: advertising.AdDisplayOptions, interactionListener: advertising.AdInteractionListener, @BuilderParam adRenderer?: () => void): void 展示广告,通过AdDisplayOptions进行广告展示参数设置,通过AdInteractionListener监听广告状态回调。

开发步骤

  1. 获取OAID。

    如果想要为用户更精准的推送广告,可以在请求参数AdRequestParams中添加oaid属性。

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

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

  2. 请求单广告位广告。

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

    在请求贴片广告时,需要在AdOptions中设置两个参数:totalDuration和placementAdCountDownDesc。

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

    请求广告参数名 类型 必填 说明
    adType number 请求广告类型,贴片广告类型为60。
    adId string 广告位ID。
    oaid string 开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。

    示例代码如下所示:

    import { advertising, identifier } from '[@kit](/user/kit).AdsKit';
    import { common } from '[@kit](/user/kit).AbilityKit';
    import { hilog } from '[@kit](/user/kit).PerformanceAnalysisKit';
    import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
    import { router } from '[@kit](/user/kit).ArkUI';
    
    [@Entry](/user/Entry)
    [@Component](/user/Component)
    struct Index {
      private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
      // 获取到的OAID
      private oaid: string = '';
    
      aboutToAppear() {
        try {
          // 使用Promise回调方式获取OAID
          identifier.getOAID().then((data: string) => {
            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, code: ${error.code}, message: ${error.message}`);
          })
        } catch (error) {
          hilog.error(0x0000, 'testTag', '%{public}s', `Catch err, code: ${error.code}, message: ${error.message}`);
        }
      }
    
      build() {
        Row() {
          Button('加载广告', { type: ButtonType.Normal, stateEffect: true })
          .onClick(() => {
            // 调用加载广告方法
            requestAd(this.context, this.oaid);
          })
          .borderRadius(8)
          .backgroundColor(0x317aff)
          .width(90)
          .height(40)
        }
        .height('100%')
      }
    }
    
    /**
    * 加载广告
    *
    * [@param](/user/param) context 上下文环境
    * [@param](/user/param) oaid OAID信息
    */
    function requestAd(context: common.Context, oaid: string): void {
      const adRequestParam: advertising.AdRequestParams = {
        // 广告类型
        adType: 60,
        // 'testy3cglm3pj0'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
        adId: 'testy3cglm3pj0',
        // 在AdRequestParams中添加oaid参数
        oaid: oaid,
        // 用于区分普通请求和预加载请求,默认值false代表普通请求,true代表预加载请求
        isPreload: false
      };
      const adOptions: advertising.AdOptions = {
        // 在AdOptions中添加totalDuration参数,用于设置贴片广告展示时长(贴片广告必填)
        totalDuration: 30,
        // 在AdOptions中添加placementAdCountDownDesc参数,设置贴片广告倒计时文案(可选,填写了则展示文案,不填写则只展示倒计时)
        placementAdCountDownDesc: encodeURI('VIP免广告'),
        // 是否允许流量下载 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 single ad, errorCode is: ${errorCode}, errorMsg is: ${errorMsg}`);
        },
        // 广告请求成功回调
        onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
          hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in requesting single ad!');
          // 保存请求到的广告内容用于展示
          const returnAds = ads;
          // 路由到广告展示页面
          routePage('pages/PlacementAdPage', returnAds);
        }
      };
      // 创建AdLoader广告对象
      const load: advertising.AdLoader = new advertising.AdLoader(context);
      // 调用广告请求接口
      hilog.info(0x0000, 'testTag', '%{public}s', 'Request single ad!');
      load.loadAd(adRequestParam, adOptions, adLoaderListener);
    }
    
    /**
    * 路由跳转
    *
    * [@param](/user/param) pageUri 要路由到的页面
    */
    async function routePage(pageUri: string, ads: Array<advertising.Advertisement | null>) {
      let options: router.RouterOptions = {
        url: pageUri,
        params: {
          ads: ads
        }
      }
      try {
        hilog.info(0x0000, 'testTag', '%{public}s', `RoutePage: ${pageUri}`);
        router.pushUrl(options);
      } catch (error) {
        hilog.error(0x0000, 'testTag', '%{public}s',
          `Failed to routePage callback, code: ${error.code}, msg: ${error.message}`);
      }
    }
    
  3. 展示广告。

    在您的页面中使用AdComponent组件展示贴片广告,由媒体判断流量场景下,可以自动播放则展示广告,反之则不展示。以前贴广告为例,前贴广告播放完成后进入正片播放。您需要在entry/src/main/resources/base/profile/main_pages.json文件中添加页面,如下图所示。

    您需要在media和rawfile目录下分别指定正片未播放时的预览图video_preview.PNG和对应的正片文件videoTest.mp4,如下图所示。

    示例代码如下所示:

    import { router, window } from '[@kit](/user/kit).ArkUI';
    import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
    import { advertising, AdComponent } from '[@kit](/user/kit).AdsKit';
    import { hilog } from '[@kit](/user/kit).PerformanceAnalysisKit';
    
    [@Entry](/user/Entry)
    [@Component](/user/Component)
    export struct PlacementAdPage {
      // 是否竖屏
      private portrait: boolean = true;
      // 请求到的广告内容
      private ads: Array<advertising.Advertisement> = [];
      // 广告展示参数
      private adDisplayOptions: advertising.AdDisplayOptions = {
        // 是否静音,默认不静音
        mute: false
      }
      // 广告参数
      private adOptions: advertising.AdOptions = {
        // 设置贴片广告展示时长(贴片广告必填)
        totalDuration: 30,
        // 设置贴片广告倒计时文案,文案需要使用encodeURI编码(可选,填写了则展示文案,不填写则只展示倒计时)
        placementAdCountDownDesc: encodeURI('VIP免广告'),
        // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
        tagForChildProtection: -1,
        // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
        tagForUnderAgeOfPromise: -1,
        // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
        adContentClassification: 'A'
      }
      // 已经播放的贴片广告数量
      private playedAdSize: number = 0;
      // 是否播放正片
      @State isPlayVideo: boolean = false;
      // 视频播放控制器
      private controller: VideoController = new VideoController();
      // 指定视频未播放时的预览图片路径
      private previewUris: Resource = $r('app.media.video_preview');
      // 指定视频播放源的路径,这里取本地视频资源
      private innerResource: Resource = $rawfile('videoTest.mp4');
      // 用于渲染右上角倒计时
      private countDownTxtPlaceholder: string = '%d | %s';
      @State countDownTxt: string = '';
    
      aboutToAppear() {
        const params: Record<string, Object> = router.getParams() as Record<string, Object>;
        if (params && params.ads as Array<advertising.Advertisement>) {
          this.ads = params.ads as Array<advertising.Advertisement>;
          this.adOptions = params.adOptions as advertising.AdOptions;
          this.initData();
        }
      }
    
      build() {
        Stack({ alignContent: Alignment.TopEnd }) {
          // AdComponent组件用于展示非全屏广告
          AdComponent({
            ads: this.ads, displayOptions: this.adDisplayOptions,
            interactionListener: {
              // 广告状态变化回调
              onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
                switch (status) {
                  case 'onPortrait':
                    hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onPortrait');
                    // 设置屏幕方向为竖屏或返回上一页
                    this.setWindowPortrait();
                    break;
                  case 'onLandscape':
                    hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onLandscape');
                    // 设置屏幕方向为横屏
                    this.setWindowLandscape();
                    break;
                  case 'onMediaProgress':
                    hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onMediaProgress');
                    break;
                  case 'onMediaStart':
                    hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onMediaStart');
                    break;
                  case 'onMediaPause':
                    hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onMediaPause');
                    break;
                  case 'onMediaStop':
                    hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onMediaStop');
                    break;
                  case 'onMediaComplete':
                    hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onMediaComplete');
                    // 所有广告都播放完毕后,开始播放正片
                    this.playedAdSize++;
                    if (this.playedAdSize === this.ads.length) {
                      this.isPlayVideo = true;
                    }
                    break;
                  case 'onMediaError':
                    hilog.error(0x0000, 'testTag', '%{public}s', 'Status is onMediaError');
                    break;
                  case 'onMediaCountdown':
                    try {
                      hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onMediaCountdown');
                      const parseData: Record<string, number> = JSON.parse(JSON.stringify(data));
                      this.updateCountDownTxt(parseData.countdownTime);
                    } catch (e) {
                      hilog.error(0x0000, 'testTag', '%{public}s',
                        `Failed to parse data, code: ${e.code}, msg: ${e.message}`);
                    }
                    break;
                }
              }
            }
          })
          .visibility(!this.isPlayVideo ? Visibility.Visible : Visibility.None)
          .width('100%')
          .height('100%')
    
          Row() {
            if (this.countDownTxt) {
              Text(this.countDownTxt.split('').join('\u200B'))
              .fontSize(12)
              .textAlign(TextAlign.Center)
              .maxLines(1)
              .fontColor(Color.White)
              .lineHeight(12)
              .textOverflow({ overflow: TextOverflow.Ellipsis })
              .maxLines(1)
              .backgroundColor('#66000000')
              .border({ radius: 25 })
              .padding({
                left: 8,
                right: 8,
                top: 6,
                bottom: 6
              })
              .margin({ right: 16, top: 16 })
              .height(24)
              .constraintSize({ minWidth: 60, maxWidth: 100 })
              .onClick((event: ClickEvent) => {
                hilog.info(0x0000, 'testTag', '%{public}s', 'OnVipClicked, do something...');
              })
            }
          }
          .alignItems(VerticalAlign.Top)
          .justifyContent(FlexAlign.End)
    
          Video({
            src: this.innerResource,
            previewUri: this.previewUris,
            controller: this.controller
          })
          .visibility(this.isPlayVideo ? Visibility.Visible : Visibility.None)
          .autoPlay(this.isPlayVideo ? true : false)
          .controls(false)
          .width('100%')
          .height('100%')
        }
        .width('100%')
        .height('100%')
      }
    
      /** 设置竖屏或返回上一页 */
      private setWindowPortrait() {
        hilog.info(0x0000, 'testTag', '%{public}s', `Set WindowPortrait, portrait: ${this.portrait}`);
        if (!this.portrait) {
          window.getLastWindow(getContext(this), (err: BusinessError, win) => {
            win.setPreferredOrientation(window.Orientation.PORTRAIT)
          });
          this.portrait = true;
        } else {
          router.back();
        }
      }
    
      /** 设置横屏(正向) */
      private setWindowLandscape() {
        hilog.info(0x0000, 'testTag', '%{public}s', `Set WindowLandscape, portrait: ${this.portrait}`);
        if (this.portrait) {
          window.getLastWindow(getContext(this), (err: BusinessError, win) => {
            win.setPreferredOrientation(window.Orientation.LANDSCAPE)
          });
          this.portrait = false;
        }
      }
    
      private initData() {
        this.initCountDownText();
      }
    
      private initCountDownText() {
        const decodeText = this.decodeString(this.adOptions?.placementAdCountDownDesc as string);
        if (!this.isBlank(decodeText)) {
          this.countDownTxtPlaceholder = this.countDownTxtPlaceholder.replace('%s', decodeText);
        } else {
          this.countDownTxtPlaceholder = '%d';
        }
      }
    
      private updateCountDownTxt(leftTime: number) {
        hilog.info(0x0000, 'testTag', '%{public}s', `Show LeftTime: ${leftTime}`);
        this.countDownTxt = this.countDownTxtPlaceholder.replace('%d', leftTime + '');
      }
    
      private decodeString(str: string): string {
        if (!str) {
          return str;
        }
        let decodeUrl = str;
        try {
          decodeUrl = decodeURIComponent(str.replace(/\+/g, '%20'));
        } catch (e) {
          hilog.error(0x0000, 'testTag', '%{public}s', `Failed to decodeURIComponent, code:${e.code}, msg: ${e.message}`);
        }
        return decodeUrl;
      }
    
      private isBlank(str: string): boolean {
        if (str === null || str === undefined) {
          return true;
        }
        if (typeof str === 'string') {
          return str.trim().length === 0;
        }
        return false;
      }
    }
    

更多关于HarmonyOS 鸿蒙Next 打造开放、合规的广告生态 - 贴片广告的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next 打造开放、合规的广告生态 - 贴片广告的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对帖子标题“HarmonyOS 鸿蒙Next 打造开放、合规的广告生态 - 贴片广告”,以下是对鸿蒙在广告生态,特别是贴片广告方面的专业回答:

HarmonyOS 鸿蒙Next在广告生态的构建上,致力于打造一个开放且合规的环境。贴片广告作为其中的一部分,将遵循严格的规范和标准。

鸿蒙系统通过其强大的技术架构和生态管理能力,为贴片广告提供了高效、安全的展示平台。广告主可以在鸿蒙生态中轻松投放广告,而用户则能在合规的前提下接收到相关广告信息。

在贴片广告的具体实现上,鸿蒙系统可能会采用智能算法来匹配广告内容与用户兴趣,从而提升广告的转化率和用户体验。同时,鸿蒙也会严格监管广告内容,确保其符合相关法律法规和道德规范,避免不良信息的传播。

此外,鸿蒙系统还提供了丰富的广告形式和投放策略,以满足不同广告主的需求。广告主可以根据自己的目标和预算,在鸿蒙生态中选择最适合自己的广告形式进行投放。

总之,HarmonyOS 鸿蒙Next在打造开放、合规的广告生态方面,通过贴片广告等形式的创新和实践,正在为用户和广告主创造更加优质、高效的互动体验。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html,

回到顶部