华为HarmonyOS打造开放、合规的广告生态 - 开屏广告

场景介绍

开屏广告是一种在应用启动时且在应用主界面显示之前需要被展示的广告。您需要预先为App设计一张开屏默认的Slogan图片,确保在未获得到开屏广告之前展示默认的Slogan,提供良好的用户体验。

开屏广告分为全屏开屏广告、半屏开屏广告,其中全屏开屏广告展示形式为广告铺满整个页面;半屏开屏广告展示形式会根据媒体页面自定义布局渲染广告、icon和版权信息,一般情况下建议将icon和版权信息展示在广告下方。

接口说明

接口名 描述
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来监听广告的加载状态。测试开屏广告时,需要使用专门的测试广告位来获取测试开屏广告,示例代码中提供了两种开屏广告类型对应的广告位:半屏开屏(图片)(testq6zq98hecj)和全屏开屏(视频)(testd7c5cewoj6),测试广告位ID仅作为调试使用,不可用于广告变现。

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

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

    示例代码如下所示:

    说明

    请求广告之前需要展示默认的Slogan图片,在请求广告时,在onAdLoadSuccess回调中切换展示广告页面。如果超时没有请求到广告,应用自行跳到默认首页。

    复制代码
    1. import { router, Prompt } from '@kit.ArkUI';
    2. import { advertising, identifier } from '@kit.AdsKit';
    3. import { common } from '@kit.AbilityKit';
    4. import { hilog } from '@kit.PerformanceAnalysisKit';
    5. import { BusinessError } from '@kit.BasicServicesKit';
    6. @Entry
    7. @Component
    8. export struct Index {
    9. private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
    10. private oaid: string = '';
    11. // 广告展示参数
    12. private adDisplayOptions: advertising.AdDisplayOptions = {
    13. // 是否静音,默认不静音
    14. mute: false
    15. }
    16. // 广告配置
    17. private adOptions: advertising.AdOptions = {
    18. // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
    19. allowMobileTraffic: 0,
    20. // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
    21. tagForChildProtection: -1,
    22. // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
    23. tagForUnderAgeOfPromise: -1,
    24. // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
    25. adContentClassification: 'A'
    26. }
    27. // 开屏视频广告请求参数
    28. private splashVideoAdReqParams: advertising.AdRequestParams = {
    29. // 'testd7c5cewoj6'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    30. adId: 'testd7c5cewoj6',
    31. adType: AdType.SPLASH_AD,
    32. adCount: 1,
    33. oaid: this.oaid
    34. }
    35. // 开屏图片广告请求参数
    36. private splashImageAdReqParams: advertising.AdRequestParams = {
    37. // 'testq6zq98hecj'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    38. adId: 'testq6zq98hecj',
    39. adType: AdType.SPLASH_AD,
    40. adCount: 1,
    41. oaid: this.oaid
    42. }
    43. aboutToAppear() {
    44. hilog.info(0x0000, 'testTag', '%{public}s', 'Start to aboutToAppear');
    45. try {
    46. // 使用Promise回调方式获取OAID
    47. identifier.getOAID().then((data: string) => {
    48. this.oaid = data;
    49. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in getting adsIdentifierInfo by promise');
    50. }).catch((error: BusinessError) => {
    51. hilog.error(0x0000, 'testTag', '%{public}s',
    52. `Failed to get adsIdentifierInfo, code: ${error.code}, message: ${error.message}`);
    53. })
    54. } catch (error) {
    55. hilog.error(0x0000, 'testTag', '%{public}s', `Catch err, code: ${error.code}, message: ${error.message}`);
    56. }
    57. }
    58. build() {
    59. Column() {
    60. Column() {
    61. // 跳转到开屏全屏视频广告展示页面
    62. CustomButton({
    63. mText: 'splash full screen request', mOnClick: () => {
    64. this.requestAd(this.splashVideoAdReqParams, this.adOptions);
    65. }
    66. });
    67. // 跳转到开屏半屏图片广告展示页面
    68. CustomButton({
    69. mText: 'splash half screen request', mOnClick: () => {
    70. this.requestAd(this.splashImageAdReqParams, this.adOptions);
    71. }
    72. });
    73. }.width('100%').height('80%').justifyContent(FlexAlign.Center)
    74. }
    75. .width('100%')
    76. .height('100%')
    77. }
    78. private requestAd(adReqParams: advertising.AdRequestParams, adOptions: advertising.AdOptions): void {
    79. // 广告请求回调监听
    80. const adLoaderListener: advertising.AdLoadListener = {
    81. // 广告请求失败回调
    82. onAdLoadFailure: (errorCode: number, errorMsg: string) => {
    83. hilog.error(0x0000, 'testTag', '%{public}s',
    84. `Failed to request ad. errorCode is: ${errorCode}, errorMsg is: ${errorMsg}`);
    85. Prompt.showToast({
    86. message: `Failed to request ad, code is: ${errorCode} , errorMsg is: ${errorMsg}`,
    87. duration: 1000
    88. });
    89. },
    90. // 广告请求成功回调
    91. onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
    92. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in requesting ad!');
    93. // 保存请求到的广告内容用于展示
    94. hilog.info(0x0000, 'testTag', '%{public}s', `ads[0].adType is : ${ads[0].adType}`);
    95. if (canIUse("SystemCapability.Advertising.Ads")) {
    96. if (ads[0].adType === AdType.SPLASH_AD) {
    97. // 调用开屏广告展示页面
    98. if (ads[0]?.isFullScreen === true) {
    99. routePage('pages/SplashFullScreenAdPage', ads, this.adDisplayOptions);
    100. } else {
    101. routePage('pages/SplashHalfScreenAdPage', ads, this.adDisplayOptions);
    102. }
    103. } else {
    104. hilog.error(0x0000, 'testTag', '%{public}s', 'Error adType');
    105. }
    106. }
    107. }
    108. };
    109. // 创建AdLoader广告对象
    110. const load: advertising.AdLoader = new advertising.AdLoader(this.context);
    111. // 调用广告请求接口
    112. hilog.info(0x0000, 'testTag', '%{public}s', 'Request ad!');
    113. adReqParams.oaid = this.oaid;
    114. load.loadAd(adReqParams, adOptions, adLoaderListener);
    115. }
    116. }
    117. async function routePage(pageUri: string, ads: Array<advertising.Advertisement | null>,
    118. displayOptions: advertising.AdDisplayOptions) {
    119. let options: router.RouterOptions = {
    120. url: pageUri,
    121. params: {
    122. ads: ads,
    123. displayOptions: displayOptions
    124. }
    125. }
    126. try {
    127. hilog.info(0x0000, 'testTag', '%{public}s', `RoutePage: ${pageUri}`);
    128. router.pushUrl(options);
    129. } catch (error) {
    130. hilog.error(0x0000, 'testTag', '%{public}s',
    131. `Failed to routePage callback, code: ${error.code}, msg: ${error.message}`);
    132. }
    133. }
    134. export enum AdType {
    135. // 开屏广告的类型
    136. SPLASH_AD = 1
    137. }
    138. @Component
    139. export struct CustomButton {
    140. private mText: string | Resource = '';
    141. private mHeight: number = 40;
    142. private mOnClick: (event?: ClickEvent) => void = (): void => {
    143. };
    144. build() {
    145. Column() {
    146. Button(this.mText)
    147. .backgroundColor('#d3d4d6')
    148. .fontSize(20)
    149. .fontColor('#000')
    150. .fontWeight(FontWeight.Normal)
    151. .align(Alignment.Center)
    152. .type(ButtonType.Capsule)
    153. .width('90%')
    154. .height(this.mHeight)
    155. .margin({ top: 10, bottom: 5 })
    156. .onClick(this.mOnClick);
    157. }
    158. }
    159. }
  3. 展示广告。

    说明

    1、由在步骤2请求广告中获取的isFullScreen参数判断展示全屏或者半屏广告,同时媒体可在AdComponent中绘制自身的半屏部分,可参考展示半屏代码。

    2、在枚举的AdStatus状态中,媒体可根据各种状态来进行下一步操作,如在AD_CLOSED时展示首页。

    3、目前只支持展示竖屏广告。

    在您的页面中使用AdComponent组件展示开屏广告。示例代码如下所示:

    您需要在entry/src/main/resources/base/profile/main_pages.json文件中添加页面,如下图所示。

    展示半屏广告:

    复制代码
    1. import { Prompt, router } from '@kit.ArkUI';
    2. import { advertising, AdComponent } from '@kit.AdsKit';
    3. import { hilog } from '@kit.PerformanceAnalysisKit';
    4. @Entry
    5. @Component
    6. export struct SplashHalfScreenAdPage {
    7. private ads: Array<advertising.Advertisement> = [];
    8. private displayOptions?: advertising.AdDisplayOptions;
    9. aboutToAppear() {
    10. hilog.info(0x0000, 'testTag', '%{public}s', 'Start to splashHalfScreenAdPage aboutToAppear');
    11. const params: Record<string, Object> = router.getParams() as Record<string, Object>;
    12. if (params && params.ads as Array<advertising.Advertisement> &&
    13. params.displayOptions as advertising.AdDisplayOptions) {
    14. this.ads = params.ads as Array<advertising.Advertisement>;
    15. this.displayOptions = params.displayOptions as advertising.AdDisplayOptions;
    16. } else {
    17. hilog.info(0x0000, 'testTag', '%{public}s', 'Router params are empty');
    18. }
    19. }
    20. build() {
    21. Column() {
    22. // 运行在提供方进程里
    23. AdComponent({
    24. ads: this.ads, displayOptions: this.displayOptions,
    25. interactionListener: {
    26. onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
    27. switch (status) {
    28. case AdStatus.AD_OPEN:
    29. hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');
    30. Prompt.showToast({
    31. message: 'splash ad open',
    32. duration: 1000
    33. });
    34. break;
    35. case AdStatus.AD_CLICKED:
    36. hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');
    37. Prompt.showToast({
    38. message: 'splash ad click',
    39. duration: 1000
    40. });
    41. break;
    42. case AdStatus.AD_CLOSED:
    43. hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
    44. Prompt.showToast({
    45. message: 'splash ad close',
    46. duration: 1000
    47. });
    48. router.replaceUrl({
    49. url: 'pages/Index',
    50. })
    51. break;
    52. }
    53. }
    54. }
    55. })
    56. .width('100%')
    57. .height('87%')
    58. // 展示媒体自定义icon、应用名称、版权信息
    59. Column({}) {
    60. Row() {
    61. Image($r('app.media.video')).width(24).height(24).margin({ right: 8 })
    62. Text($r('app.string.video')).fontColor('#1A1A1A').fontSize(16).width(32).height(21)
    63. }.margin({ bottom: 8 })
    64. Column() {
    65. Text($r('app.string.copyright')).fontColor('#1A1A1A').fontSize(9).height(15)
    66. }
    67. }.width('100%').height('100%')
    68. }
    69. }
    70. }
    71. export enum AdStatus {
    72. AD_OPEN = 'onAdOpen',
    73. AD_CLICKED = 'onAdClick',
    74. AD_CLOSED = 'onAdClose'
    75. }

    展示全屏广告:

    复制代码
    1. import { Prompt, router } from '@kit.ArkUI';
    2. import { advertising, AdComponent } from '@kit.AdsKit';
    3. import { hilog } from '@kit.PerformanceAnalysisKit';
    4. const TAG = 'Ads Demo-SplashFullScreenAdPage';
    5. @Entry
    6. @Component
    7. export struct SplashFullScreenAdPage {
    8. private ads: Array<advertising.Advertisement> = [];
    9. private displayOptions?: advertising.AdDisplayOptions;
    10. aboutToAppear() {
    11. hilog.info(0x0000, 'testTag', '%{public}s', 'Start to splashFullScreenAdPage aboutToAppear');
    12. const params: Record<string, Object> = router.getParams() as Record<string, Object>;
    13. if (params && params.ads as Array<advertising.Advertisement> &&
    14. params.displayOptions as advertising.AdDisplayOptions) {
    15. this.ads = params.ads as Array<advertising.Advertisement>;
    16. this.displayOptions = params.displayOptions as advertising.AdDisplayOptions;
    17. } else {
    18. hilog.info(0x0000, 'testTag', '%{public}s', 'Router params are empty');
    19. }
    20. }
    21. build() {
    22. Column() {
    23. // 运行在提供方进程里
    24. AdComponent({
    25. ads: this.ads, displayOptions: this.displayOptions,
    26. interactionListener: {
    27. onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
    28. switch (status) {
    29. case AdStatus.AD_OPEN:
    30. hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');
    31. Prompt.showToast({
    32. message: 'splash ad open',
    33. duration: 1000
    34. });
    35. break;
    36. case AdStatus.AD_CLICKED:
    37. hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');
    38. Prompt.showToast({
    39. message: 'splash ad click',
    40. duration: 1000
    41. });
    42. break;
    43. case AdStatus.AD_CLOSED:
    44. hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
    45. Prompt.showToast({
    46. message: 'splash ad close',
    47. duration: 1000
    48. });
    49. router.replaceUrl({
    50. url: 'pages/Index',
    51. })
    52. break;
    53. }
    54. }
    55. }
    56. })
    57. .width('100%')
    58. .height('100%')
    59. }.width('100%').height('100%')
    60. }
    61. }
    62. export enum AdStatus {
    63. AD_OPEN = 'onAdOpen',
    64. AD_CLICKED = 'onAdClick',
    65. AD_CLOSED = 'onAdClose'
    66. }
相关推荐
SoraLuna41 分钟前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
AORO_BEIDOU4 小时前
单北斗+鸿蒙系统+国产芯片,遨游防爆手机自主可控“三保险”
华为·智能手机·harmonyos
博览鸿蒙6 小时前
鸿蒙操作系统(HarmonyOS)的应用开发入门
华为·harmonyos
Damon小智13 小时前
HarmonyOS NEXT 技术实践-基于基础视觉服务的多目标识别
华为·harmonyos
匹马夕阳15 小时前
华为笔记本之糟糕的体验
华为·笔记本电脑
egekm_sefg15 小时前
华为、华三交换机纯Web下如何创关键VLANIF、操作STP参数
网络·华为
岳不谢1 天前
华为DHCP高级配置学习笔记
网络·笔记·网络协议·学习·华为
爱笑的眼睛111 天前
uniapp 极速上手鸿蒙开发
华为·uni-app·harmonyos
K.P1 天前
鸿蒙元服务从0到上架【第三篇】(第二招有捷径)
华为·harmonyos·鸿蒙系统
K.P1 天前
鸿蒙元服务从0到上架【第二篇】
华为·harmonyos·鸿蒙系统