华为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监听广告状态回调。 |
开发步骤
- 获取OAID。
如果想要为用户更精准的推送广告,可以在请求参数AdRequestParams中添加oaid属性。
如何获取OAID参见获取OAID信息。
说明
使用以下示例中提供的测试广告位必须先获取OAID信息。
- 请求广告。
请求单广告位广告,需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener,来监听广告的加载状态。
如果想要为用户更精准的推送广告,可以在请求参数AdRequestParams中添加oaid属性。
请求广告关键参数如下所示:
示例代码如下所示:请求广告参数名
类型
必填
说明
adType
number
是
请求广告类型,原生广告类型为3。
adId
string
是
广告位ID。
- 如果仅调测广告,可使用测试广告位ID:testy63txaom86(原生视频),testu7m3hc4gvm(原生大图),testb65czjivt9(原生小图),testr6w14o0hqz(原生三图)。
- 如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建。
oaid
string
否
开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。
- import { advertising, identifier } from '@kit.AdsKit';
- import { router } from '@kit.ArkUI';
- import { common } from '@kit.AbilityKit';
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import { BusinessError } from '@kit.BasicServicesKit';
- @Entry
- @Component
- export struct LoadAd {
- private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
- 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, error code: ${error.code}, message: ${error.message}`);
- })
- } catch (error) {
- hilog.error(0x0000, 'testTag', '%{public}s', `Catch err, code: ${error.code}, message: ${error.message}`);
- }
- }
- build() {
- Column() {
- Column() {
- // 跳转到原生广告展示页面
- Button("请求原生广告", { type: ButtonType.Normal, stateEffect: true }).onClick(() => {
- this.requestAd();
- })
- }.width('100%').height('80%').justifyContent(FlexAlign.Center)
- }
- .width('100%')
- .height('100%')
- }
- private requestAd(): void {
- // 广告展示参数
- 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,App正式发布时需要改为正式的广告位ID
- adId: 'testu7m3hc4gvm',
- adType: 3,
- adCount: 1,
- // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
- enableDirectReturnVideoAd: true,
- oaid: this.oaid
- }
- // 广告请求回调监听
- 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');
- // 调用原生广告展示页面
- routePage('pages/NativeAdPage', ads, adDisplayOptions);
- }
- };
- // 创建AdLoader广告对象
- const load: advertising.AdLoader = new advertising.AdLoader(this.context);
- // 调用广告请求接口
- load.loadAd(nativeVideoAdReqParams, adOptions, adLoaderListener);
- }
- }
- async function routePage(pageUri: string, ads: Array<advertising.Advertisement | null>,
- displayOptions: advertising.AdDisplayOptions) {
- let options: router.RouterOptions = {
- url: pageUri,
- params: {
- ads: ads,
- displayOptions: displayOptions
- }
- }
- try {
- router.pushUrl(options);
- } catch (error) {
- hilog.error(0x0000, 'testTag', '%{public}s',
- `Failed to routePage callback, code: ${error.code}, msg: ${error.message}`);
- }
- }
- import { advertising, identifier } from '@kit.AdsKit';
- import { router } from '@kit.ArkUI';
- import { common } from '@kit.AbilityKit';
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import { BusinessError } from '@kit.BasicServicesKit';
- @Entry
- @Component
- export struct LoadAd {
- private ads: Array<advertising.Advertisement> = [];
- private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
- 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() {
- Column() {
- Column() {
- // 跳转到原生广告展示页面
- Button("请求原生广告", { type: ButtonType.Normal, stateEffect: true }).onClick(() => {
- this.requestAd();
- })
- }.width('100%').height('80%').justifyContent(FlexAlign.Center)
- }
- .width('100%')
- .height('100%')
- }
- private requestAd(): void {
- // 广告展示参数
- const adDisplayOptions: advertising.AdDisplayOptions = {
- // 是否静音,默认不静音
- mute: false
- }
- // 原生广告配置
- const 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'
- };
- // 原生广告请求参数
- const nativeVideoAdReqParams: advertising.AdRequestParams[] = [{
- // 'testy63txaom86'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
- adId: 'testy63txaom86',
- adType: 3,
- adCount: 1,
- // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
- enableDirectReturnVideoAd: true,
- oaid: this.oaid
- }, {
- // 'testu7m3hc4gvm'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
- adId: 'testu7m3hc4gvm',
- adType: 3,
- adCount: 1,
- // 原生广告自定义扩展参数。等所有广告素材下载完后再回调
- enableDirectReturnVideoAd: true,
- oaid: this.oaid
- }]
- // 广告请求回调监听
- const adLoaderListener: advertising.MultiSlotsAdLoadListener = {
- // 广告请求失败回调
- onAdLoadFailure: (errorCode: number, errorMsg: string) => {
- hilog.error(0x0000, 'testTag', '%{public}s',
- `Failed to request ad errorCode is: ${errorCode}, errorMsg is: ${errorMsg}`);
- },
- // 广告请求成功回调
- onAdLoadSuccess: (ads: Map<string, Array<advertising.Advertisement>>) => {
- hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in requesting ad!');
- ads.forEach((adsArray) => this.ads.push(...adsArray));
- // 调用原生广告展示页面
- routePage('pages/NativeAdPage', this.ads, adDisplayOptions);
- }
- };
- // 创建AdLoader广告对象
- const load: advertising.AdLoader = new advertising.AdLoader(this.context);
- // 调用广告请求接口
- load.loadAdWithMultiSlots(nativeVideoAdReqParams, adOptions, adLoaderListener);
- }
- }
- async function routePage(pageUri: string, ads: Array<advertising.Advertisement | null>,
- displayOptions: advertising.AdDisplayOptions) {
- let options: router.RouterOptions = {
- url: pageUri,
- params: {
- ads: ads,
- displayOptions: displayOptions
- }
- }
- try {
- router.pushUrl(options);
- } catch (error) {
- hilog.error(0x0000, 'testTag', '%{public}s',
- `Failed to routePage callback, code: ${error.code}, msg: ${error.message}`);
- }
- }
- 展示广告
在您的页面中使用AdComponent组件展示原生广告。您需要在entry/src/main/resources/base/profile/main_pages.json文件中添加pages/NativeAdPage页面,如下图所示。
示例代码如下所示:- import { advertising, AdComponent } from '@kit.AdsKit';
- import { Prompt, router } from '@kit.ArkUI';
- @Entry
- @Component
- export struct NativeAdPage {
- // 广告内容
- private ads: Array<advertising.Advertisement> = [];
- private adDisplayOptions: advertising.AdDisplayOptions = {
- // 是否静音,默认不静音
- mute: false
- }
- aboutToAppear() {
- const params: Record<string, Object> = router.getParams() as Record<string, Object>;
- if (params && params.ads as Array<advertising.Advertisement> &&
- params.displayOptions as advertising.AdDisplayOptions) {
- this.ads = params.ads as Array<advertising.Advertisement>;
- this.adDisplayOptions = params.displayOptions as advertising.AdDisplayOptions;
- }
- }
- build() {
- Column() {
- List({ space: 20, initialIndex: 0 }) {
- ForEach(this.ads, (ad: advertising.Advertisement) => {
- ListItem() {
- AdComponent({
- ads: [ad],
- displayOptions: this.adDisplayOptions,
- interactionListener: {
- onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
- switch (status) {
- case 'onAdOpen':
- Prompt.showToast({
- message: 'native ad open',
- duration: 1000
- });
- break;
- case 'onAdClick':
- Prompt.showToast({
- message: 'native ad click',
- duration: 1000
- });
- break;
- case 'onAdClose':
- Prompt.showToast({
- message: 'native ad close',
- duration: 1000
- });
- break;
- default:
- }
- }
- }
- })
- .width('100%')
- }
- })
- }
- .listDirection(Axis.Vertical)
- .scrollBar(BarState.Off)
- .friction(0.6)
- .divider({
- strokeWidth: 2,
- color: Color.White,
- startMargin: 20,
- endMargin: 20
- })
- .edgeEffect(EdgeEffect.Spring)
- .width('100%')
- .height('100%')
- }.width('100%').height('100%')
- }
- }
说明
在原生广告场景中通常不需要显式设置AdComponent组件的高度,AdComponent组件会自动调整高度以适应需要展示的内容