HarmonyOS NEXT中自定义广告的四种模式-根据场景选择

打印 上一主题 下一主题

主题 1607|帖子 1607|积分 4821


一、应用场景

app冷启动/热启动-有广告需求,就打开广告页,没有的话就去登录或者主页
华为有广告业务,但是我们不用
自定义一个ad模块,但是根据不同的业务场景和需求,可以使用不同的打开广告方式

  • 应用启动时,有广告则直接进入广告页,定时竣事或点击跳过,跳转到首页
  • 打开子窗口,然后通过销毁子窗口方式关闭广告
  • 封装window窗口广告模式,关闭时直接调用封装的关闭方法
  • 采用与页面解耦的模式实现广告,关闭时候直接调用封装的关闭方法
总结处有附完备代码
二、新建一个关于广告类的数据模子

1.创建广告类

这个广告模子其实在那里创建不影响,只要导出,在需要用到的地方可以正常导入就行,由于本项目有har包,就直接创建到har包里-basic- viewmodels/advert.ets
  1. export class AdvertClass {
  2.   showAd: boolean = false // 是否展示广告
  3.   isFull: boolean = true // 是否全屏
  4.   adTime: number = 5 // 倒计时数据
  5.   adUrl?: string = "" // 要跳转的连接
  6.   adImg?: ResourceStr = "" // 图片连接
  7. }
  8. // 全屏广告 半屏广告
复制代码
2.本地存储广告用来读取和设置广告

这里用的方式不同于首选项方式,而是使用AppStorage和持久化本地存储的方式,这种方式更加简单。
当然无论是首选项的方式还是什么都只是将广告信息存储,都不影响后面任何模式的使用。
utils/setting.ets
  1. import { USER_SETTING, USER_SETTING_AD } from '../constants'
  2. import { AdvertClass } from '../viewmodels'
  3. export const defaultAd: AdvertClass = {
  4.   showAd: true,
  5.   isFull: true,
  6.   adTime: 3,
  7.   adImg: $r("app.media.start")
  8. }
  9. // 首选项方式,每次使用前记得给context赋值
  10. // 负责首选项的读取
  11. // export class UserSetting {
  12. //   context?: Context
  13. //   // 获取仓库
  14. //   getStore () {
  15. //     return preferences.getPreferencesSync(this.context || getContext(), {
  16. //       name: USER_SETTING
  17. //     })
  18. //   }
  19. //   // 设置用户广告
  20. //   async setUserAd(ad: AdvertClass) {
  21. //     const store = this.getStore()
  22. //     store.putSync(USER_SETTING_AD, ad)
  23. //     await store.flush()  // 让外界能够控制自己的流程
  24. //   }
  25. //   // 获取用户广告
  26. //   getUserAd() {
  27. //     const store = this.getStore()
  28. //     return store.getSync(USER_SETTING_AD, defaultAd) as AdvertClass
  29. //   }
  30. // }
  31. export class UserSetting{
  32.   // 初始化仓库
  33.   initUserSetting(){
  34.     PersistentStorage.persistProp<AdvertClass>(USER_SETTING_AD,defaultAd)
  35.   }
  36.   // 设置用户广告
  37.   setUserAd(ad: AdvertClass) {
  38.     AppStorage.setOrCreate<AdvertClass>(USER_SETTING_AD, ad)
  39.   }
  40.   // 获取用户广告
  41.   getUserAd(){
  42.     return AppStorage.get<AdvertClass>(USER_SETTING_AD)
  43.   }
  44. }
  45. export const userSetting = new UserSetting() // 导出一个单例
