HarmonyOS鸿蒙Next中uniapp开发的应用如何通过嵌入原生组件的方式添加广告呢?比如banner,插屏,激励视频
HarmonyOS鸿蒙Next中uniapp开发的应用如何通过嵌入原生组件的方式添加广告呢?比如banner,插屏,激励视频
【问题描述】:uniapp开发的鸿蒙应用. 如何通过嵌入原生组件的方式添加广告呢?比如banner,插屏,激励视频。
【问题现象】:已经用uniapp开发好应用,上架了鸿蒙next,现在想添加广告变现。官方目前还没有适配,然后自己通过uts嵌入原生组件的方式开发原生广告,页面中不显示,原生日志打印提示广告也加载完成。
【版本信息】:HBuilder X 5.07
【复现代码】:
import { NativeEmbedBuilderOptions, defineNativeEmbed } from "@dcloudio/uni-app-runtime"
import { abilityAccessCtrl, common, PermissionRequestResult } from '@kit.AbilityKit';
import { advertising, AutoAdComponent, identifier } from '@kit.AdsKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Component
struct adsBannerComponent {
@State visibilityState: Visibility = Visibility.None;
// 广告请求参数
private adRequestParams: advertising.AdRequestParams = {
// 'h5xkz3mbr2'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
adId: 'h5xkz3mbr2',
// 横幅广告类型
adType: 8,
// 广告位宽
adWidth: 360,
// 广告位高
adHeight: 57
};
// 广告配置参数,开发者可根据项目实际情况设置
private adOptions: advertising.AdOptions = {};
// 广告展示参数,开发者可根据项目实际情况设置
private adDisplayOptions: advertising.AdDisplayOptions = {
// 广告轮播的时间间隔,单位ms,取值范围[30000, 120000]
refreshTime: 30000
};
private ratio: number = 1;
private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
async aboutToAppear(): Promise<void> {
// 开放匿名设备标识符
this.adRequestParams.oaid = await requestOAID(this.context);
console.log('this.adRequestParams',this.adRequestParams);
this.visibilityState = Visibility.Visible;
if (this.adRequestParams.adWidth && this.adRequestParams.adHeight) {
this.ratio = this.adRequestParams.adWidth / this.adRequestParams.adHeight;
}
}
build() {
Stack({ alignContent: Alignment.Bottom }) {
Row() {
AutoAdComponent({
adParam: this.adRequestParams,
adOptions: this.adOptions,
displayOptions: this.adDisplayOptions,
interactionListener: {
onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
switch (status) {
case 'onAdOpen':
console.log('打开广告');
break;
case 'onAdClick':
console.log('点击广告');
break;
case 'onAdClose':
console.log('关闭广告');
this.visibilityState = Visibility.None;
break;
case 'onAdLoad':
console.log('广告加载成功');
break;
case 'onAdFail':
console.log('广告加载失败');
this.visibilityState = Visibility.None;
break;
}
}
}
}).width('100%')
.height('100%')
}
.width('100%')
.aspectRatio(this.ratio)
.visibility(this.visibilityState)
}
}
}
async function requestOAID(context: Context): Promise<string | undefined> {
// 向用户请求授权广告跨应用关联访问权限
let isPermissionGranted: boolean = false;
try {
const atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
const result: PermissionRequestResult =
await atManager.requestPermissionsFromUser(context, ['ohos.permission.APP_TRACKING_CONSENT']);
isPermissionGranted = result.authResults[0] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
} catch (err) {
hilog.error(0x0000, 'testTag', `Failed to request permission. Code is ${err.code}, message is ${err.message}`);
}
if (isPermissionGranted) {
hilog.info(0x0000, 'testTag', 'Succeeded in requesting permission');
try {
const oaid = await identifier.getOAID();
hilog.info(0x0000, 'testTag', 'Succeeded in getting OAID');
return oaid;
} catch (err) {
hilog.error(0x0000, 'testTag', `Failed to get OAID. Code is ${err.code}, message is ${err.message}`);
}
} else {
hilog.error(0x0000, 'testTag', 'Failed to request permission. User rejected');
}
return undefined;
}
@Builder
function adsBannerBuilder(options: NativeEmbedBuilderOptions) {
adsBannerComponent()
}
defineNativeEmbed('adsbanner', {
builder: adsBannerBuilder
})

