鸿蒙项目加入广告展示页业务
广告页的思路------华为有广告业务,但是我们不用- ad模块;
想自定义广告------场景: app启动-有广告需求,就打开广告页,没有的话就去登录或者主页;
腾讯体育的广告- 启动有广告页,退到后台的情况下,再次进入前台也会有广告;
一、分析需求:
广告页作为一个app启动的首页,应该是在我们应用启动就进去的。
- 有的app有的需要广告页,有的不需要,搞个配置呗!!!
二、思路
- 通过首选项配置存储我们的一些常用配置,比如要不要广告页,还有广告页的路由地址,点击广告页跳转的链接,广告页倒计时的秒数
- 在入口处进行判断是否需要广告页,需要的话,跳转广告页-广告页根据设置的参数进行渲染
- 问题来了,因为运营人员肯定不能每次都去改我们底层的代码-这里我还可以设置成动态的-就是初始化的时候通过请求去读一下云端的请求,然后把我们的图片和一些参数配置下来,这样每次你启动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'); // 正常加载页面
}
这里我们模拟了一个请求,给了一个默认广告, 写入首选项-正常加载主页
- 在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');
}
}
到此广告功能就搞定了!