HarmonyOS项目开发经历——添加自定义广告

鸿蒙项目加入广告展示页业务

广告页的思路------华为有广告业务,但是我们不用- ad模块;

想自定义广告------场景: app启动-有广告需求,就打开广告页,没有的话就去登录或者主页;

腾讯体育的广告- 启动有广告页,退到后台的情况下,再次进入前台也会有广告;

一、分析需求:

广告页作为一个app启动的首页,应该是在我们应用启动就进去的。

  • 有的app有的需要广告页,有的不需要,搞个配置呗!!!

二、思路

  1. 通过首选项配置存储我们的一些常用配置,比如要不要广告页,还有广告页的路由地址,点击广告页跳转的链接,广告页倒计时的秒数
  2. 在入口处进行判断是否需要广告页,需要的话,跳转广告页-广告页根据设置的参数进行渲染
  3. 问题来了,因为运营人员肯定不能每次都去改我们底层的代码-这里我还可以设置成动态的-就是初始化的时候通过请求去读一下云端的请求,然后把我们的图片和一些参数配置下来,这样每次你启动app就是运营人员给你配置的广告和设置了

三、开搞

  • 新建一个关于广告类的数据模型-basic- models/advert.ets
ts 复制代码
export class AdvertClass {
  showAd: boolean = false // 显示广告
  adTime: number = 5 // 广告时长
  adUrl?: string = '' // 广告链接
  adImg?: ResourceStr = '' // 广告图片
}
  • 在model/index.ets中进行统一导出
ts 复制代码
export * from './advert'
  • 在utils中新建一个关于读取首选项的类,用来读取和设置首选项的广告设置- utils/setting.ets
ts 复制代码
import { AdvertClass } from '../models'
import preferences from '@ohos.data.preferences'
import { USER_SETTING, USER_SETTING_AD } from '../constants'
// 默认广告选项
const defaultAd: AdvertClass = {
  showAd: true,
  adTime: 5,
  adImg: $r('app.media.start')
}
export class UserSettingClass {
  context: Context
  constructor(context: Context) {
    this.context = context
  }
  // 获取存储用户信息的首选项仓库
  getStore () {
     return preferences.getPreferences(this.context, USER_SETTING)
  }
  // 设置用户广告设置
  async setUserAd (ad: AdvertClass) {
    const adStore = await this.getStore()
    await adStore.put(USER_SETTING_AD, JSON.stringify(ad))
    await adStore.flush()
  }
  // 获取广告配置
  async getUserAd (): Promise<AdvertClass> {
    const  adStore = await this.getStore()
    return  JSON.parse(await adStore.get(USER_SETTING_AD, JSON.stringify(defaultAd)) as string) as AdvertClass
  }
}

在上面代码中,我们设计了读取和设置广告的两个方法,并且提供了一个默认广告的设置

  • 在utils中统一导出
ts 复制代码
export * from './setting'
  • 上面还用到了两个常量,我们同样需要在constants目录下定义一个文件专门用来记录-setting
ts 复制代码
export const USER_SETTING = 'fast_driver_setting' // 用来存储用户设置的首选项的key
export const USER_SETTING_AD = 'fast_driver_setting_ad' // 用来存储用户设置广告首选项的key
  • 同样在constants/index.ets文件中导出
ts 复制代码
export * from './setting'
  • 在basic/Index.ets统一导出
ts 复制代码
export * from './src/main/ets/models'
export * from './src/main/ets/constants'
export * from './src/main/ets/utils'

entry模块-oh-package.json5

  • 在ability中引入该har包依赖
ts 复制代码
{
  "name": "entry",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "",
  "author": "",
  "license": "",
  "dependencies": {
    "@hm/basic":"file:../common/basic"
  }
}

ability中判断

  • 导入包
ts 复制代码
import { AdvertClass, UserSettingClass } from '@hm/basic'
  • 判断
ts 复制代码
 async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
    // Main window is created, set main page for this ability
    // 检查是否有广告
    const setting = new UserSettingClass(this.context) // getContext拿到的是undefined
    //
    const ad = await new Promise<AdvertClass>((resolve, reject) => {
      setTimeout(() => {
        resolve(defaultAd) // 广告信息
      }, 500)
      // resolve()
    })
    // 通过模拟请求拿到广告信息
    await setting.setUserAd(ad) // 写入首选项
    if(ad.showAd) {
      // 展示广告的情况 展示广告页 有时限
      // 创建一个子窗口 子窗口加载广告 广告播完 窗口销毁
    }
    windowStage.loadContent('pages/Index'); // 正常加载页面
  }

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

  1. 在pages下新建Start目录,下面新建Start的page页面

编辑

  • 实现Start页的页面结构及倒计时逻辑
