原生广告(模版\自渲染\draw)
1、场景介绍
原生广告是与应用内容融于一体的广告,通过“和谐”的内容呈现广告信息,在不破坏用户体验的前提下,为用户提供有价值的信息,展示形式包含图片和视频,支持您自由定制界面。
信息流广告分为自渲染广告和模板广告,但是模板广告只有当三方SDK支持时才会返回模板广告。
- 自渲染广告:聚合SDK返回物料,由开发者在TBNativeAdComponent组件上进行子视图的自行渲染和展示。
- 模版渲染广告:聚合SDK直接返回渲染好的广告组件TBNativeAdComponent,开发者直接展示即可。
2、广告加载类TBNativeAdLoader
在SDK里只需要使用 TBNativeAdLoader 就可以获取信息流广告。TBNativeAdLoader支持多广告加载,可以一次加载返回多个广告。
注意:adHeight高度为0时,广告的实际高度由模版广告自行渲染决定
export class TBNativeAdLoader {
/**
* 广告请求信息
*/
readonly request: TBType.AdRequest;
/**
* 构造函数
*/
constructor(request: TBType.AdRequest);
/**
* 设置广告加载监听器
*/
set adLoadListener(listener: TBNativeAdLoaderListener);
/**
* 返回广告缓存池内所有信息
* 填充后可调用, 广告关闭后清理
* @returns
*/
getCacheAdInfoList(): TBAdInfo[];
/**
* 加载广告
*/
loadAdData();
/**
* 销毁广告加载资源
*/
destroy(): void;
}3、广告模型类TBNativeAd
在广告加载成功回调中获取相关广告信息,将广告信息传入广告组件TBNativeAdComponent进行信息流广告的展示。
export class TBNativeAd {
/**
* 广告交互监听器
*/
interactListener: TBNativeAdInteractListener | null = null;
/**
* 视频交互监听器
*/
videoListener: TBAdVideoListener | null = null;
/**
* 广告dislike弹窗监听
*/
dislikeListener: TBDislikeListener | null = null;
/**
* 渠道ID
*/
readonly channelId: TBType.Channel;
/**
* 普通点击组件Id集合
*/
readonly clickViewIds: TBClickViewIdList<string> = new TBClickViewIdList();
/**
* 创意点击ID集合
*/
readonly creativeViewIds: TBClickViewIdList<string> = new TBClickViewIdList();
/**
* 扩展参数
*/
readonly extra: Record<string, Object> = {};
/**
* 释放资源
*/
destroy(): void;
/**
* 广告唯一标识
*/
getUniqueId(): string;
/**
* 素材类型
* 【模版渲染为空】
*/
getMaterialType(): TBType.MaterialType;
/**
* 渲染类型 模版渲染 or 自渲染
*/
getRenderType(): TBType.RenderType;
/**
* 信息流广告类型 信息流 or DrawVideo
*/
getNativeType(): TBType.NativeType;
/**
* 广告交互类型
* 【模版渲染时为空】
*/
getInteractionType(): TBType.AdInteractionType;
/**
* 广告标题
* 【模版渲染时为空】
*/
getAdTitle(): string;
/**
* 广告描述
* 【模版渲染时为空】
*/
getAdDescription(): string;
/**
* 广告来源,可能为空
* 【模版渲染时为空】
*/
getAdSource(): string;
/**
* 获取广告⻆标的logo
* 当返回string类型时,可能为标准url,(csj)adx广告场景时可能文字描述
* 【模版渲染时为空】
*/
getAdLogo(): string | Resource | undefined ;
/**
* 广告图片集合,单图和组图类型广告素材有返回,视频类素材返回为空
* 【模版渲染时为空】
*/
getImageList(): TBAdImage[];
/**
* 广告Icon链接
* 【模版渲染时为空】
*/
getAppIconUrl(): string | undefined;
/**
* 应用下载相关合规信息
* 【模版渲染时为空】
*/
getComplianceInfo(): TBComplianceInfo | undefined;
/**
* 应用下载次数文案,非下载返回为空 eg:1000W此下载
* 【模版渲染时为空】
*/
getAppDownloadCountDes(): string | undefined;
/**
* 广告app评论数
* 【模版渲染时为0】
*/
getAppCommentNum(): number;
/**
* 应用下载评分,取值0~5.0; 非下载返回为0
* 【模版渲染时为空】
*/
getAppScore(): number;
/**
* 视频封面url
* [支持渠道:快手]
* 【模版渲染时为空】
*/
getCoverUrl(): TBAdImage | undefined;
/**
* 视频url
* 【模版渲染时为空】
*/
getVideoUrl(): string | undefined;
/**
* 视频时⻓
* 【模版渲染时为空】
*/
getVideoDuration(): number;
/**
* CTA按钮文案
* 【模版渲染时为空】
*/
getActionDescription(): string;
/**
* 注册原生自渲染广告点击组件ID
* @param rootAdComponentId 广告布局根节点Id
* @param uiContext 当前组件的上下文
* @param clickViewIds 普通点击Id集合,点击之后,会跳转到落地页,然后再进行后续广告转化
* @param creativeViewIds: 创意点击Id集合,点击之后,会直接进行转化
*/
registerViewForInteraction(clickViewIds: TBClickViewIdList<string>, creativeViewIds: TBClickViewIdList<string>);
}3.1、TBComplianceInfo说明
TBComplianceInfo提供应用下载相关合规信息,仅在返回广告位下载类广告时生效。
export class TBComplianceInfo extends TBMediaComplianceInfo {
/**
* 获取App Name
* @returns
*/
getAppName(): string;
/**
* 获取应用版本
* @returns
*/
getAppVersion(): string;
/**
* 获取开发者名称
* @returns
*/
getDeveloperName(): string;
/**
* 获取隐私协议
* @returns
*/
getPrivacyUrl(): string;
/**
* 获取权限名称及权限描述列表
* @returns
*/
getPermissionsMap(): Map<string, string>;
/**
* 获取权限列表url
* @returns
*/
getPermissionUrl(): string;
/**
* 获取产品功能url
* @returns
*/
getIntroductionInfoUrl(): string;
}4、广告组件TBNativeAdComponent
本组件提供了信息流广告的渲染
TBNativeAdComponent({nativeAd: TBNativeAd, builder: () => void})
展示信息流广告广告
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| nativeAd | TBNativeAd | 是 | 广告对象 |
| builder | () => void | 否 | 应用自渲染广告子组件。 |
5、视频组件TBNativeMediaComponent
本组件提供了信息流广告视频的渲染(仅在开发者自渲染时渲染)
TBNativeMediaComponent({nativeAd: TBBaseNativeAd})
展示信息流广告视频组件
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| nativeAd | TBBaseNativeAd | 是 | 广告加载成功后返回的广告对象 |
6、广告加载监听器
export interface TBNativeAdLoaderListener {
/**
* 广告加载成功
* @param loader 广告加载对象
* @param ads 广告对象数据
*/
onAdLoadSuccessed(ads: TBNativeAd[]): void;
/**
* 广告加载失败
* @param loader 广告加载对象
* @param error
*/
onAdLoadFailed(error: BusinessError): void;
}7、广告交互监听器
export interface TBNativeAdInteractListener {
/**
* 广告渲染成功【仅模版渲染广告】
* @param adInfo 渠道信息
* @param width 广告组件宽度
* @param height 广告组件高度
*/
onRenderSuccess(adInfo: TBAdInfo, width: number, height: number): void;
/**
* 广告渲染失败【仅模版渲染广告】
* @param adInfo 渠道信息
* @param error 错误描述信息
*/
onRenderFail(adInfo: TBAdInfo, error: BusinessError<void>): void;
/**
* 广告曝光
* @param adInfo 渠道信息
*/
onAdShow(adInfo: TBAdInfo): void;
/**
* 广告点击
* @param adInfo 渠道信息
*/
onAdClick(adInfo: TBAdInfo): void;
/**
* 广告点击关闭
* @param adInfo 渠道信息
* @warning 仅在模版渲染时触发,自渲染由开发者自行渲染关闭按钮。
*/
onAdClose(adInfo: TBAdInfo): void;
}8、广告视频交互监听器
export interface TBAdVideoListener {
/**
* 视频开始播放
*/
onVideoPlayStart(adInfo: TBAdInfo): void;
/**
* 视频播放结束
*/
onVideoPlayComplete(adInfo: TBAdInfo): void;
/**
* 视频播放失败
*/
onVideoPlayError(adInfo: TBAdInfo, error: BusinessError): void;
}9、广告Dislike交互监听器
export interface TBDislikeListener {
/**
* dislike 弹窗show
*/
onShow(): void;
/**
* Dislike 条目被选中
* @param position 条目的index
* @param value 条目的内容
* @param enforce 是否强制关闭广告
*/
onSelected(position: number, value: string, enforce: boolean): void;
/**
* Dislike 弹窗取消
*/
onCancel(): void;
}10、加载信息流广告
// 创建广告请求参数
let request: TBType.AdRequest = {
placementId: 'your placement id',
userId: 'your user ID',
adCount: 1, // 加载广告数量,一次建议1~3条
adWidth: number, // 广告宽度(单位vp)
adHeight: number, //当高度不设置时,则模版自适应高度(以宽度自适应高度)
}
// 创建广告加载对象
let loader = new TBNativeAdLoader(request);
// 设置广告监听
loader.adLoadListener = this;
// 加载广告
loader.loadAdData();11、注册原生自渲染广告计费事件
注意:仅针对自渲染生效
通过registerViewForInteraction方法注册原生自渲染广告计费事件和交互事件,方法说明如下,其中TBClickViewIdList类为SDK提供的集合容器继承自ArrayList;该容器主要作用是收集注册点击事件的UI组件Id;
注意:UI组件id在应用中必须保持唯一(华为鸿蒙官方要求)
/**
* 注册原生自渲染广告点击组件ID
* @param rootAdComponentId 广告布局根节点Id
* @param uiContext 当前组件的上下文
* @param clickViewIds 普通点击Id集合,点击之后,会跳转到落地页,然后再进行后续广告转化
* @param creativeViewIds: 创意点击Id集合,点击之后,会直接进行转化
*/
registerViewForInteraction(clickViewIds: TBClickViewIdList<string>, creativeViewIds: TBClickViewIdList<string>);注意:这里clickViewIds和creativeViewIds的区别,注册在clickViewIds的组件,点击后会跳转到落地页,然后再进行后续的广告转化,注册在creativeViewIds的组件,点击后,会直接进行转化
注册案例:
@Builder
builderAdView(nativeAd: TBNativeAd) {
Column() {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Image(nativeAd.getAppIconUrl())
.id(this.clickViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
.objectFit(ImageFit.Contain)
.height('100%')
.aspectRatio(1)
.borderRadius(5)
.constraintSize({
minWidth: 50, minHeight: 50
})
.backgroundColor(Color.Black)
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) {
Text(nativeAd.getAdTitle())
.id(this.clickViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
.maxLines(1)
Text(nativeAd.getAdDescription())
.id(this.clickViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
.maxLines(1)
.textOverflow({
overflow: TextOverflow.Ellipsis
})
}
.height('100%')
.margin({ left: 10 })
}
.width('100%')
.height(50)
.margin({ top: 10 })
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.End }) {
Row({ space: 3 }) {
if (nativeAd.getAdLogo()) {
Image(nativeAd.getAdLogo())
.objectFit(ImageFit.Cover)
.onComplete((data) => {
if (data?.loadingStatus === 1) {
this.logoWidth = data.width / data.height * 20;
}
})
.width(this.logoWidth).height(20)
} else {
Text(nativeAd!.getAdSource())
.fontColor(Color.Red)
.fontSize(10)
}
}
Button(nativeAd.getActionDescription())
.buttonStyle(ButtonStyleMode.TEXTUAL)
.controlSize(ControlSize.SMALL)
.fontColor(Color.Blue)
.borderWidth(0.5)
.borderColor(Color.Blue)
.backgroundColor(Color.White)
.id(this.creativeViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
}
.width('100%')
.margin({ top: 10 })
}
.width('100%')
.padding(10)
.backgroundColor(Color.Transparent)
.onAppear(() => {
nativeAd.registerViewForInteraction(this.clickViewIds, this.creativeViewIds)
})
}12、展示信息流广告
信息流广告分为自渲染和模版渲染,渲染类型可通过native.getRenderType()判断
12.1、展示自渲染信息流广告
TBNativeAdComponent({
nativeAd: this.nativeAd,
builder: (): void => this.builderAd()
})其中builderAd中为渲染自渲染的布局,由开发者自定布局样式。
注意:自渲染需通过registerViewForInteraction方法注册原生自渲染广告计费事件和交互事件,否则会影响计费
@Builder
builderAd(nativeAd: TBNativeAd) {
Column() {
Stack() {
if (nativeAd.getMaterialType() === TBType.MaterialType.video) {
this.builderVideo()
} else {
this.builderImage()
}
}
.width('100%')
.aspectRatio(1.7778)
.borderRadius(10)
.clip(true)
.backgroundColor(Color.Black)
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Image(nativeAd.getAppIconUrl())
.id(this.clickViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
.objectFit(ImageFit.Contain)
.height('100%')
.aspectRatio(1)
.borderRadius(5)
.constraintSize({
minWidth: 50, minHeight: 50
})
.backgroundColor(Color.Black)
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) {
Text(nativeAd.getAdTitle())
.id(this.clickViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
.maxLines(1)
Text(nativeAd.getAdDescription())
.id(this.clickViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
.maxLines(1)
.textOverflow({
overflow: TextOverflow.Ellipsis
})
}
.height('100%')
.margin({ left: 10 })
}
.width('100%')
.height(50)
.margin({ top: 10 })
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.End }) {
Row({ space: 3 }) {
if (nativeAd.getAdLogo()) {
Image(nativeAd.getAdLogo())
.objectFit(ImageFit.Cover)
.onComplete((data) => {
if (data?.loadingStatus === 1) {
this.logoWidth = data.width / data.height * 20;
}
})
.width(this.logoWidth).height(20)
} else {
Text(nativeAd!.getAdSource())
.fontColor(Color.Red)
.fontSize(10)
}
}
Button(nativeAd.getActionDescription())
.buttonStyle(ButtonStyleMode.TEXTUAL)
.controlSize(ControlSize.SMALL)
.fontColor(Color.Blue)
.borderWidth(0.5)
.borderColor(Color.Blue)
.backgroundColor(Color.White)
.id(this.creativeViewIds.addAdId(util.generateRandomUUID())) //设置组件Id,需要全局保证唯一性,涉及计费
}
.width('100%')
.margin({ top: 10 })
}
.width('100%')
.padding(10)
.backgroundColor(Color.Transparent)
.onAppear(() => {
nativeAd.registerViewForInteraction(this.clickViewIds, this.creativeViewIds)
})
}
@Builder
builderImage() {
if (this.nativeAd?.getImageList() !== undefined) {
Image(this.nativeAd!.getImageList()[0].imageUrl)
.objectFit(ImageFit.Contain)
.width('100%').height('100%')
.backgroundColor(Color.Transparent)
}
}
@Builder
builderVideo() {
TBNativeMediaComponent({ nativeAd: this.nativeAd })
.width('100%')
.width('100%').height('100%')
.backgroundColor(Color.Black)
}12.2、展示模版渲染信息流广告
TBNativeAdComponent({
nativeAd: this.nativeAd
})