Harmony OS搭建广告展示页

有些app需要广告页,有的不需要,我们需要搞个配置。

1. 通过首选项配置存储我们的常用配置,比如是否需要广告页、广告页的路由地址、点击广告页跳转的链接以及广告页倒计时。

1.1 新建一个关于广告页的数据模型。

export class AdvertClass {showAd: boolean = false // 是否展示广告isFull: boolean = true // 是否全屏adTime: number = 5 // 倒计时数据adUrl?: string = "" // 要跳转的连接adImg?: ResourceStr = "" // 图片连接
}

1.2 新建一个关于读取首选项的类,用于读取和设置首选项的广告设置

import { preferences } from '@kit.ArkData'
import { USER_SETTING, USER_SETTING_AD } from '../constants'
import { AdvertClass } from '../viewmodels'export const defaultAd: AdvertClass = {showAd: true,isFull: true,adTime: 3,adImg: $r("app.media.start")
}// 负责首选项的读取
export class UserSetting {context?: Context// 获取仓库getStore () {return preferences.getPreferencesSync(this.context || getContext(), {name: USER_SETTING})}// 设置用户广告async setUserAd(ad: AdvertClass) {const store = this.getStore()store.putSync(USER_SETTING_AD, ad)await store.flush()  // 让外界能够控制自己的流程}// 获取用户广告getUserAd() {const store = this.getStore()return store.getSync(USER_SETTING_AD, defaultAd) as AdvertClass}
}export const userSetting = new UserSetting() // 导出一个单例

上面还用到了两个常量,我们需要在constants目录下定义一个文件专门用来记录setting

export const USER_SETTING = 'fast_driver_setting' // 用来存储用户设置的首选项的key
export const USER_SETTING_AD = 'fast_driver_setting_ad' // 用来存储用户设置广告首选项的key

1.3 在ability中判断