【尝试解决方案】:不涉及
更多关于HarmonyOS鸿蒙Next中uniapp开发的应用如何通过嵌入原生组件的方式添加广告呢?比如banner,插屏,激励视频的实战教程也可以访问 https://www.itying.com/category-93-b0.html
尊敬的开发者,您好,uni-app嵌入ArkUI组件使用了同层渲染,广告不支持纹理导出,NodeController挂载节点时不能设置为NodeRenderType.RENDER_TYPE_TEXTURE,nodeRenderType需要设置为NodeRenderType.RENDER_TYPE_DISPLAY请参考uni-app官网链接修改,以下为修改后的参考代码。
import { NativeEmbedBuilderOptions, defineNativeEmbed } from "@dcloudio/uni-app-runtime"
import { abilityAccessCtrl, common, PermissionRequestResult } from '@kit.AbilityKit';
import { advertising, AutoAdComponent, identifier } from '@kit.AdsKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { NodeRenderType } from '@kit.ArkUI'
@Component
struct adsBannerComponent {
@State visibilityState: Visibility = Visibility.None;
// 广告请求参数
private adRequestParams: advertising.AdRequestParams = {
// 'h5xkz3mbr2'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
adId: 'h5xkz3mbr2',
// 横幅广告类型
adType: 8,
// 广告位宽
adWidth: 360,
// 广告位高
adHeight: 57
};
// 广告配置参数,开发者可根据项目实际情况设置
private adOptions: advertising.AdOptions = {};
// 广告展示参数,开发者可根据项目实际情况设置
private adDisplayOptions: advertising.AdDisplayOptions = {
// 广告轮播的时间间隔,单位ms,取值范围[30000, 120000]
refreshTime: 30000
};
private ratio: number = 1;
private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
async aboutToAppear(): Promise<void> {
// 开放匿名设备标识符
this.adRequestParams.oaid = await requestOAID(this.context);
console.log('this.adRequestParams', this.adRequestParams);
this.visibilityState = Visibility.Visible;
if (this.adRequestParams.adWidth && this.adRequestParams.adHeight) {
this.ratio = this.adRequestParams.adWidth / this.adRequestParams.adHeight;
}
}
build() {
Row() {
AutoAdComponent({
adParam: this.adRequestParams,
adOptions: this.adOptions,
displayOptions: this.adDisplayOptions,
interactionListener: {
onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
switch (status) {
case 'onAdOpen':
console.log('打开广告');
break;
case 'onAdClick':
console.log('点击广告');
break;
case 'onAdClose':
console.log('关闭广告');
this.visibilityState = Visibility.None;
break;
case 'onAdLoad':
console.log('广告加载成功');
break;
case 'onAdFail':
console.log('广告加载失败');
this.visibilityState = Visibility.None;
break;
}
}
}
})
.width('100%')
.height('100%')
.aspectRatio(this.ratio)
.visibility(this.visibilityState)
.backgroundColor(Color.Red)
}
}
}
async function requestOAID(context: Context): Promise<string | undefined> {
// 向用户请求授权广告跨应用关联访问权限
let isPermissionGranted: boolean = false;
try {
const atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
const result: PermissionRequestResult =
await atManager.requestPermissionsFromUser(context, ['ohos.permission.APP_TRACKING_CONSENT']);
isPermissionGranted = result.authResults[0] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
} catch (err) {
hilog.error(0x0000, 'testTag', `Failed to request permission. Code is ${err.code}, message is ${err.message}`);
}
if (isPermissionGranted) {
hilog.info(0x0000, 'testTag', 'Succeeded in requesting permission');
try {
const oaid = await identifier.getOAID();
hilog.info(0x0000, 'testTag', 'Succeeded in getting OAID');
return oaid;
} catch (err) {
hilog.error(0x0000, 'testTag', `Failed to get OAID. Code is ${err.code}, message is ${err.message}`);
}
} else {
hilog.error(0x0000, 'testTag', 'Failed to request permission. User rejected');
}
return undefined;
}
@Builder
function adsBannerBuilder(options: NativeEmbedBuilderOptions) {
adsBannerComponent()
.width(options.width)
.height(options.height)
}
defineNativeEmbed('adsbanner', {
builder: adsBannerBuilder,
nodeRenderType: NodeRenderType.RENDER_TYPE_DISPLAY
})
更多关于HarmonyOS鸿蒙Next中uniapp开发的应用如何通过嵌入原生组件的方式添加广告呢?比如banner,插屏,激励视频的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
你这个问题里,最关键的结论其实不是 AdsKit,而是 uni-app 的原生嵌入模式本身。
先说结论
你现在这套写法:
defineNativeEmbed(...)NativeEmbedBuilderOptions- 在 uni-app 页面里嵌一个 ArkTS 原生组件
这条路在鸿蒙上大概率就是不支持的,所以会出现:
- 原生日志里
onAdLoad成功 - 但页面里就是不显示
原因是 DCloud 官方文档已经写了:
uni-app兼容模式的 uts 组件开发- 不支持鸿蒙
- 只有
uni-app x的 标准模式,基于native-view,才支持 HarmonyOS 见 DCloud 文档:uts插件 - 组件开发
文档原话核心意思是:
uni-app兼容模式:支持 uni-app 的 app-nvue 和 uni-app x 的 app-uvue,不支持鸿蒙标准模式:仅支持 uni-app x,但全平台支持,其中包含 HarmonyOS 同页可见:uts插件 - 组件开发
这也解释了你现在的现象
你现在不是“广告没加载成功”,而是更像:
AdsKit原生广告组件已经加载完成- 但 uni-app 页面容器并没有真正把这个原生组件渲染到鸿蒙页面文档流里
所以看起来就是:
- 逻辑通了
- 广告回调通了
- 但 UI 不显示
这和你描述的现象是完全一致的。
你当前这条路里,哪些广告能做,哪些不能做
1. Banner
如果你想要的是页面内嵌 banner,那它本质上是一个“原生组件嵌入页面”的问题。
这在你当前的 uni-app 经典工程 里,鸿蒙侧基本不可行,原因就是上面说的:
defineNativeEmbed这类兼容模式组件- 鸿蒙不支持
2. 插屏、激励视频
这两个其实不一定要走“页面内嵌组件”。
DCloud 文档也区分了:
- 组件:适合页面里嵌一个区域
- API:适合全屏 UI 或弹出式原生界面 见:uts插件 - 组件开发
而:
- 插屏广告
- 激励视频广告
本身就是全屏/弹窗式广告,所以更适合封装成 UTS API 插件,而不是嵌入组件。
也就是说:
Banner:你现在这套 uni-app 经典工程里不适合插屏/激励视频:可以改成 UTS 原生 API 调用 方式做
另外,AdsKit 本身是没问题的
华为官方文档确认:
Banner可以用AutoAdComponentonAdLoad表示广告加载成功AutoAdComponent支持Phone / Tablet / PC/2in1见:横幅广告开发指导、@ohos.advertising.AutoAdComponent
所以你这段代码本身从 AdsKit 角度看并不离谱,甚至和官方示例很接近。 问题更可能就是:
广告组件在原生侧创建了,但 uni-app 鸿蒙页面没有承载它。
你现在最可行的方案
方案 1:插屏 + 激励视频 先做成 UTS API 插件
这是最现实的。
因为这两类广告不是页面内嵌型,可以走:
- UTS 暴露
showInterstitialAd() - UTS 暴露
showRewardAd() - 页面里直接 JS/UTS 调用
这种方式不依赖页面内嵌原生组件,成功率最高。
方案 2:Banner 如果一定要做页面内嵌,建议迁移到 uni-app x
如果你必须做鸿蒙原生 Banner 内嵌:
- 最好改成
uni-app x - 用 DCloud 官方说的 标准模式
- 基于
native-view做原生组件承载 见:uts插件 - 组件开发
方案 3:如果项目必须留在经典 uni-app
那就建议:
- 放弃鸿蒙原生 Banner 内嵌
- 只先接 插屏 / 激励视频
- Banner 改成其他替代变现方案
你代码里还有几个次要点
这些不是主因,但后面真做原生插件时建议一起注意:
1. 权限和 module 配置
UTS 鸿蒙插件里,权限要通过插件自己的 module.json5 配置,DCloud 文档有说明:uts for HarmonyOS
2. Context 获取方式
DCloud 也建议在鸿蒙插件里通过宿主窗口拿 getHostContext(),而不是按普通页面 JS 思路处理:uts for HarmonyOS
3. 设备类型限制
Banner 只支持:
PhoneTabletPC/2in1不支持所有设备类型。见:横幅广告
一句话结论
不是广告没加载,而是你现在用的 uni-app 原生嵌入方案在鸿蒙上不成立。
所以建议你这样定方案:
Banner:要么迁移uni-app x做native-view原生组件,要么暂时不做插屏/激励视频:直接做成 UTS API 插件,不走嵌入组件
你的外层 Row 依赖 aspectRatio 撑高,但在数据未返回时,ratio 计算可能为 1,导致 Row 高度过小而不可见。可以试试是给最外层 Row 加一个最小高度,确保点击区域存在:
Row() {
// ...
}
.width('100%')
.constraintSize({ minHeight: 50 }) // 保证行可见
.aspectRatio(this.ratio)
.visibility(this.visibilityState)
找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17,
学习一下
从现象看,“广告已加载但页面不显示”优先排查广告类型和展示组件是否匹配,以及 uni-app 原生嵌入组件是否真的布局出来。横幅广告通常用 AutoAdComponent;原生、开屏、贴片广告用 AdComponent;插屏和激励视频一般不是嵌入页面组件,而是加载后调用 showAd 展示。建议先在纯 ArkTS 页面只跑通 banner,再放入 native embed,并确认外层容器有明确 width/height,没有被滚动容器裁剪或被 zIndex/overflow 影响。
。
期待HarmonyOS能继续优化多屏协同功能,让跨设备体验更加完美。