复制代码
这里初始化本地仓库的代码不能放到要在EntryAbility中的onWindowStageCreate中,官网的意思最早也是UI实例初始化后才能持久化。
PersistentStorage:持久化存储UI状态
PersistentStorage和UI实例相关联,持久化操纵需要在UI实例初始化成功后(即loadContent传入的回调被调用时)才可以被调用,早于该时机调用会导致持久化失败。
EntryAbility.ets
  1. onWindowStageCreate(){
  2. // ...省略
  3. // 初始化广告仓库
  4. windowStage.loadContent('pages/Index', (err) => {
  5.       if (err.code) {
  6.         hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
  7.         return;
  8.       }
  9.       // 初始化广告仓库
  10.       userSetting.initUserSetting()
  11.       hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
  12.     });
  13. // ...省略
  14. }
复制代码
这里还要设置常量USER_SETTING_AD,但由于用的不是首选项,所以只要广告名,不需要仓库名
constants/index.ets
  1. export const USER_SETTING_AD = 'fast_driver_setting_ad' // 用来存储用户设置广告首选项的key
复制代码
假如你使用的是har包存放静态资源,末了统一在basic/Index.ets统一导出所有资源,但是这样导出有个bug,在使用的地方导入,会有代码提示,但是会报错说找不到导出的资源
basic/Index.ets可能报错
  1. export * from 'ets/utils'
  2. export * from 'ets/constants'
  3. export * from 'ets/viewmodels'
复制代码
假如报错请补全路径
basic/Index.ets
  1. export * from './src/main/ets/utils'
  2. export * from './src/main/ets/constants'
  3. export * from './src/main/ets/viewmodels'
复制代码
假如是在har包中定义的数据,记得在entry中导入你har包的数据.
entry/oh-package.json5
  1. {
  2.   "name": "entry",
  3.   "version": "1.0.0",
  4.   "description": "Please describe the basic information.",
  5.   "main": "",
  6.   "author": "",
  7.   "license": "",
  8.   "dependencies": {
  9.     "basic":"file:../basic"
  10.   }
  11. }
复制代码
3.新建一个广告页面Start

Start页面中,读取本地存储的广告,展示广告内容,实现倒计时逻辑,倒计时竣事或者点击跳过都会调用toMain()方法。
toMain()方法其实就是你关闭广告的方式,选择不同的广告模式,就要修改不同的toMain()方法
前三种模式都会用到Start页面,所以选择不同方式打开广告,就要用不同方式去关闭广告。
pages/Start/Start.ets
  1. import { AdvertClass, userSetting } from 'basic'
  2. import { router } from '@kit.ArkUI'
  3. @Entry
  4. @Component
  5. struct Start {
  6.   // 需要广告对象
  7.   @State
  8.   ad: AdvertClass = new AdvertClass()
  9.   timer: number = -1 // 用来记录定时器的标记
  10.   // @State
  11.   // ad: Partial<AdvertClass> = {}
  12.   aboutToAppear(): void {
  13.     // 获取首选项的广告数据给到ad
  14.     this.getAdInfo()
  15.   }
  16.   getAdInfo() {
  17.     // 首选项的读取
  18.     this.ad = userSetting.getUserAd()
  19.     // 开启倒计时了
  20.     if (this.ad.showAd) {
  21.       // 如果真的展示广告要开始倒计时
  22.       this.timer = setInterval(() => {
  23.         if (this.ad.adTime === 0) {
  24.           clearInterval(this.timer)
  25.           this.toMain()
  26.           return // return一定要写
  27.         }
  28.         this.ad.adTime--
  29.       }, 1000)
  30.     }
  31.   }
  32.   // 去主页的方法
  33.   toMain() {
  34.     // 关闭广告的方式
  35.     打开方式不同,关闭方式也就不同
  36.   }
  37.   aboutToDisappear(): void {
  38.     clearInterval(this.timer)
  39.   }
  40.   build() {
  41.     RelativeContainer() {
  42.       if (this.ad.showAd) {
  43.         Image(this.ad.adImg)
  44.           .width("100%")
  45.           .height("100%")
  46.           .objectFit(ImageFit.Cover)
  47.         Text(`${this.ad.adTime}秒跳过`)
  48.           .padding({
  49.             left: 10,
  50.             right: 10
  51.           })
  52.           .alignRules({
  53.             right: {
  54.               anchor: '__container__',
  55.               align: HorizontalAlign.End
  56.             },
  57.             top: {
  58.               anchor: '__container__',
  59.               align: VerticalAlign.Top
  60.             }
  61.           })
  62.           .borderRadius(15)
  63.           .height(30)
  64.           .fontSize(14)
  65.           .backgroundColor($r("app.color.background_page"))
  66.           .margin({
  67.             right: 20,
  68.             top: 20
  69.           })
  70.           .onClick(() => {
  71.             // 此时跳过广告
  72.             // 跳转到主页
  73.             this.toMain()
  74.           })
  75.       }
  76.     }
  77.     .height('100%')
  78.     .width('100%')
  79.   }
  80. }
