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

场景介绍

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

接口说明

接口名 描述
loadAd(adParam: AdRequestParams, adOptions: AdOptions, listener: AdLoadListener): void 请求单广告位广告,通过AdRequestParams、AdOptions进行广告请求参数设置,通过AdLoadListener监听广告请求回调。
loadAdWithMultiSlots(adParams: AdRequestParams[], adOptions: AdOptions, listener: MultiSlotsAdLoadListener): void 请求多广告位广告,通过AdRequestParams[]、AdOptions进行广告请求参数设置,通过MultiSlotsAdLoadListener监听广告请求回调。
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,来监听广告的加载状态。

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

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

    示例代码如下所示:

    复制代码
    1. import { advertising, identifier } from '@kit.AdsKit';
    2. import { router } from '@kit.ArkUI';
    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 LoadAd {
    9. private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
    10. private oaid: string = '';
    11. aboutToAppear() {
    12. try {
    13. // 使用Promise回调方式获取OAID
    14. identifier.getOAID().then((data: string) => {
    15. this.oaid = data;
    16. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in getting adsIdentifierInfo by promise');
    17. }).catch((error: BusinessError) => {
    18. hilog.error(0x0000, 'testTag', '%{public}s',
    19. `Failed to get adsIdentifierInfo, error code: {error.code}, message: {error.message}`);
    20. })
    21. } catch (error) {
    22. hilog.error(0x0000, 'testTag', '%{public}s', `Catch err, code: {error.code}, message: {error.message}`);
    23. }
    24. }
    25. build() {
    26. Column() {
    27. Column() {
    28. // 跳转到原生广告展示页面
    29. Button("请求原生广告", { type: ButtonType.Normal, stateEffect: true }).onClick(() => {
    30. this.requestAd();
    31. })
    32. }.width('100%').height('80%').justifyContent(FlexAlign.Center)
    33. }
    34. .width('100%')
    35. .height('100%')
    36. }
    37. private requestAd(): void {
    38. // 广告展示参数
    39. const adDisplayOptions: advertising.AdDisplayOptions = {
    40. // 是否静音,默认不静音
    41. mute: false
    42. }
    43. // 原生广告配置
    44. const adOptions: advertising.AdOptions = {
    45. // 设置是否请求非个性化广告
    46. nonPersonalizedAd: 1,
    47. // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
    48. allowMobileTraffic: 0,
    49. // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
    50. tagForChildProtection: -1,
    51. // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
    52. tagForUnderAgeOfPromise: -1,
    53. // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
    54. adContentClassification: 'A'
    55. }
    56. // 原生广告请求参数
    57. const nativeVideoAdReqParams: advertising.AdRequestParams = {
    58. // 'testu7m3hc4gvm'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    59. adId: 'testu7m3hc4gvm',
    60. adType: 3,
    61. adCount: 1,
    62. // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
    63. enableDirectReturnVideoAd: true,
    64. oaid: this.oaid
    65. }
    66. // 广告请求回调监听
    67. const adLoaderListener: advertising.AdLoadListener = {
    68. // 广告请求失败回调
    69. onAdLoadFailure: (errorCode: number, errorMsg: string) => {
    70. hilog.error(0x0000, 'testTag', '%{public}s',
    71. `Failed to request ad, message: {errorMsg}, error code: {errorCode}`);
    72. },
    73. // 广告请求成功回调
    74. onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
    75. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in requesting ad');
    76. // 调用原生广告展示页面
    77. routePage('pages/NativeAdPage', ads, adDisplayOptions);
    78. }
    79. };
    80. // 创建AdLoader广告对象
    81. const load: advertising.AdLoader = new advertising.AdLoader(this.context);
    82. // 调用广告请求接口
    83. load.loadAd(nativeVideoAdReqParams, adOptions, adLoaderListener);
    84. }
    85. }
    86. async function routePage(pageUri: string, ads: Array<advertising.Advertisement | null>,
    87. displayOptions: advertising.AdDisplayOptions) {
    88. let options: router.RouterOptions = {
    89. url: pageUri,
    90. params: {
    91. ads: ads,
    92. displayOptions: displayOptions
    93. }
    94. }
    95. try {
    96. router.pushUrl(options);
    97. } catch (error) {
    98. hilog.error(0x0000, 'testTag', '%{public}s',
    99. `Failed to routePage callback, code: {error.code}, msg: {error.message}`);
    100. }
    101. }

    请求多广告与请求单广告类似,需要创建一个AdLoader对象,通过AdLoader的loadAdWithMultiSlots方法请求广告,最后通过MultiSlotsAdLoadListener,来监听广告的加载状态。示例代码如下:

    复制代码
    1. import { advertising, identifier } from '@kit.AdsKit';
    2. import { router } from '@kit.ArkUI';
    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 LoadAd {
    9. private ads: Array<advertising.Advertisement> = [];
    10. private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
    11. private oaid: string = '';
    12. aboutToAppear() {
    13. try {
    14. // 使用Promise回调方式获取OAID
    15. identifier.getOAID().then((data: string) => {
    16. this.oaid = data;
    17. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in getting adsIdentifierInfo by promise');
    18. }).catch((error: BusinessError) => {
    19. hilog.error(0x0000, 'testTag', '%{public}s',
    20. `Failed to get adsIdentifierInfo, code: {error.code}, message: {error.message}`);
    21. })
    22. } catch (error) {
    23. hilog.error(0x0000, 'testTag', '%{public}s', `Catch err, code: {error.code}, message: {error.message}`);
    24. }
    25. }
    26. build() {
    27. Column() {
    28. Column() {
    29. // 跳转到原生广告展示页面
    30. Button("请求原生广告", { type: ButtonType.Normal, stateEffect: true }).onClick(() => {
    31. this.requestAd();
    32. })
    33. }.width('100%').height('80%').justifyContent(FlexAlign.Center)
    34. }
    35. .width('100%')
    36. .height('100%')
    37. }
    38. private requestAd(): void {
    39. // 广告展示参数
    40. const adDisplayOptions: advertising.AdDisplayOptions = {
    41. // 是否静音,默认不静音
    42. mute: false
    43. }
    44. // 原生广告配置
    45. const adOptions: advertising.AdOptions = {
    46. // 是否允许流量下载 0不允许 1允许,不设置以广告主设置为准
    47. allowMobileTraffic: 0,
    48. // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
    49. tagForChildProtection: -1,
    50. // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
    51. tagForUnderAgeOfPromise: -1,
    52. // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
    53. adContentClassification: 'A'
    54. };
    55. // 原生广告请求参数
    56. const nativeVideoAdReqParams: advertising.AdRequestParams[] = [{
    57. // 'testy63txaom86'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    58. adId: 'testy63txaom86',
    59. adType: 3,
    60. adCount: 1,
    61. // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
    62. enableDirectReturnVideoAd: true,
    63. oaid: this.oaid
    64. }, {
    65. // 'testu7m3hc4gvm'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    66. adId: 'testu7m3hc4gvm',
    67. adType: 3,
    68. adCount: 1,
    69. // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
    70. enableDirectReturnVideoAd: true,
    71. oaid: this.oaid
    72. }]
    73. // 广告请求回调监听
    74. const adLoaderListener: advertising.MultiSlotsAdLoadListener = {
    75. // 广告请求失败回调
    76. onAdLoadFailure: (errorCode: number, errorMsg: string) => {
    77. hilog.error(0x0000, 'testTag', '%{public}s',
    78. `Failed to request ad errorCode is: {errorCode}, errorMsg is: {errorMsg}`);
    79. },
    80. // 广告请求成功回调
    81. onAdLoadSuccess: (ads: Map<string, Array<advertising.Advertisement>>) => {
    82. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in requesting ad!');
    83. ads.forEach((adsArray) => this.ads.push(...adsArray));
    84. // 调用原生广告展示页面
    85. routePage('pages/NativeAdPage', this.ads, adDisplayOptions);
    86. }
    87. };
    88. // 创建AdLoader广告对象
    89. const load: advertising.AdLoader = new advertising.AdLoader(this.context);
    90. // 调用广告请求接口
    91. load.loadAdWithMultiSlots(nativeVideoAdReqParams, adOptions, adLoaderListener);
    92. }
    93. }
    94. async function routePage(pageUri: string, ads: Array<advertising.Advertisement | null>,
    95. displayOptions: advertising.AdDisplayOptions) {
    96. let options: router.RouterOptions = {
    97. url: pageUri,
    98. params: {
    99. ads: ads,
    100. displayOptions: displayOptions
    101. }
    102. }
    103. try {
    104. router.pushUrl(options);
    105. } catch (error) {
    106. hilog.error(0x0000, 'testTag', '%{public}s',
    107. `Failed to routePage callback, code: {error.code}, msg: {error.message}`);
    108. }
    109. }
  3. 展示广告

    在您的页面中使用AdComponent组件展示原生广告。您需要在entry/src/main/resources/base/profile/main_pages.json文件中添加pages/NativeAdPage页面,如下图所示。


    示例代码如下所示:

    复制代码
    1. import { advertising, AdComponent } from '@kit.AdsKit';
    2. import { Prompt, router } from '@kit.ArkUI';
    3. @Entry
    4. @Component
    5. export struct NativeAdPage {
    6. // 广告内容
    7. private ads: Array<advertising.Advertisement> = [];
    8. private adDisplayOptions: advertising.AdDisplayOptions = {
    9. // 是否静音,默认不静音
    10. mute: false
    11. }
    12. aboutToAppear() {
    13. const params: Record<string, Object> = router.getParams() as Record<string, Object>;
    14. if (params && params.ads as Array<advertising.Advertisement> &&
    15. params.displayOptions as advertising.AdDisplayOptions) {
    16. this.ads = params.ads as Array<advertising.Advertisement>;
    17. this.adDisplayOptions = params.displayOptions as advertising.AdDisplayOptions;
    18. }
    19. }
    20. build() {
    21. Column() {
    22. List({ space: 20, initialIndex: 0 }) {
    23. ForEach(this.ads, (ad: advertising.Advertisement) => {
    24. ListItem() {
    25. AdComponent({
    26. ads: [ad],
    27. displayOptions: this.adDisplayOptions,
    28. interactionListener: {
    29. onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
    30. switch (status) {
    31. case 'onAdOpen':
    32. Prompt.showToast({
    33. message: 'native ad open',
    34. duration: 1000
    35. });
    36. break;
    37. case 'onAdClick':
    38. Prompt.showToast({
    39. message: 'native ad click',
    40. duration: 1000
    41. });
    42. break;
    43. case 'onAdClose':
    44. Prompt.showToast({
    45. message: 'native ad close',
    46. duration: 1000
    47. });
    48. break;
    49. default:
    50. }
    51. }
    52. }
    53. })
    54. .width('100%')
    55. }
    56. })
    57. }
    58. .listDirection(Axis.Vertical)
    59. .scrollBar(BarState.Off)
    60. .friction(0.6)
    61. .divider({
    62. strokeWidth: 2,
    63. color: Color.White,
    64. startMargin: 20,
    65. endMargin: 20
    66. })
    67. .edgeEffect(EdgeEffect.Spring)
    68. .width('100%')
    69. .height('100%')
    70. }.width('100%').height('100%')
    71. }
    72. }

    说明

    在原生广告场景中通常不需要显式设置AdComponent组件的高度,AdComponent组件会自动调整高度以适应需要展示的内容

相关推荐
雪芽蓝域zzs2 小时前
鸿蒙Next开发 获取APP缓存大小和清除缓存
缓存·华为·harmonyos
Robot2515 小时前
「华为」人形机器人赛道投资首秀!
大数据·人工智能·科技·microsoft·华为·机器人
鸿蒙布道师6 小时前
鸿蒙NEXT开发动画案例5
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
小诸葛的博客13 小时前
华为ensp实现跨vlan通信
网络·华为·智能路由器
康康这名还挺多15 小时前
鸿蒙HarmonyOS list优化一: list 结合 lazyforeach用法
数据结构·list·harmonyos·lazyforeach
晚秋大魔王18 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos
python算法(魔法师版)1 天前
.NET 在鸿蒙系统上的适配现状
华为od·华为·华为云·.net·wpf·harmonyos
bestadc1 天前
鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
harmonyos
枫叶丹41 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十二)
华为·harmonyos·deveco studio·harmonyos next
ax一号街阿楠1 天前
华为FAT AP配置 真机
网络·华为·智能路由器