
11-自然壁纸实战教程-接入鲸鸿动能广告 原创 精华
11-自然壁纸实战教程-接入鲸鸿动能广告
前言
目前我们上架的作品都打算接入广告,当做是学习下鸿蒙的广告接入流程,也是也希望着后续做出更加优质的 作品和应用了,可以通过广告实现收益。
广告流程
商业上架前需进行广告的测试验证,包括媒体自测和鲸鸿动能验收两个步骤。
自测
自测阶段请使用测试ID,并对照《APK广告位信息表》交付件中的“转测自检项”核对检查;
-
SDK自助测试工具
您可以通过SDK自助测试工具检测自己的App是否正确集成了SDK、广告请求和广告返回是否成功、广告展示是否正常以及广告事件是否正常上报。如果广告请求异常或未正确获取广告,SDK自助测试工具会提供相应的解决建议。具体详情请扫描下方二维码或点击链接下载APK。
类型 二维码 APK下载 APK 下载 -
极速开屏无需自测,直接提交鲸鸿动能测试验收,但需填写信息表。
-
请务必检查确认关于用户隐私声明的要求,媒体需以自身的名义发布用户隐私声明,禁止以华为或鲸鸿动能等名义发布用户隐私声明,详情参考《业务规范》- 《隐私声明》的要求;
-
各广告位规则:请参照《业务规范》-《广告规范》;
-
自测完成后,填写《APK广告位信息表》和《RPK广告位信息表》,其中涉及广告位信息和转测自检项,保证清晰描述广告位调用逻辑,转测自检项全部通过。
鲸鸿动能验收
在自测没有问题之后,我们要交予鲸鸿动能验收,联系人工客服,拉群进行验收(一家公司有一个群就行了)
一般就是1-2个工作日哈
运营配置广告
在测试验收通过之后,他们会联系运营进行配置广告,一般这个过程也需要一日
商品上架
在上方的步骤全部结束之后,我们就可以更换广告正式位ID,然后上架
广告开发流程
请求广告。
请求单广告位广告,需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener,来监听广告的加载状态。
请求广告关键参数如下所示:
请求广告参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
adType | number | 是 | 请求广告类型,原生广告类型为3。 |
adId | string | 是 | 广告位ID。 |
- 如果仅调测广告,可使用测试广告位ID:testy63txaom86(原生视频),testu7m3hc4gvm(原生大图),testb65czjivt9(原生小图),testr6w14o0hqz(原生三图)。
- 如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建。
展示广告
- 说明
用户关闭广告或点负反馈,需要处理AD_CLOSED回调。
在您的页面中使用AdComponent组件展示原生广告
封装之后的代码
请求广告的类
NativeAdUtil.ets
import { advertising } from "@kit.AdsKit";
import { router } 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
//正式广告位 s3z1eig5n2
adId: "s3z1eig5n2",
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`,
);
// 调用原生广告展示页面
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();
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374;
广告展示组件
import { AdComponent, advertising } from '@kit.AdsKit';
import { emitter } from '@kit.BasicServicesKit';
import { nativeAdUtil } from '../utils/NativeAdUtil';
@Component
export struct NativeAdPage {
// 广告内容
private ads: Array<advertising.Advertisement> = [];
private adDisplayOptions: advertising.AdDisplayOptions = {
// 是否静音,默认不静音
mute: false
};
@State isShow: 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) {
AdComponent({
ads: this.ads,
displayOptions: this.adDisplayOptions,
interactionListener: {
onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
switch (status) {
case AdStatus.AD_OPEN:
break;
case AdStatus.AD_CLICKED:
break;
case AdStatus.AD_CLOSED:
break;
default:
}
}
}
})
.width('100%')
}
}
}
enum AdStatus {
AD_OPEN = 'onAdOpen',
AD_CLICKED = 'onAdClick',
AD_CLOSED = 'onAdClose'
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
测试位ID效果
补充:Ads Kit(广告服务)开发指南
Ads Kit(广告服务)依托华为终端平台与数据能力为您提供流量变现服务,帮助您解决流量变现的难题;同时为广告主提供广告服务,配合华为终端平台向用户提供个性化的营销活动或商业广告。
鲸鸿动能流量变现服务(以下简称流量变现服务)是广告服务依托华为终端强大的平台与数据能力为您提供的App流量变现服务,您通过该服务可以在自己的App中获取并向用户展示精美的、高价值的广告内容,并从中获得广告收益。
为满足App不同场景下的内容形式,流量变现服务提供了横幅广告、原生广告、激励广告、插屏广告、开屏广告、贴片广告六种广告形式。
广告形式 | 展示形式 | 应用场景 |
---|---|---|
横幅广告 | 图片 | 以通知栏或矩形固定展示在应用内页面顶部、中部或底部,适合用于用户停留较久或者访问频繁的页面。 |
原生广告 | 图片、视频 | 界面内插入广告,与媒体内容无缝融合。 |
激励广告 | 视频 | 游戏通关、复活、获取道具、积分、继续机会、人物技能升级时等展示。 |
插屏广告 | 图片、视频 | 游戏或流媒体开启、暂停、过关、跳转、加载、退出时弹出。 |
开屏广告 | 图片、视频 | 打开App时,以开屏形式全屏展现,展示时长3s-5s,展示完毕后自动关闭并进入应用主页面。 |
贴片广告 | 图片、视频 | 前贴:视频播放前。中贴:视频播放中。后贴:视频播放结束后。说明:您可以根据自身需求设置广告的播放时长。 |
具体如何进入这项服务,我在之前的文章中专门介绍过接入广告服务,这里就不过多介绍这个,本系列文章主要介绍的是广告的使用和展示
广告展示
1.横幅广告
横幅广告又名Banner广告,是在应用程序顶部、中部或底部占据一个位置的矩形图片,广告内容每隔一段时间会自动刷新。
1.1 解释说明
横幅广告是所有广告里较为简单的。
-
获取OAID。
若需提升广告推送精准度,可以在请求参数AdRequestParams中添加oaid属性以提升广告推送精准度和广告填充率。
如何获取OAID参考获取OAID信息。
说明
使用以下示例中提供的测试广告位时,必须先获取OAID信息。
identifier.getOAID().then((data: string) => { this.oaid = data; }).catch((error: BusinessError) => { hilog.error(0x0000, 'testTag', 'Failed to get OAID'); });
-
请求和展示广告。
在您的页面中使用AutoAdComponent组件展示横幅广告。
请求广告关键参数如下所示:
请求广告参数名 类型 必填 说明 adType number 是 请求广告类型,横幅广告类型为8。 adId string 是 广告位ID。如果仅调测广告,可使用测试广告位ID:testw6vs28auh3。如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建。 adWidth number 是 广告位宽,单位vp。宽和高支持36057和360144两种尺寸。 adHeight number 是 广告位高,单位vp。宽和高支持36057和360144两种尺寸。 oaid string 否 开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。 展示广告关键参数如下所示:
展示广告参数名 类型 必填 说明 refreshTime number 否 横幅广告轮播时间。单位ms,取值范围[30000, 120000]。如果不设置或取值为非数字或小于等于0的数字,则不轮播。设置小于30000的数字取值30000,设置大于120000的数字取值120000。
AutoAdComponent({
adParam: this.adParam,
adOptions: this.adOptions,
displayOptions: this.displayOptions,
interactionListener: {
onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
hilog.info(0x0000, 'testTag', '%{public}s', `status is ${status}`);
switch (status) {
case AdStatus.AD_OPEN:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');
break;
case AdStatus.AD_CLICKED:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');
break;
case AdStatus.AD_CLOSED:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
this.visibilityState = Visibility.None;
break;
case AdStatus.AD_LOAD:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdLoad');
break;
case AdStatus.AD_FAIL:
hilog.error(0x0000, 'testTag', '%{public}s', 'Status is onAdFail');
this.visibilityState = Visibility.None;
break;
}
}
}
})
1.2示例代码
为了小伙伴之后,可以直接使用,这边我已经将他封装成自定义组件咯
import { advertising, AutoAdComponent } from '@kit.AdsKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Component
export struct BannerView {
@State adParam: advertising.AdRequestParams = {
// 广告类型:横幅广告
adType: 8,
// 'testw6vs28auh3'为测试专用的广告位ID,应用正式发布时需要改为正式的广告位ID
adId: 'testw6vs28auh3',
// 广告位宽
adWidth: 360,
// 广告位高
adHeight: 57
};
private 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'
};
private displayOptions: advertising.AdDisplayOptions = {
// 广告轮播的时间间隔,单位ms,取值范围[30000, 120000]
refreshTime: 30000
}
private ratio: number = 1;
private adWidth: number = -1;
private adHeight: number = -1;
@State visibilityState: Visibility = Visibility.Visible;
aboutToAppear() {
if (this.adParam?.adWidth && typeof (this.adParam?.adWidth) === 'number' && this.adParam?.adWidth > 0) {
this.adWidth = this.adParam?.adWidth;
}
if (this.adParam?.adHeight && typeof (this.adParam?.adHeight) === 'number' && this.adParam?.adHeight > 0) {
this.adHeight = this.adParam?.adHeight;
}
if (this.adWidth > 0 && this.adHeight > 0) {
this.ratio = this.adWidth / this.adHeight;
}
}
build() {
Stack({ alignContent: Alignment.Bottom }) {
this.buildBannerView()
}
}
@Builder
buildBannerView() {
Row() {
AutoAdComponent({
adParam: this.adParam,
adOptions: this.adOptions,
displayOptions: this.displayOptions,
interactionListener: {
onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
hilog.info(0x0000, 'testTag', '%{public}s', `status is ${status}`);
switch (status) {
case AdStatus.AD_OPEN:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');
break;
case AdStatus.AD_CLICKED:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');
break;
case AdStatus.AD_CLOSED:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
this.visibilityState = Visibility.None;
break;
case AdStatus.AD_LOAD:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdLoad');
break;
case AdStatus.AD_FAIL:
hilog.error(0x0000, 'testTag', '%{public}s', 'Status is onAdFail');
this.visibilityState = Visibility.None;
break;
}
}
}
})
}
.width('100%')
.aspectRatio(this.ratio)
.visibility(this.visibilityState)
}
}
enum AdStatus {
AD_LOAD = 'onAdLoad',
AD_FAIL = 'onAdFail',
AD_OPEN = 'onAdOpen',
AD_CLICKED = 'onAdClick',
AD_CLOSED = 'onAdClose',
AD_REWARDED = 'onAdReward',
AD_VIDEO_START = 'onVideoPlayBegin',
AD_COMPLETED = 'onVideoPlayEnd'
}
1.3 效果演示
1.4 总结
- 广告请求:通过
AdLoader
请求广告并处理回调。 - 广告显示:使用
AdComponent
组件展示广告数据,并通过interactionListener
监听广告状态。
2.开屏广告
开屏广告是一种在应用启动时且在应用主界面显示之前展示的广告。它分为以下两种类型:
- 全屏开屏广告:广告覆盖整个屏幕。
- 半屏开屏广告:广告占据部分屏幕,并可自定义布局,通常会显示广告的图标和版权信息。
2.1 开发步骤
2.1.1 获取OAID
- OAID(Open Advertising ID)是设备的唯一广告标识符,用于精准推送广告。建议在请求广告时传递 OAID 以提升广告投放的精准度。
- 获取 OAID 示例代码:
identifier.getOAID().then((data: string) => {
this.oaid = data;
}).catch((error: BusinessError) => {
hilog.error(0x0000, 'testTag', 'Failed to get OAID');
});
2.1.2 请求广告
需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener来监听广告的加载状态。测试开屏广告时,需要使用专门的测试广告位来获取测试开屏广告,示例代码中提供了两种开屏广告类型对应的广告位:半屏开屏(图片)(testq6zq98hecj)和全屏开屏(视频)(testd7c5cewoj6),测试广告位ID仅作为调试使用,不可用于广告变现。
请求广告关键参数如下所示:
请求广告参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
adType | number | 是 | 请求广告类型,开屏广告类型为1。 |
adId | string | 是 | 广告位ID。如果仅调测广告,可使用测试广告位ID:testq6zq98hecj半屏开屏(图片)和testd7c5cewoj6全屏开屏(视频)。如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建。 |
adCount | number | 否 | 广告数量。 |
返回广告参数名 | 类型 | 说明 |
---|---|---|
isFullScreen | boolean | 标识返回的广告是否为全屏,true为全屏广告,false为半屏广告。 |
说明
- 如果超时没有请求到广告,应用自行跳转到默认首页。
- 为保证开屏展示效果,建议开发者在请求广告前,设置屏幕方向为竖屏。
2.1.3 设置监听回调
- 通过 AdLoadListener 监听广告加载的回调:
- onAdLoadFailure:广告加载失败。
- onAdLoadSuccess:广告加载成功。
const adLoaderListener: advertising.AdLoadListener = {
onAdLoadFailure: (errorCode: number, errorMsg: string) => {
hilog.error(0x0000, 'testTag', `Failed to load ad. errorCode: ${errorCode}, errorMsg: ${errorMsg}`);
},
onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
hilog.info(0x0000, 'testTag', 'Ad loaded successfully!');
// 展示广告
}
};
2.2 开发使用
2.2.1 请求封装
将请求开屏广告(全屏和半屏)的方法进行封装
import { router } from '@kit.ArkUI';
import { advertising } from '@kit.AdsKit';
import { common } from '@kit.AbilityKit';
import { emitter } from '@kit.BasicServicesKit';
/**
* 开屏广告
* 1.视频 2.图片
*/
export enum AdType {
// 开屏广告的类型
SPLASH_AD = 1
}
class SplashAdUtil {
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
private isTimeOut: boolean = false;
// 超时时间(单位毫秒),开发者可根据实际情况修改
private timeOutDuration: number = 1 * 1000;
// 超时index
private timeOutIndex: number = -1;
// 广告展示参数
private adDisplayOptions: advertising.AdDisplayOptions = {
// 是否静音,默认不静音
mute: false
}
// 广告配置
private 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'
}
// 开屏视频广告请求参数
private splashVideoAdReqParams: advertising.AdRequestParams = {
// 'testd7c5cewoj6'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
adId: 'testd7c5cewoj6',
adType: AdType.SPLASH_AD,
adCount: 1,
}
// 开屏图片广告请求参数
private splashImageAdReqParams: advertising.AdRequestParams = {
// 'testq6zq98hecj'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
adId: 'testq6zq98hecj',
adType: AdType.SPLASH_AD,
adCount: 1,
}
private requestAd(adReqParams: advertising.AdRequestParams, adOptions: advertising.AdOptions): void {
// 广告请求回调监听
const adLoaderListener: advertising.AdLoadListener = {
// 广告请求失败回调
onAdLoadFailure: (errorCode: number, errorMsg: string) => {
clearTimeout(this.timeOutIndex);
if (this.isTimeOut) {
return;
}
},
// 广告请求成功回调
onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
clearTimeout(this.timeOutIndex);
if (this.isTimeOut) {
return;
}
// 保存请求到的广告内容用于展示
if (canIUse("SystemCapability.Advertising.Ads")) {
if (ads[0].adType === AdType.SPLASH_AD) {
// 调用开屏广告展示页面
if (ads[0]?.isFullScreen === true) {
emitter.emit('SplashFullScreenAdPage',
{ data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })
} else {
emitter.emit('SplashHalfScreenAdPage',
{ data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })
}
} else {
}
}
}
};
// 创建AdLoader广告对象
const load: advertising.AdLoader = new advertising.AdLoader(this.context);
// 调用广告请求接口
// adReqParams.oaid = this.oaid;
this.timeOutHandler();
load.loadAd(adReqParams, adOptions, adLoaderListener);
}
private timeOutHandler(): void {
this.isTimeOut = false;
// 超时处理
this.timeOutIndex = setTimeout(() => {
this.isTimeOut = true;
const options: router.RouterOptions = {
// 开发者可根据项目实际情况修改超时之后要跳转的目标页面
url: 'pages/Index',
};
router.pushUrl(options);
}, this.timeOutDuration);
}
//视频
splashVideoAd() {
this.requestAd(this.splashVideoAdReqParams, this.adOptions);
}
//图片
splashImageAd() {
this.requestAd(this.splashImageAdReqParams, this.adOptions);
}
}
export const splashAdUtil = new SplashAdUtil()
2.2.2 广告参数传递
当发送广告请求,得到应有的广告参数之后,我们将参数传递给全屏广告或者半屏广告(利用emitter线性通信)
if (ads[0]?.isFullScreen === true) {
emitter.emit('SplashFullScreenAdPage',
{ data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })
} else {
emitter.emit('SplashHalfScreenAdPage',
{ data: { 'ads': ads, 'adDisplayOptions': this.adDisplayOptions } })
}
2.2.3 开屏(全屏)广告展示
- 解释广告请求时间点
aboutToAppear() {
emitter.on('SplashFullScreenAdPage', (eventData: emitter.EventData) => {
const data = eventData.data as Record<string, object>
this.ads = data['ads'] as Array<advertising.Advertisement>
this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
this.isShow = true
})
splashAdUtil.splashVideoAd()
}
- 全屏广告页面
import { router } from '@kit.ArkUI';
import { AdComponent, advertising } from '@kit.AdsKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { emitter } from '@kit.BasicServicesKit';
import { splashAdUtil } from '../utils/SplashAdUtil';
const TAG = 'Ads Demo-SplashFullScreenAdPage';
@Entry
@Component
struct SplashFullScreenAdPage {
private ads: Array<advertising.Advertisement> = [];
private displayOptions?: advertising.AdDisplayOptions;
@State isShow: boolean = false
aboutToAppear() {
emitter.on('SplashFullScreenAdPage', (eventData: emitter.EventData) => {
const data = eventData.data as Record<string, object>
this.ads = data['ads'] as Array<advertising.Advertisement>
this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
this.isShow = true
})
splashAdUtil.splashVideoAd()
}
build() {
if (this.isShow) {
Column() {
// 运行在提供方进程里
AdComponent({
ads: this.ads, displayOptions: this.displayOptions,
interactionListener: {
onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
switch (status) {
case AdStatus.AD_OPEN:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdOpen');
break;
case AdStatus.AD_CLICKED:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClick');
break;
case AdStatus.AD_CLOSED:
hilog.info(0x0000, 'testTag', '%{public}s', 'Status is onAdClose');
router.replaceUrl({
url: 'pages/Index',
})
break;
}
}
}
})
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
}
}
export enum AdStatus {
AD_OPEN = 'onAdOpen',
AD_CLICKED = 'onAdClick',
AD_CLOSED = 'onAdClose'
}
-
效果展示
2.2.4 开屏(半屏)广告展示
- 解释广告请求时间点
aboutToAppear() {
emitter.on('SplashHalfScreenAdPage', (eventData: emitter.EventData) => {
const data = eventData.data as Record<string, object>
this.ads = data['ads'] as Array<advertising.Advertisement>
this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions
this.isShow = true
})
splashAdUtil.splashImageAd()
}
-
半屏广告页面
import { router } from '@kit.ArkUI'; import { AdComponent, advertising } from '@kit.AdsKit'; import { splashAdUtil } from '../utils/SplashAdUtil'; import { emitter } from '@kit.BasicServicesKit'; @Entry @Component struct SplashHalfScreenAdPage { private ads: Array<advertising.Advertisement> = []; private displayOptions?: advertising.AdDisplayOptions; @State isShow: boolean = false aboutToAppear() { emitter.on('SplashHalfScreenAdPage', (eventData: emitter.EventData) => { const data = eventData.data as Record<string, object> this.ads = data['ads'] as Array<advertising.Advertisement> this.displayOptions = data['adDisplayOptions'] as advertising.AdDisplayOptions this.isShow = true }) splashAdUtil.splashImageAd() } build() { if (this.isShow) { Column() { // 运行在提供方进程里 AdComponent({ ads: this.ads, displayOptions: this.displayOptions, interactionListener: { onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => { switch (status) { case AdStatus.AD_OPEN: break; case AdStatus.AD_CLICKED: break; case AdStatus.AD_CLOSED: router.replaceUrl({ url: 'pages/Index', }) break; } } } }) .width('100%') .height('87%') // 展示媒体自定义icon、应用名称、版权信息 Column({}) { Text('广告') }.width('100%').height('100%') } } } } export enum AdStatus { AD_OPEN = 'onAdOpen', AD_CLICKED = 'onAdClick', AD_CLOSED = 'onAdClose' }
-
效果展示
3.原生广告
原生广告是与应用内容融于一体的广告,通过“和谐”的内容呈现广告信息,在不破坏用户体验的前提下,为用户提供有价值的信息,展示形式包含图片和视频,支持您自由定制界面。
3.1 广告展示
3.2 开发步骤
3.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');
});
3.2.2 请求广告。
请求单广告位广告,需要创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener,来监听广告的加载状态。
若需提升广告推送精准度,可以在请求参数AdRequestParams中添加oaid属性。
请求广告参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
adType | number | 是 | 请求广告类型,原生广告类型为3。 |
adId | string | 是 | 广告位ID。如果仅调测广告,可使用测试广告位ID:testy63txaom86(原生视频),testu7m3hc4gvm(原生大图),testb65czjivt9(原生小图),testr6w14o0hqz(原生三图)。如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建。 |
oaid | string | 否 | 开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。 |
3.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 } })
}
};
3.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()
3.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 { @State isShow: boolean = false @State isShowClose: boolean = false // 广告内容 private ads: Array<advertising.Advertisement> = []; private adDisplayOptions: advertising.AdDisplayOptions = { // 是否静音,默认不静音 mute: 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' }
-
效果展示
4. 插屏广告
插屏广告是一种在应用开启、暂停或退出时以全屏或半屏的形式弹出的广告形式,展示时机巧妙避开用户对应用的正常体验,尺寸大,曝光效果好。
4.1 广告展示
4.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'
}
4.3 开发使用
4.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);
}
4.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);
}
}
-
效果展示
如何获取资料
获取资料的途径,可以关注我们 官网的公众号 青蓝逐码 ,输入 项目名称 《自然壁纸》 即可获得以上资料。
关于我们
如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯,甚至你想要做出一款属于自己的应用!欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。