复制代码
4.初始化广告信息

由于广告随时有切换的可能,但是我们又不能每次换个广告就去改源码,所以其实是通过发请求的方式,去获取广告的信息,但你有可能在启动时就需要打开广告页,所以依然是在EntryAbility中的onWindowStageCreate方法中就请求回广告信息,并存入本地存储,供广告页面使用。
不过这里我们模拟发送请求就好了,到时候有真实接口再真的请求数据
EntryAbility.ets
  1. async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
  2.     // Main window is created, set main page for this ability
  3.     hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
  4.     // 假装向云端获取广告数据的请求
  5.     const ad = await new Promise<AdvertClass>((resolve, reject) => {
  6.       setTimeout(() => {
  7.         resolve({
  8.           showAd: true,
  9.           isFull: true,
  10.           adTime: 3,
  11.           adImg: $r("app.media.start")
  12.         })
  13.       }, 500)
  14.     })
  15.     userSetting.setUserAd(ad); // 云端的广告设置到本地
  16. }
复制代码
统统预备就绪,接下来就时选择不同打开广告方式了。
方式一:应用启动时,有广告则直接进入广告页

这种方式是直接判断有无广告,然后通过windowStage.loadContent()直接打开广告页或者首页,
不过在应用启动时打开广告比力实用,不得当在使用中途打开广告。
EntryAbility.ets
  1. //在保存好ad广告信息后
  2. //1. 判断是否需要展示广告
  3.     const path = ad.showAd ? 'pages/Start/Start' : 'pages/Index'
  4.     // 根据抽取的路径加载对应path, 如果要用这种模式,将默认路径 'pages/Index' 替换为path
  5.     // 使用这种只适用于刚打开应用时,因为他的关闭方式其实是直接跳转到首页(固定的)
  6.     windowStage.loadContent(path, (err) => {
  7.       if (err.code) {
  8.         hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
  9.         return;
  10.       }
  11. // 初始化广告仓库
  12.       userSetting.initUserSetting()
  13.       hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
  14.     });
复制代码
当然使用方式一就要在广告Start页面修改实用他的toMain()方法,点击跳过或者倒计时竣事,直接跳转到首页
Start.ets
  1. toMain() {
  2. // 1. 方式一打开广告,关闭是直接跳转到主页
  3.     router.replaceUrl({
  4.       url: 'pages/Index'
  5.     })
  6. }
复制代码
方式二:打开子窗口,然后通过销毁子窗口方式关闭广告

这种方式相当于在不影响加载主页的同时,另外打开了一个页面,覆盖在主页上,到时候关闭直接露出主页
EntryAbility.ets
  1. // 2. 略微有点意思的模式:创建二级窗口,并展示广告
  2.     // 用这种方式就在 'pages/Start/Start' 中将关闭广告的方法改为 2
  3.     if (ad.showAd) {
  4.       const win = await windowStage.createSubWindow("ad_win") // 二级窗口的实际对象
  5.       await win.showWindow() // 展示二级窗口
  6.       win.setUIContent("pages/Start/Start") // 二级窗口放的还是Start广告页
  7.     }
  8. // 这里还是需要正常打开首页的
  9. windowStage.loadContent('pages/Index', (err) => {
  10.       if (err.code) {
  11.         hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
  12.         return;
  13.       }
  14. // 初始化广告仓库
  15.       userSetting.initUserSetting()
  16.       hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
  17.     });