<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<embed class="native-button" tag="button" :options="options" @buttonclick="onClick"></embed>
<embed class="native-button" tag="adsbanner"></embed>
</view>
</template>
<script>
import '@/uni_modules/harmony-ads'
export default {
data() {
return {
title: 'Hello',
options: {
label: '广告测试'
}
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.native-button {
display: block;
width: 200px;
height: 50px;
margin: 10px auto;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
需要编写插件搭桥,可以试试embed的方式引入广告
<embed class="native-button" tag="adsbanner"></embed>
就是引入了但是页面不显示 写一个button按钮或者地图什么的都显示 就是这个广告不显示
你可以新建一个项目,然后用最小化验证的方式去测试一下,这样就可以测出到底是这玩意儿不生效,还是因为你原本项目中的什么东西干扰了,
我新建了一个项目测试了一下感觉就是不生效 代码跟效果我新开了一个楼
在鸿蒙Next中,uniapp应用通过创建原生插件(如ExtensionAbility或Service)集成广告SDK,使用NativeContainer或XComponent等ArkUI原生组件嵌入广告视图。通过JSBridge暴露接口,前端调用Native方法加载并展示banner、插屏或激励视频广告,各广告类型需在原生侧分别实现对应组件渲染与生命周期管理。
问题在于 Stack 和内部 Row 的尺寸约束不足,导致 AutoAdComponent 计算出高度为 0,虽然广告加载成功但不可见。修改布局,直接给包裹容器一个明确高度即可解决。
精简后的代码修改如下(Banner 部分):
struct adsBannerComponent {
// ... 其余代码不变 ...
build() {
// 使用 Column 替代 Stack,确保组件有确定的约束
Column() {
AutoAdComponent({
adParam: this.adRequestParams,
adOptions: this.adOptions,
displayOptions: this.adDisplayOptions,
interactionListener: { /* ... */ }
})
.width('100%')
.height('100%')
}
.width('100%')
.height(57) // 或保持 aspectRatio,但必须给一个高度基准
.visibility(this.visibilityState)
}
}
对于插屏和激励视频广告,它们不应作为嵌入组件,需在 onAdLoad 中调用 ad.show() 进行全屏展示,不可内嵌到页面布局。