ts 复制代码
import { UserSettingClass, AdvertClass } from '@hm/basic'
​
@Entry
@Component
struct Start {
  userSetting: UserSettingClass = new UserSettingClass(getContext(this))
  @State
  adObj: AdvertClass  = {
    showAd: false,
    adTime: 0
  }
  timer: number = -1
  
  async aboutToAppear() {
    this.adObj = await this.userSetting.getUserAd()
    this.timer = setInterval(() => {
      if(this.adObj.adTime === 0) {
        clearInterval(this.timer)
        return
      }
      this.adObj.adTime--
    }, 1000)
  }
  build() {
    Stack({ alignContent: Alignment.TopEnd }) {
      Image(this.adObj.adImg).objectFit(ImageFit.Cover)
      Text(`${this.adObj.adTime}秒后跳过`)
        .padding({ left: 10, right: 10 })
        .margin({ right: 20, top: 20 })
        .height(30)
        .fontSize(14)
        .borderRadius(15)
        .backgroundColor($r("app.color.background_page"))
        .textAlign(TextAlign.Center)
​
    }.height('100%').width('100%')
  }
}
  • 使用子窗口模式加载广告

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

ts 复制代码
 if (result.showAd) {
      const win = await windowStage.createSubWindow("ad_window")
      await win.showWindow()
          win.setUIContent("pages/Start/Start")
    }
  • 广告页在广告结束或者点击跳过广告时,关闭广告

Start/Start页面

ts 复制代码
closeWin () {
    window.findWindow("ad_window").destroyWindow()
}
  • 完成Start页面代码
ts 复制代码
import { UserSettingClass, AdvertClass } from '@hm/basic'
import { window } from '@kit.ArkUI'
​
@Entry
@Component
struct Start {
  userSetting: UserSettingClass = new UserSettingClass(getContext(this))
  @State
  adObj: AdvertClass  = {
    showAd: false,
    adTime: 0
  }
  timer: number = -1
  closeWin () {
    window.findWindow("ad_window").destroyWindow()
  }
  async aboutToAppear() {
    this.adObj = await this.userSetting.getUserAd()
    this.timer = setInterval(() => {
      if(this.adObj.adTime === 0) {
        clearInterval(this.timer)
        this.closeWin()
        return
      }
      this.adObj.adTime--
    }, 1000)
  }
  aboutToDisappear(): void {
    clearInterval(this.timer)
  } 
  build() {
    Stack({ alignContent: Alignment.TopEnd }) {
      Image(this.adObj.adImg).objectFit(ImageFit.Cover)
      Text(`${this.adObj.adTime}秒后跳过`)
        .padding({ left: 10, right: 10 })
        .margin({ right: 20, top: 20 })
        .height(30)
        .fontSize(14)
        .borderRadius(15)
        .backgroundColor($r("app.color.background_page"))
        .textAlign(TextAlign.Center)
        .onClick(() => {
          this.closeWin()
        })
​
    }.height('100%').width('100%')
  }
}

这里请注意-如果需要使用线上的广告图片,需要开启网络权限

完整代码-EntryAbility

ts 复制代码
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { AdvertClass, UserSettingClass } from '@hm/basic'
​
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 ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    // 这里要尝试去读一下运营的配置-我们现在还没有实现接口,直接模拟一下
    const userSetting = new UserSettingClass(this.context)
    const result = await new Promise<AdvertClass>((resolve, reject) => {
      setTimeout(() => {
        resolve({
          showAd: true,
          adTime: 5,
          adImg: $r("app.media.start")
        } as AdvertClass)
      }, 500)
    })
    await userSetting.setUserAd(result) // 写入首选项
    if (result.showAd) {
      const win = await windowStage.createSubWindow("ad_window")
      await win.showWindow()
      win.setUIContent("pages/Start/Start")
    }
    windowStage.loadContent('pages/Index');
  }
​
  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }
​
  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }
​
  onBackground(): void {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

到此广告功能就搞定了!

相关推荐
sanzk3 小时前
华为鸿蒙应用开发
华为·harmonyos
SoraLuna7 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
ClkLog-开源埋点用户分析8 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
mg6689 小时前
鸿蒙系统的优势 开发 环境搭建 开发小示例
华为·harmonyos
模拟IC攻城狮9 小时前
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
嵌入式硬件·华为·硬件架构·芯片
lqj_本人9 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人9 小时前
使用 Flutter 绘制一个棋盘
harmonyos
TangKenny9 小时前
计算网络信号
java·算法·华为
23zhgjx-NanKon10 小时前
华为eNSP:QinQ
网络·安全·华为
23zhgjx-NanKon10 小时前
华为eNSP:mux-vlan
网络·安全·华为