复制代码
当然,在广告页Start中的toMain(),也要将关闭方式修改
Start.ets
  1. toMain() {
  2.     // 2.使用子窗口模式关闭广告
  3.     clearInterval(this.timer) // 先清理一下定时器
  4.     this.closeWin()
  5. }
  6. // 这个关闭方法传入刚才打开的子窗口名称即可
  7. closeWin () {
  8.     window.findWindow("ad_win").destroyWindow()
  9.   }
复制代码
方式三:封装window窗口广告模式

这种方式是打开一个宽高自定义的窗口,然后把广告页面放在窗口中,通过封装类导出实例对象,调用showAd和closeAd方法来打开关闭广告。
假如不好理解可以先不用管内里具体的API都是什么,就看showAd方法和closeAd方法,和导出的实例,用实例调用打开和关闭的方法,看方法需要什么参数给他传什么参数就行了。


 utils/ad_manager.ets
  1. import { display, window } from '@kit.ArkUI'
  2. import { util } from '@kit.ArkTS'
  3. export class AdManager {
  4.   context?: Context // 是给ability使用的
  5.   private winNames: string [] = []
  6.   // 展示广告 采用windows窗口的创建和销毁的方式
  7.   async showAd(url: string, width?: number, height?: number) {
  8.     if (url) {
  9.       let name = `win_${util.generateRandomUUID()}`
  10.       const win = await window.createWindow({
  11.         name,
  12.         windowType: window.WindowType.TYPE_DIALOG,
  13.         ctx: this.context || getContext()
  14.       })
  15.       if (width && width >= 320 && height && height >= 240) {
  16.         const screen = display.getDefaultDisplaySync()
  17.         let mainWidth = vp2px(width)
  18.         let mainHeight = vp2px(height)
  19.         win.resizeAsync(mainWidth, mainHeight)
  20.         win.moveWindowToAsync((screen.width - mainWidth) / 2, (screen.height - mainHeight) / 2)
  21.       }
  22.       await win.showWindow() // 展示窗口
  23.       win.setUIContent(url) // 设置地址
  24.       this.winNames.push(name)
  25.       return name  // showAd方法返回了一个name可以接受存下来,用于关闭广告
  26.     }
  27.     return ""
  28.   }
  29.   // 关闭广告
  30.   async closeAd(name?: string) {  // 传入刚才存的name关闭具体小窗,不穿则关闭所有小窗
  31.     if (name) {
  32.       window.findWindow(name).destroyWindow()
  33.       this.winNames = this.winNames.filter(item => item !== name) //清空数组内容
  34.     } else {
  35.       // 不传就认为 想关闭所有
  36.       let index = 0
  37.       while (index < this.winNames.length) {
  38.         await window.findWindow(this.winNames[index]).destroyWindow()
  39.         index++
  40.       }
  41.       this.winNames = [] // 清空数组
  42.     }
  43.   }
  44. }
  45. export const adManger = new AdManager()
复制代码
在EntryAbility.ets中,判断是否需要广告,然后打开小窗口。在别的地方使用也可。
  1. // 3.使用封装window窗口广告模式
  2. // 用这种方式就在 'pages/Start/Start' 中将关闭广告的方法改为 3:adManger.closeAd()
  3.     if(ad.showAd){
  4.       adManger.context = this.context
  5.       adManger.showAd('pages/Start/Start', 320, 240)  // 设置小窗宽高
  6.       // 如果你在这里接收了一个name,那么也要存起来,在关闭时使用。
  7.       // 不过因为暂时只打开了一个小窗,不存关闭所有也是相同的效果
  8.     }