async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {// Main window is created, set main page for this abilityhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');userSetting.context = this.context // 首选项赋值上下文// 发起一个向云端获取广告数据的请求const ad = await new Promise<AdvertClass>((resolve, reject) => {setTimeout(() => {resolve(cloudAd)}, 500)})await userSetting.setUserAd(ad) // 将广告设置到首选项// 此时应该判断是不是展示广告?if (ad.showAd) {windowStage.loadContent('pages/Start/Start');} else {windowStage.loadContent('pages/Index');}}

1.4 模拟一个请求,给一个默认广告,写入首选项-正常加载主页

实现start页的页面结构及倒计时逻辑

import { AdvertClass, userSetting } from 'basic'
import { router } from '@kit.ArkUI'@Entry
@Component
struct Start {// 需要广告对象@Statead: AdvertClass = new AdvertClass()timer: number = -1 // 用来记录定时器的标记// @State// ad: Partial<AdvertClass> = {}aboutToAppear(): void {// 获取首选项的广告数据给到adthis.getAdInfo()}getAdInfo() {// 首选项的读取this.ad = userSetting.getUserAd()// 开启倒计时了if (this.ad.showAd) {// 如果真的展示广告要开始倒计时this.timer = setInterval(() => {if (this.ad.adTime === 0) {clearInterval(this.timer)this.toMain()return // return一定要写}this.ad.adTime--}, 1000)}}// 去主页的方法toMain() {router.replaceUrl({url: 'pages/Index'})}aboutToDisappear(): void {clearInterval(this.timer)}build() {RelativeContainer() {if (this.ad.showAd) {Image(this.ad.adImg).width("100%").height("100%").objectFit(ImageFit.Cover)Text(`${this.ad.adTime}秒跳过`).padding({left: 10,right: 10}).alignRules({right: {anchor: '__container__',align: HorizontalAlign.End},top: {anchor: '__container__',align: VerticalAlign.Top}}).borderRadius(15).height(30).fontSize(14).backgroundColor($r("app.color.background_page")).margin({right: 20,top: 20}).onClick(() => {// 此时跳过广告// 跳转到主页this.toMain()})}}.height('100%').width('100%')}
}

1.5 使用子窗口模式加载广告

我们可以使用windowStage的createSubWindow来实现当前页面上创建一个窗口

 if (result.showAd) {const win = await windowStage.createSubWindow("ad_window")await win.showWindow()win.setUIContent("pages/Start/Start")}

2.  window窗口广告模式

封装window窗口广告模式

import { display, window } from '@kit.ArkUI'
import { util } from '@kit.ArkTS'export class AdManager {context?: Context // 是给ability使用的private winNames: string [] = []// 展示广告 采用windows窗口的创建和销毁的方式async showAd(url: string, width?: number, height?: number) {if (url) {let name = `win_${util.generateRandomUUID()}`const win = await window.createWindow({name,windowType: window.WindowType.TYPE_DIALOG,ctx: this.context || getContext()})if (width && width >= 320 && height && height >= 240) {const screen = display.getDefaultDisplaySync()let mainWidth = vp2px(width)let mainHeight = vp2px(height)win.resizeAsync(mainWidth, mainHeight)win.moveWindowToAsync((screen.width - mainWidth) / 2, (screen.height - mainHeight) / 2)}await win.showWindow() // 展示窗口win.setUIContent(url) // 设置地址this.winNames.push(name)return name}return ""}// 关闭广告async closeAd(name?: string) {if (name) {window.findWindow(name).destroyWindow()this.winNames = this.winNames.filter(item => item !== name) //清空数组内容} else {// 不传就认为 想关闭所有let index = 0while (index < this.winNames.length) {await window.findWindow(this.winNames[index]).destroyWindow()index++}this.winNames = [] // 清空数组}}
}export const adManger = new AdManager()

Start页面代码

import { adManger, AdvertClass, userSetting } from 'basic'
import { router, window } from '@kit.ArkUI'@Entry
@Component
struct Start {// 需要广告对象@Statead: AdvertClass = new AdvertClass()timer: number = -1 // 用来记录定时器的标记// @State// ad: Partial<AdvertClass> = {}aboutToAppear(): void {// 获取首选项的广告数据给到adthis.getAdInfo()}getAdInfo() {// 首选项的读取this.ad = userSetting.getUserAd()// 开启倒计时了if (this.ad.showAd) {// 如果真的展示广告要开始倒计时this.timer = setInterval(() => {if (this.ad.adTime === 0) {clearInterval(this.timer)this.toMain()return // return一定要写}this.ad.adTime--}, 1000)}}// 去主页的方法toMain() {// router.replaceUrl({//   url: 'pages/Index'// })// 销毁当前的窗口clearInterval(this.timer) // 先清理一下定时器adManger.closeAd()}aboutToDisappear(): void {clearInterval(this.timer)}build() {RelativeContainer() {if (this.ad.showAd) {Image(this.ad.adImg).width("100%").height("100%").objectFit(ImageFit.Cover)Text(`${this.ad.adTime}秒跳过`).padding({left: 10,right: 10}).alignRules({right: {anchor: '__container__',align: HorizontalAlign.End},top: {anchor: '__container__',align: VerticalAlign.Top}}).borderRadius(15).height(30).fontSize(14).backgroundColor($r("app.color.background_page")).margin({right: 20,top: 20}).onClick(() => {// 此时跳过广告// 跳转到主页this.toMain()})}}.height('100%').width('100%')}
}

EntryAbility完整代码

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { adManagerFinal, adManger, AdvertClass, userSetting } from 'basic';// 云端广告
const cloudAd: AdvertClass = {showAd: true,isFull: false,adTime: 100,adImg: $r("app.media.start")
}export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');}onDestroy(): void {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');}async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {// Main window is created, set main page for this abilityhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');userSetting.context = this.context // 首选项赋值上下文// 发起一个向云端获取广告数据的请求const ad = await new Promise<AdvertClass>((resolve, reject) => {setTimeout(() => {resolve(cloudAd)}, 500)})await userSetting.setUserAd(ad) // 将广告设置到首选项// 此时应该判断是不是展示广告?// 1. 第一种页面方式// if (ad.showAd) {//   windowStage.loadContent('pages/Start/Start');// } else {//   windowStage.loadContent('pages/Index');// }// 2. 第二种window窗口模式// if (ad.showAd) {//   const win = await windowStage.createSubWindow("ad_win") // 二级窗口的实际对象//   await win.showWindow() // 展示二级窗口//   win.setUIContent("pages/Start/Start")// }await windowStage.loadContent('pages/Index'); // 必须等到有了UIContext才可以使用if (ad.showAd) {adManagerFinal.context = this.context// adManger.context = this.context// await adManger.showAd("pages/Start/Start", 330, 440)adManagerFinal.showAd(ad) // 展示广告}}onWindowStageDestroy(): void {// Main window is destroyed, release UI related resourceshilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground(): void {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}

3.  还可采用与页面解耦的方式实现广告

import { AdvertClass } from '../viewmodels'
import { ComponentContent, promptAction, window } from '@kit.ArkUI'
import { util } from '@kit.ArkTS'// 展示广告的结构最重要写的代码
@Builder
function AdBuilder(ad: AdvertClass) {Column() {Image(ad.adImg).width("100%").height("100%").objectFit(ImageFit.Cover).borderRadius(10)Row() {Image($r("app.media.ic_btn_close")).width(14).aspectRatio(1).fillColor("#ccc")}.width(30).aspectRatio(1).justifyContent(FlexAlign.Center).borderRadius(15).border({color: '#ff343232',width: 2}).margin({top: 40}).onClick(() => {if (ad.dialogName) {adManagerFinal.closeAd(ad.dialogName) //  ? name从哪里进来}})}.width(ad.isFull ? "100%" : "80%").height(ad.isFull ? "100%" : "50%")
}export class AdManagerFinal {context?: Context// 所有的弹窗都放到这个map中 通过name来标识private map: Map<string, ComponentContent<AdvertClass>> = new Map()// 实际上需要广告async showAd(ad: AdvertClass) {// 按照文档实现// UIContext上下文必须得等到页面初始化之后才可以进行获取// 生成一个namelet name = `dialog_${util.generateRandomUUID()}`// 通过当前的主窗口来获取const mainWin = await window.getLastWindow(this.context || getContext())let uiContext = mainWin.getUIContext() // 拿到UIContextlet promptAction = uiContext.getPromptAction();ad.dialogName = name // 目的是将dialog的弹窗名称传递到builder中let contentNode = new ComponentContent(uiContext, wrapBuilder(AdBuilder), ad);let options: promptAction.BaseDialogOptions = {alignment: DialogAlignment.Center,autoCancel: false};this.map.set(name, contentNode) // 将key/value写入到map中promptAction.openCustomDialog(contentNode, options);// 一般半屏广告 是得用户手动点击才能关闭的 一般不会自动关闭// setTimeout(() => {//   promptAction.closeCustomDialog(contentNode)// }, 2000)}async closeAd(name: string) {if (name) {const mainWin = await window.getLastWindow(this.context || getContext())let uiContext = mainWin.getUIContext() // 拿到UIContextlet promptAction = uiContext.getPromptAction();promptAction.closeCustomDialog(this.map.get(name))// 清理mapthis.map.delete(name) // 删除已经关闭的弹窗}}
}export const adManagerFinal = new AdManagerFinal()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/58711.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国内AI大模型学习平台

据不完全统计&#xff0c;目前&#xff0c;国内有几大AI大模型学习平台可供选择&#xff1a; 1.昇思大模型平台&#xff1a;这是一个集算法选型、创意分享、模型实验和大模型在线体验于一体的AI学习与实践社区。 2.魔搭社区&#xff1a;提供AI模型、数据集和应用的开发与探索平…

JVM(HotSpot):finally块的相关问题

文章目录 前言一、finally 中 return1、代码案例2、字节码 二、finally 中修改值1、代码案例2、字节码 三、总结 前言 try {}catch (Exception e){}finally {}如上代码&#xff0c;如果发生异常&#xff0c;我们在可以通过catch块捕获 捕获后&#xff0c;是打印报错信息还是怎么…

新建Flutter工程

1.使用Android studio新建New Flutter project&#xff1b; 2.最新版本兼容性配置 android-settings.gradle文件下&#xff1a; pluginManagement {//.......repositories {//阿里云镜像地址&#xff1a;maven { url https://maven.aliyun.com/repository/public/ }maven { …

设计模式4-工厂模式策略模式

目录 一 工厂模式 1.1 思想 1.2 案例 1.2.1 接口 1.2.2 实现类 1.2.3 工厂类 1.2.4 调用 二 策略模式 2.1 思想 2.2 案例 2.2.1 接口 2.2.2 实现类 2.2.3 策略类 2.2.4 调用 三 工厂模式策略模式 3.1 思想 3.2 案例 3.2.1 接口 3.2.2 实现类 3.2.3 定义F…

常见问题 | 数字签名如何保障电子商务交易安全?

如何解决电商交易中数据泄露、交易欺诈等问题&#xff1f; 数字签名是一种类似于电子“指纹”的安全技术&#xff0c;它在电子商务中扮演着至关重要的角色。随着电子商务的迅猛发展&#xff0c;网上交易的数量不断增加&#xff0c;确保交易的安全性和完整性成为了亟待解决的问题…

不适合的学习方法

文章目录 不适合的学习方法1. 纯粹死记硬背2. 过度依赖单一资料3. 线性学习4. 被动学习5. 一次性学习6. 忽视实践7. 缺乏目标导向8. 过度依赖技术9. 忽视个人学习风格10. 过于频繁的切换 结论 以下是关于不适合的学习方法的更详细描述&#xff0c;包括额外的内容和相关公式&…

HTML5 + CSS3 + JavaScript 编程语言学习教程

HTML5 CSS3 JavaScript 编程语言学习教程 欢迎来到这篇关于 HTML5、CSS3 和 JavaScript 的详细学习教程&#xff01;无论你是初学者还是有一定基础的开发者&#xff0c;这篇文章都将帮助你深入理解这三种技术的核心概念、语法和应用。 目录 HTML5 1.1 HTML5 简介1.2 HTML5 …

【安全性分析】正式安全分析与非正式安全分析

安全性分析-系列文章目录 第一章 【安全性分析】正式安全分析与非正式安全分析 第二章 【安全性分析】BAN逻辑 (BAN Logic) 文章目录 安全性分析-系列文章目录前言一、正式安全分析1. 理想化模型(如随机预言机模型)2. 标准模型(Standard Model)3. 形式化验证4. 数学证明二…

win11安装安卓apk原生应用,并设置网络代理

一、win11安装安卓apk原生应用&#xff0c;查看https://blog.csdn.net/qq_33704787/article/details/123658419https://blog.csdn.net/qq_33704787/article/details/123658419 主要是安装&#xff1a;Windows Subsystem for Android™ with Amazon Appstore 二、使用ABD工具设…

C语言的知识框架

C语言知识框架概览 C语言是一种广泛使用的计算机编程语言&#xff0c;以其高效、灵活和接近硬件的特性而闻名。学习C语言通常涉及以下几个方面的知识&#xff1a; 1.基础概念&#xff1a;了解C语言的历史、特点、环境搭建和首个程序的编写。 2.数据类型&#xff1a;熟悉基本数…

无人机救援系统基本组成

无人机救援系统基本组成 1. 源由2. 组成2.1 无人机载具2.1.1 多旋翼2.1.2 垂起固定翼2.1.3 智能避障2.1.4 物资投递 2.2 智能吊舱2.2.1 云台2.2.2 高清摄像2.2.3 红外热成像2.2.4 激光测距2.2.5 目标跟踪 2.3 通讯链路2.3.1 超长距离通信2.3.2 长距离通信2.3.3 中等距离通信 2.…

固态硬盘写入文件是以后可能会移动其他文件

固态硬盘写入文件时可能会移动其他文件。当固态硬盘小文件特别多时就会拉低性能。 是的&#xff0c;您的理解是正确的。机械硬盘&#xff08;HDD&#xff09;和固态硬盘&#xff08;SSD&#xff09;在文件移动和存储管理方面有以下几个主要区别&#xff1a; 1. **存储介质**&am…

Flink CDC系列之:学习理解核心概念——Transform

Flink CDC系列之&#xff1a;学习理解核心概念——Transform Transform参数元数据字段函数比较函数逻辑函数字符串函数时间函数条件函数 示例添加计算列参考元数据列使用通配符投影所有字段添加过滤规则重新分配主键重新分配分区键指定表创建配置分类映射用户定义函数已知限制 …

ubuntu基于docker-compose部署mysql5.7和mysql8.0

docker-compose部署系统简单方便&#xff0c;出现问题也可以快速重来。mysql5.7和mysql8.0是两个比较流行的mysql版本。简单部署记录下来&#xff0c;供大家参考。 1、准备docker-compose环境 安装docker.io和docker-compose sudo apt install docker.iosudo curl -L "h…

conda的对应环境下安装cuda11.0和对应的cudnn

在 Conda 环境中安装 CUDA 11.0 和对应的 cuDNN&#xff0c;可以按照以下步骤进行&#xff1a; 一. 环境配置 1. 创建 Conda 环境 首先&#xff0c;创建一个新的 Conda 环境&#xff08;可选&#xff09;&#xff1a; conda create -n myenv python3.8 conda activate myen…

每天五分钟深度学习pytorch:基于pytorch搭建普通全连接神经网络

本文重点 本文我们通过pytorch搭建普通的全连接神经网络,这里我们就不介绍什么是全连接神经网络了,如果不知道的可以看我的机器学习专栏,或者深度学习专栏,它们对全连接神经网络都进行了简单的介绍。 代码 import torch from torch import nn class ThreeNet(nn.Module)…

python opencv1

一、基本参数 OpenCV的全称是Open Source Computer Vision Library,是一个开放源代码的计算机视觉库。 安装&#xff1a;pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple imprort cv2 1、显示窗口 cv2.namedWindow(winname, flagsNone) &#xff1a;w…

unity学习-异步场景加载

我们的项目在加载场景的时候如果需要加载的场景过大的话就会卡很久&#xff0c; 我们可以摒弃掉一定要到最后才加载下一个场景的观念&#xff0c;可以将加载场景的任务设置在任何地方&#xff0c;放在携程函数下&#xff0c;加载场景的任务和游戏运行任务同时进行 这叫做异步…

故障诊断 | MTF-TLSSA-DarkNet-GRU-MSA迁移学习故障识别程序(t分布+莱维飞行改进麻雀优化)

故障诊断 | 故障诊断实例代码 目录 故障诊断 | 故障诊断实例代码效果一览基本介绍程序设计参考资料 效果一览 基本介绍 利用了迁移学习和多项技术改进&#xff0c;包括麻雀搜索法、DarkNet19、GRU、多头注意力机制等&#xff0c;以提高故障识别的准确性和效率 模型框架&#x…

【一起python】使用python实现学生管理系统

文章目录 &#x1f4dd;前言&#x1f320;主函数man&#x1f309;菜单menu&#x1f309;添加学生信息&#x1f309;展示目前学生信息&#x1f309;查找学生&#x1f309;删除同学信息&#x1f309;退出程序 &#x1f320;python完整代码&#x1f6a9;总结 &#x1f4dd;前言 &…