普通视图

发现新文章,点击刷新页面。
昨天 — 2025年1月18日首页

鸿蒙NEXT开发浅进阶到精通02:APP隐私弹窗和启动页自定义创建

2025年1月18日 17:02

写在前面

在APP开发中呈现给用户的第一页面就是隐私政策和用户协议弹窗(后文简称隐私弹框)了,用老实话来讲,一个APP和用户没有什么法律纠纷就没有,有用到时,这两个文件就起到大的用途。 再白话一点讲,没这个弹框,上架审核不会通过的。而开发一个鸿蒙Next APP的隐私弹窗呢,本文将会从产品业务逻辑层面和代码层面逐一叙述,看完和CV本文代码,可满足绝大多少APP的场景需要,当然演示项目,UI还需自行优化。这里有个好消息就是鸿蒙元服务的这一块弹框是不需要开发的,官方只需要你在AGC平台上填入对应的链接即可。

image.png

概念概述

隐私弹框与APP内的其他常见弹框,如拨打电话弹框-删除提示弹框的场景,但是在产品和出现逻辑上有本质区别,隐私弹框讲究的是,用户首次下载弹出,不点击同意,就退出APP,点击同意后进入APP,再次打开除非重新下载安装不会再弹出。而且重要一点要防止用户什么也不点击,使用屏幕侧滑返回,来去掉弹框直接使用APP。

实战流程和过程注解

在上文我们提到隐私弹框和其他弹框的本质区别:

  1. 用户首次下载弹出
  2. 不点击同意或者点击不同意/取消等,就退出APP
  3. 点击同意后进入APP,以后再进入APP不会弹出
  4. 放在屏幕侧滑,让弹框消失,用户越过隐私弹框使用APP

那么我们也逐一展开,首先看下实际中一些朋友遇到的问题和想法 小白:这个弹窗干啥用的?

大白答:为了各种要求规定吧,反正你不点同意,这个APP主页用户股东是进不去了,那这个同意一次就OK了,卸载之前或者注销和切换账号前就不用弹出。

那么既然后一次性必点属性,肯定要设置一个全局持久变量是最基本的(如果有账号相关就住这之前去请求后端的这个字段)

小白:那这个弹框在哪出现嘞,有尝试过在主页面index中的aboutTo里弹出,好像也行哦!

大白答:行是行,但根据路由的尿性,用户点击返回,或者侧滑返回,也能进入页面,这时候就审核不过,因为用户并没有同意你的隐私协议,就会存在争议和风险。

所以启动页就特么诞生了,又能做广告宣传海报,又能防止用户无门槛进入APP/元服务

水了这么多,上代码(这里以简单的无后端账号信息 的demo举例个栗子)

一、设置启动页

在EntryAbility中,进入pages/inex之前,创建一个Windows展示

image.png

   // 创建一个子窗口 子窗口加载广告 广告播完 窗口销毁
    let isFirstOpen = AppStorage.get('isFirstOpen') as boolean
    if (!isFirstOpen) {
      const win = await windowStage.createSubWindow('ad_window')
      await win.showWindow()
      win.setUIContent('pages/Start')
    }

这里有个布尔值,就是持久化来的,判断要不要创建这个启动页,在客户要求有启动页的时候,可以设置在页面内部控制这个变量,是否再弹出弹框,这里Demo直接控制是否有启动页(v的时候要注意哦) 至于为什么设置启动页,上文提到是一举两得,还有一个层面是笔者不设置启动页时,对于用户侧滑屏幕操作越过这个弹框,不好控制。有不设置启动页,也能防止用户越过弹框也还请评论区交流

二、页面有了,创建弹窗,在这个里面用那个持久布尔值isFirstOpen来做判断,可以用首选项也可以本地持久化

启动页代码

import { window } from '@kit.ArkUI'
import { agreementPolicyDialog } from '../components/agreementPolicyDialog'
import common from '@ohos.app.ability.common'
PersistentStorage.persistProp('isFirstOpen', false)

const context = getContext(this) as common.UIAbilityContext

@Entry
@Component
struct Start {
  @StorageLink('isFirstOpen') isFirstOpen: boolean = false

  async onPageShow() {

    if (this.isFirstOpen) {
      this.closeWin()

    } else {
      this.controller.open()
    }
  }

  controller: CustomDialogController = new CustomDialogController({
    builder: agreementPolicyDialog(), customStyle: true, cancel: () => {
      context.terminateSelf()
    }
  })

  onBackPress(): boolean | void {
    if (!this.isFirstOpen) {
      context.terminateSelf()
      // this.controller.close()
    }
    return true
  }

  //关闭广告
  closeWin() {
    window.findWindow('ad_window').destroyWindow()
  }

  build() {
    Stack({ alignContent: Alignment.TopEnd }) {


    }.height('100%').width('100%').backgroundColor(Color.White)
  }
}

这里代码就是启动页页面,弹框也在这里弹出,有意思的是我们设置启动页背景为纯白色,在不添加企业海报广告或者logo时,弹出弹框的UI效果跟元服务类似。

创建弹框结构就截图吧,这里注意要给到点击的字段隐私政策和协议的标题,使用text内部套span即可设置隐私和协议的颜色与点击事件

image.png

在设置弹框的时候,要注意cancel函数 的调用,放在返回事件中调用一次,防止用户返回,返回也执行这个取消函数内的退出APP代码

三、意外并重要的知识点--无损退出APP 的代码

image.png 这行代码要注意,收到那个导入window方法和创建实例再在页面中调用,一是在取消按钮下,一是在onBackPress这个生命函数中使用,因为用户看到弹窗,不惦记取消和确定,直接返回也是一种“不同意”,也是要退出APP的,这段代码及其珍贵,看到这里一定要给个赞哦,,

四、注意一次性布尔值的判断逻辑

image.png 那他同意了,就好办了,设置为true,销毁这个启动页,就自动进入主页面了,如果保留海报页仅控制这个弹窗的出现次数,就住EntryAbility中取消判断页面的创建,这里做一个定时器销毁启动页即可,这里不过多赘述

那不同意,也好办,你甚至不用设置false,直接关闭弹窗并退出APP了

image.png

因为你在初始化这个持久变量时,就设置了false(这里也展示了如何注册持久化变量,这个要放在整个应用启动前,在老版鸿蒙编辑器中,mac版是可以放在entryability中的,现在应该是不让了,有兴趣的朋友可以试试)

❌
❌