鸿蒙项目加入广告展示页业务
广告页的思路——华为有广告业务,但是我们不用- ad模块;
想自定义广告——场景: app启动-有广告需求,就打开广告页,没有的话就去登录或者主页;
腾讯体育的广告- 启动有广告页,退到后台的情况下,再次进入前台也会有广告;
一、分析需求:
广告页作为一个app启动的首页,应该是在我们应用启动就进去的。
-
有的app有的需要广告页,有的不需要,搞个配置呗!!!
二、思路
-
通过首选项配置存储我们的一些常用配置,比如要不要广告页,还有广告页的路由地址,点击广告页跳转的链接,广告页倒计时的秒数
-
在入口处进行判断是否需要广告页,需要的话,跳转广告页-广告页根据设置的参数进行渲染
-
问题来了,因为运营人员肯定不能每次都去改我们底层的代码-这里我还可以设置成动态的-就是初始化的时候通过请求去读一下云端的请求,然后把我们的图片和一些参数配置下来,这样每次你启动app就是运营人员给你配置的广告和设置了
三、开搞
-
新建一个关于广告类的数据模型-basic- models/advert.ets
export class AdvertClass {showAd: boolean = false // 显示广告adTime: number = 5 // 广告时长adUrl?: string = '' // 广告链接adImg?: ResourceStr = '' // 广告图片
}
-
在model/index.ets中进行统一导出
export * from './advert'
-
在utils中新建一个关于读取首选项的类,用来读取和设置首选项的广告设置- utils/setting.ets
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: Contextconstructor(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中统一导出
export * from './setting'
-
上面还用到了两个常量,我们同样需要在constants目录下定义一个文件专门用来记录-setting
export const USER_SETTING = 'fast_driver_setting' // 用来存储用户设置的首选项的key
export const USER_SETTING_AD = 'fast_driver_setting_ad' // 用来存储用户设置广告首选项的key
-
同样在constants/index.ets文件中导出
export * from './setting'
-
在basic/Index.ets统一导出
export * from './src/main/ets/models'
export * from './src/main/ets/constants'
export * from './src/main/ets/utils'
entry模块-oh-package.json5
-
在ability中引入该har包依赖
{"name": "entry","version": "1.0.0","description": "Please describe the basic information.","main": "","author": "","license": "","dependencies": {"@hm/basic":"file:../common/basic"}
}
ability中判断
-
导入包
import { AdvertClass, UserSettingClass } from '@hm/basic'
-
判断
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页的页面结构及倒计时逻辑
import { UserSettingClass, AdvertClass } from '@hm/basic'
@Entry
@Component
struct Start {userSetting: UserSettingClass = new UserSettingClass(getContext(this))@StateadObj: AdvertClass = {showAd: false,adTime: 0}timer: number = -1async 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来实现在当前页面上创建一个窗口
if (result.showAd) {const win = await windowStage.createSubWindow("ad_window")await win.showWindow()win.setUIContent("pages/Start/Start")}
-
广告页在广告结束或者点击跳过广告时,关闭广告
Start/Start页面
closeWin () {window.findWindow("ad_window").destroyWindow()
}
-
完成Start页面代码
import { UserSettingClass, AdvertClass } from '@hm/basic'
import { window } from '@kit.ArkUI'
@Entry
@Component
struct Start {userSetting: UserSettingClass = new UserSettingClass(getContext(this))@StateadObj: AdvertClass = {showAd: false,adTime: 0}timer: number = -1closeWin () {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
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 abilityhilog.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 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');}
}
到此广告功能就搞定了!