复制代码
在广告页Start中修改关闭方法toMain()
  1. toMain() {
  2.    // 3.使用封装window窗口广告模式
  3.     clearInterval(this.timer) // 先清理一下定时器
  4.     adManger.closeAd() //这里如果不传入name就会关闭所有的小窗
  5. }
复制代码
方式四:采用与页面解耦的模式实现广告

这种方式相当于弹出一个雷同消息提示的弹框(dialog),也是通过封装类导出实例,实现打开和关闭广告的方法。
这个种没有实现倒计时,需要用户手动去点击关闭按钮或者使用返回键关闭广告。
但是这种方式需要给广告类再增加一个dialogName属性,当然叫什么无所谓,就是后面用于关闭弹窗。
这种方式用的不是Start页面,而是自定义的弹框builder,所以不用去Start中修改关闭方式


 advert.ets
  1. export class AdvertClass {
  2.   showAd: boolean = false // 是否展示广告
  3.   isFull: boolean = true // 是否全屏
  4.   adTime: number = 5 // 倒计时数据
  5.   adUrl?: string = "" // 要跳转的连接
  6.   adImg?: ResourceStr = "" // 图片连接
  7.   dialogName?: string = "" // 新增的name属性
  8. }
复制代码
封装ad_manager_final工具
这里由于使用的不是Start页面,所以不用去Start做相应的关闭逻辑
utils/ad_manager_final.ets
  1. import { ComponentContent, promptAction, window } from '@kit.ArkUI'
  2. import { util } from '@kit.ArkTS'
  3. import { AdvertClass } from 'basic'
  4. // 展示广告的结构最重要写的代码
  5. @Builder
  6. function AdBuilder(ad: AdvertClass) {
  7.   Column() {
  8.     Image(ad.adImg)
  9.       .width("100%")
  10.       .height("100%")
  11.       .objectFit(ImageFit.Cover)
  12.       .borderRadius(10)
  13.     Row() {
  14.       Image($r("app.media.ic_btn_close"))
  15.         .width(14)
  16.         .aspectRatio(1)
  17.     }
  18.     .position({  // 不加定位会看不到关闭按钮
  19.       right: 20,
  20.       top: 20
  21.     })
  22.     .width(30)
  23.     .aspectRatio(1)
  24.     .justifyContent(FlexAlign.Center)
  25.     .borderRadius(15)
  26.     .border({
  27.       color: '#ff343232',
  28.       width: 2
  29.     })
  30.     .margin({
  31.       top: 40
  32.     })
  33.     .onClick(() => {
  34.       if (ad.dialogName) {
  35.         // 点击关闭的逻辑在这里
  36.         adManagerFinal.closeAd(ad.dialogName) //  ? name从哪里进来
  37.       }
  38.     })
  39.   }
  40.   .width(ad.isFull ? "100%" : "80%")
  41.   .height(ad.isFull ? "100%" : "50%")
  42. }
  43. export class AdManagerFinal {
  44.   context?: Context
  45.   // 所有的弹窗都放到这个map中 通过name来标识
  46.   private map: Map<string, ComponentContent<AdvertClass>> = new Map()
  47.   // 实际上需要广告
  48.   async showAd(ad: AdvertClass) {
  49.     // 按照文档实现
  50.     // UIContext上下文必须得等到页面初始化之后才可以进行获取
  51.     // 生成一个name
  52.     let name = `dialog_${util.generateRandomUUID()}`
  53.     // 通过当前的主窗口来获取
  54.     const mainWin = await window.getLastWindow(this.context || getContext())
  55.     let uiContext = mainWin.getUIContext() // 拿到UIContext
  56.     let promptAction = uiContext.getPromptAction();
  57.     ad.dialogName = name // 目的是将dialog的弹窗名称传递到builder中
  58.     let contentNode = new ComponentContent(uiContext, wrapBuilder(AdBuilder), ad);
  59.     let options: promptAction.BaseDialogOptions = {
  60.       alignment: DialogAlignment.Center,
  61.       autoCancel: false
  62.     };
  63.     this.map.set(name, contentNode) // 将key/value写入到map中
  64.     promptAction.openCustomDialog(contentNode, options);
  65.     // 一般半屏广告 是得用户手动点击才能关闭的 一般不会自动关闭
  66.     // setTimeout(() => {
  67.     //   promptAction.closeCustomDialog(contentNode)
  68.     // }, 2000)
  69.   }
  70.   async closeAd(name: string) {
  71.     if (name) {
  72.       const mainWin = await window.getLastWindow(this.context || getContext())
  73.       let uiContext = mainWin.getUIContext() // 拿到UIContext
  74.       let promptAction = uiContext.getPromptAction();
  75.       promptAction.closeCustomDialog(this.map.get(name))
  76.       // 清理map
  77.       this.map.delete(name) // 删除已经关闭的弹窗
  78.     }
  79.   }
  80. }
  81. export const adManagerFinal = new AdManagerFinal()
