纯血鸿蒙开发之广告服务(2)
前言
哈喽,小伙伴们大家好!我是青蓝逐码的云杰,上一篇文章我们学习鸿蒙广告服务中的banner广告和开屏广告,今天我们接着学习!
1.原生广告
原生广告是与应用内容融于一体的广告,通过“和谐”的内容呈现广告信息,在不破坏用户体验的前提下,为用户提供有价值的信息,展示形式包含图片和视频,支持您自由定制界面。
1.1 广告展示
1.2 开发步骤
1.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');
});
1.2.2 请求广告。
请求单广告位广告,需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener,来监听广告的加载状态。
若需提升广告推送精准度,可以在请求参数AdRequestParams中添加oaid属性。
请求广告参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
adType | number | 是 | 请求广告类型,原生广告类型为3。 |
adId | string | 是 | 广告位ID。如果仅调测广告,可使用测试广告位ID:testy63txaom86(原生视频),testu7m3hc4gvm(原生大图),testb65czjivt9(原生小图),testr6w14o0hqz(原生三图)。如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建。 |
oaid | string | 否 | 开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。 |
1.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 } })
}
};
1.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()
1.2.5 封装原生广告组件
-
请求广告
nativeAdUtil.requestAd()
-
获取广告参数信息
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() }
-
广告封装组件
import { AdComponent, advertising } from '@kit.AdsKit'; import { emitter } from '@kit.BasicServicesKit'; import { nativeAdUtil } from '../utils/NativeAdUtil'; @Component export struct NativeAdView { // 广告内容 private ads: Array<advertising.Advertisement> = []; private adDisplayOptions: advertising.AdDisplayOptions = { // 是否静音,默认不静音 mute: false }; @State isShow: boolean = false @State isShowClose: 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) { 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' }
-
效果展示
2. 插屏广告
插屏广告是一种在应用开启、暂停或退出时以全屏或半屏的形式弹出的广告形式,展示时机巧妙避开用户对应用的正常体验,尺寸大,曝光效果好。
2.1 广告展示
2.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'
}
2.3 开发使用
2.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);
}
2.3.2 展示广告
- 展示时期
由于我们不清楚广告参数什么时候请求成功,我们可以监听存储广告参数的数组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);
}
}
-
效果展示
总结
今天介绍了广告服务中的两个,目前我们已经掌握了广告服务,如果对这方面还有疑惑,欢迎在评论区留言或者加入我们组织,组织里很多厉害的大佬!如果我的内容对您有帮助,可以点赞、关注+收藏,谢谢大家!如果小伙伴对鸿蒙的其他内容感兴趣,欢迎加入我们青蓝逐码!
青蓝逐码官网:www.qinglanzhuma.cn/