复制代码
在EntryAbility.ets中,判断是否需要广告,打开广告。在别的地方使用也可。
  1. // 4.采用与页面解耦的模式实现广告
  2.     // 这种模式是单独打开一个全屏模态框,而不是打开 'pages/Start/Start' 页面,关闭按钮也在 'pages/Start/Start' 页面中
  3.     if (ad.showAd) {
  4.       adManagerFinal.context = this.context
  5.       adManagerFinal.showAd(ad) // 展示广告
  6.     }
复制代码
这种方式是单独拉起一个雷同dialog弹框,所以样式是重新定义的,不需要去Start页面修改toMain()方法
总结:


  • 四种方式各有不同,需要在不同业务场景下公道选择。
  • 第一种和第二种方式更得当在应用刚打开时的广告展示
  • 第三种和第四种由于是封装导出的实例,更得当在全局使用。
  • 前三种都是使用了Start页面,第四种是雷同dialog弹框,他们的关闭方式各不相同。

附:完备的EntryAbility.ets和Start.ets
EntryAbility种的1、2、3分别对应Start中toMain()的1、2、3方法
EntryAbility.ets
  1. import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';import { window } from '@kit.ArkUI';import { AdvertClass, userSetting } from 'basic';import { BusinessError } from '@kit.BasicServicesKit';import { adManagerFinal, adManger } from '../utils';const DOMAIN = 0x0000;export default class EntryAbility extends UIAbility {  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {    this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');  }  onDestroy(): void {    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');  }  async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {    // Main window is created, set main page for this ability    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');    // 冒充向云端获取广告数据的请求    const ad = await new Promise<AdvertClass>((resolve, reject) => {      setTimeout(() => {        resolve({          showAd: true,          isFull: true,          adTime: 3,          adImg: $r("app.media.start")        })      }, 500)    })    userSetting.setUserAd(ad); // 云端的广告设置到本地    // 2. 略微有点意思的模式:创建二级窗口,并展示广告    // 用这种方式就在 'pages/Start/Start' 中将关闭广告的方法改为 2    // if (ad.showAd) {    //   const win = await windowStage.createSubWindow("ad_win") // 二级窗口的实际对象    //   await win.showWindow() // 展示二级窗口    //   win.setUIContent("pages/Start/Start")    // }    // //1. 判断是否需要展示广告    // const path = ad.showAd ? 'pages/Start/Start' : 'pages/Index'    // 根据抽取的路径加载对应path, 假如要用这种模式,将默认路径 'pages/Index' 替换为path    // 使用这种只实用于刚打开应用时,由于他的关闭方式其实是直接跳转到首页(固定的)    windowStage.loadContent('pages/Index', (err) => {      if (err.code) {        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));        return;      }            // 初始化广告仓库    userSetting.initUserSetting()      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');    });    // 3.使用封装window窗口广告模式    // 用这种方式就在 'pages/Start/Start' 中将关闭广告的方法改为 3:adManger.closeAd()    // if(ad.showAd){    //   adManger.context = this.context    //   adManger.showAd('pages/Start/Start', 320, 240)    // }    // 4.采用与页面解耦的模式实现广告
  2.     // 这种模式是单独打开一个全屏模态框,而不是打开 'pages/Start/Start' 页面,关闭按钮也在 'pages/Start/Start' 页面中
  3.     if (ad.showAd) {
  4.       adManagerFinal.context = this.context
  5.       adManagerFinal.showAd(ad) // 展示广告
  6.     }  }  onWindowStageDestroy(): void {    // Main window is destroyed, release UI related resources    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');  }  onForeground(): void {    // Ability has brought to foreground    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');  }  onBackground(): void {    // Ability has back to background    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');  }}
复制代码
 Start.ets
  1. import { AdvertClass, userSetting } from 'basic'
  2. import { router, window } from '@kit.ArkUI'
  3. import { adManagerFinal, adManger } from '../../utils'
  4. @Entry
  5. @Component
  6. struct Start {
  7.   // 需要广告对象
  8.   @State
  9.   ad: AdvertClass = new AdvertClass()
  10.   timer: number = -1 // 用来记录定时器的标记
  11.   // @State
  12.   // ad: Partial<AdvertClass> = {}
  13.   aboutToAppear(): void {
  14.     console.log('123123123')
  15.     // 获取首选项的广告数据给到ad
  16.     this.getAdInfo()
  17.   }
  18.   getAdInfo() {
  19.     // 首选项的读取
  20.     this.ad = userSetting.getUserAd()!
  21.     // 开启倒计时了
  22.     if (this.ad.showAd) {
  23.       // 如果真的展示广告要开始倒计时
  24.       this.timer = setInterval(() => {
  25.         if (this.ad.adTime === 0) {
  26.           clearInterval(this.timer)
  27.           this.toMain()
  28.           return // return一定要写
  29.         }
  30.         this.ad.adTime--
  31.       }, 1000)
  32.     }
  33.   }
  34.   closeWin () {
  35.     window.findWindow("ad_win").destroyWindow()
  36.   }
  37.   // 去主页的方法
  38.   toMain() {
  39.     // 1. 方式一打开广告,关闭是直接跳转到主页
  40.     // router.replaceUrl({
  41.     //   url: 'pages/Index'
  42.     // })
  43.     // 2.方式二:使用子窗口模式关闭广告
  44.     // this.closeWin()
  45.     // 3.方式三:使用封装window窗口广告模式
  46.     // clearInterval(this.timer) // 先清理一下定时器
  47.     // adManger.closeAd()
  48.   }
  49.   aboutToDisappear(): void {
  50.     clearInterval(this.timer)
  51.   }
  52.   build() {
  53.     RelativeContainer() {
  54.       if (this.ad.showAd) {
  55.         Image(this.ad.adImg)
  56.           .width("100%")
  57.           .height("100%")
  58.           .objectFit(ImageFit.Cover)
  59.         Text(`${this.ad.adTime}秒跳过`)
  60.           .padding({
  61.             left: 10,
  62.             right: 10
  63.           })
  64.           .alignRules({
  65.             right: {
  66.               anchor: '__container__',
  67.               align: HorizontalAlign.End
  68.             },
  69.             top: {
  70.               anchor: '__container__',
  71.               align: VerticalAlign.Top
  72.             }
  73.           })
  74.           .borderRadius(15)
  75.           .height(30)
  76.           .fontSize(14)
  77.           .backgroundColor($r("app.color.background_page"))
  78.           .margin({
  79.             right: 20,
  80.             top: 20
  81.           })
  82.           .onClick(() => {
  83.             // 此时跳过广告
  84.             // 跳转到主页
  85.             this.toMain()
  86.           })
  87.       }
  88.     }
  89.     .height('100%')
  90.     .width('100%')
  91.   }
  92. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

羊蹓狼

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表