iOS端的"隐私权政策"

4,759 阅读8分钟

背景

大概在2019年11月上旬开始,工信部发布了针对app隐私进行专项整治的声明。 image

一时间,各大app纷纷针对此声明进行各自修复完善,以相应政策,避免被下架整顿。

微脉app也不例外,针对隐私权政策专门成立了项目组进行推进优化。

方式比较

我们对比了几家app的实现方式:

微医

  1. 系统权限没有滞后,在隐私框之前;
  2. 隐私框显示在引导页最后一页上;
  3. 隐私政策按钮点击跳转app内界面,若前面不同意使用网络则显示空页面;
  4. 不同意停留在此页面,同意进首页

微医隐私处理

淘宝

  1. 隐私框显示在启动页上
  2. 隐私政策按钮点击跳转Safari
  3. 不同意退出app,同意进入首页
  4. 系统权限在同意隐私之后调用

淘宝隐私处理

丁香园

  1. 系统权限在首页之前
  2. 隐私框是首页上的弹框
  3. 隐私框只是提示作用,同意不同意都可以使用app

丁香园隐私处理

综合比较之后,我们确定使用淘宝的隐私框显示方式。

认为这样更符合政策要求,在启动页弹框,只用同意隐私政策后才调用系统权限,比较合理,最主要的是,谁要淘宝这么大碗儿呢,该考虑的不该考虑的他们肯定都整的明明白白的才这么做。

实现步骤

已经确定了使用淘宝的隐私框方式。

开始拆分步骤实现:

pre 1.判断显示隐私框

隐私权分了三期来做,需求不断尝试和修改。

/*
     *  启动优化是把匿名接口提前,放在didFinish中,缩短启动时间提升体验
     *  隐私协议需求,是首次安装时隐私政策弹框展示在开屏页,做处理是必须同意政策后,才能进行正常流程,
        故:做标志区分,当首次安装时(未安装过)- 不在didFinish里进行jm匿名接口请求,放在同意h隐私政策后再请求 ;
                     非首次的话(已安装) - 继续放在didFinish里,提高启动优化
     */
    /* 第二次新增需求,要求判断条件:老用户覆盖升级不显示隐私框、卸载重装显示
     * 根据项目里缓存的用户信息是否存在 - 来判断是否老用户 。 即:新用户 show隐私弹框; 老用户,不作处理
     */
    /* 三期新增需求:“系统权限弹框” 要在点击“同意隐私政策”后,再显示。
     * 所以在上述判断条件中,需要把项目配置 第三方初始化 匿名接口等独立在一个方法里,按”是否首次安装“来判断时机执行;
     * 即”非首次进入App“,在程序入口didFinish里 进行项目配置 第三方初始化 匿名token接口等 ;
     * 首次进入,则在点击同意隐私政策后,再进行项目配置 第三方初始化 匿名token接口等
     */

1.隐私框显示在启动页上

我们都知道,启动页是系统的,我们不能去在启动页上处理业务。

于是我们造了一个视图,作为启动页后的第一个视图。

该视图展示的内容和启动页一致,我们在该视图上做业务处理,这样就能实现了视觉上在启动页显示隐私框的方案。

2.隐私政策按钮点击跳转Safari

因要考虑点击隐私按钮时无网状态,所以跳转到app内部页面会出现数据不展示的情况,就算使用在App内部加载固定js代码实现,也会有内容更新不及时、在未设置根视图时从启动页跳转需单独处理等问题。

所以跳转到Safari展示隐私政策,还是比较合理的。毕竟一般人也不会太在意这些条例,而且iPhone左上角自带返回按钮。

3.系统权限在同意隐私之后调用

一直以来我们项目的逻辑都是在程序入口didFinish里进行项目的初始化配置/第三方初始化等操作,所以系统权限就会在这里初始化的时候进行调用提示。

要实现系统权限在同意隐私操作之后调用,就意味着把这些操作都滞后在同意隐私事件后了。且隐私框只显示一次,所以:

  1. 把项目的初始化配置/第三方初始化等操作放在独立的一个方法里
  2. 程序入口时缓存launchOption
  3. 非首次时,直接在程序入口didFinish方法里调用独立的初始化配置/第三方初始化方法
  4. 首次安装显示隐私权弹框,在同意按钮事件时,获取缓存的launchOption 调用独立的初始化配置/第三方初始化方法
// 独立出来的方法 --- 进行项目配置 第三方初始化 匿名token接口等。。
- (void)applicationLaunchingSetupWithOptions:(NSDictionary *)launchOptions {
    // 初始化程序配置
    [self prepareCustomSetting];
    // 注册Umeng,Growing,wxApi等
    [self socialSetup];
    //ADHUB注册
    [AdHubSDKManager configureWithApplicationID:@"2" DomainURL:@"http://rtb.wm.ghmap.hubcloud.com.cn"];
    [AdHubSDKManager openTheAdHubLog];
    // bugly设置
    [self setupBugly];
    // DoraemonKit设置
    [self setupDoraemonKit];
    [self setupBugTags];
    // 个推
    [self GtPushWithOptions:launchOptions];
    // 注册融云
    [[RCIM sharedRCIM] initWithAppKey:RONGCLOUNDAPP_KEY];
    // 初始化登录数据和UA
    [[AppLoginHandle sharedInstance] initLoginData];
    // 定位 以及上传定位
    [[LocationManager sharedInstance] startUpdatingLocation:NO];
    // 获取网络基础配置
    [self syncGetAppParameters:nil];
    // 3DTouch初始化
    [App3DTouchHandle load];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    /*
     *  启动优化是把匿名接口提前,放在didFinish中,缩短启动时间提升体验
     *  隐私协议需求,是首次安装时隐私政策弹框展示在开屏页,做处理是必须同意政策后,才能进行正常流程,
        故:做标志区分,当首次安装时(未安装过)- 不在didFinish里进行jm匿名接口请求,放在同意h隐私政策后再请求 ;
                     非首次的话(已安装) - 继续放在didFinish里,提高启动优化
     */
    /* 第二次新增需求,要求判断条件:老用户覆盖升级不显示隐私框、卸载重装显示
     * 根据项目里缓存的用户信息是否存在 - 来判断是否老用户 。 即:新用户 show隐私弹框; 老用户,不作处理
     */
    /* 又新增需求:“系统权限弹框” 要在点击“同意隐私政策”后,再显示。
     * 所以在上述判断条件中,需要把项目配置 第三方初始化 匿名接口等独立在一个方法里,按”是否首次安装“来判断时机执行;
     * 即”非首次进入App“,在程序入口didFinish里 进行项目配置 第三方初始化 匿名token接口等 ;
     * 首次进入,则在点击同意隐私政策后,再进行项目配置 第三方初始化 匿名token接口等
     */
    LoginModel *loginModel = [WMCache getDiskLoginModel];
    if (stringIsEmpty(loginModel.WMTOKEN)) {
        // token为空,首次安装, 把launchOptions存起来, 在启动页隐私弹框的同意后 - 再调用方法进行设置程序配置、第三方初始化、匿名token等使用。
        self.saveOptions = [NSDictionary dictionaryWithDictionary:launchOptions];
    }else {
        /*** token有值,说明是老用户; 老用户直接在didFinish里进行项目配置 第三方初始化 匿名token接口等 ***/
        [self applicationLaunchingSetupWithOptions:launchOptions];
    }
}
// 同意隐私政策执行事件
- (void)agreePrivacyAction {
    // 同意隐私政策,再进行项目配置、第三方初始化、匿名token接口逻辑等
    NSDictionary *options = [[AppDelegate sharedAppDelegate] saveOptions];
    [[AppDelegate sharedAppDelegate] applicationLaunchingSetupWithOptions:options];
}

效果如下:

image

遇到的问题

1.存储launchOption闪退的问题

隐私三期提测时,偶然发现当通过3DTouch/scheme等非点击icon图标进入App时,会出现app直接闪退。

因此方法无法启动app,所以无法通过xcode来断点查找原因,在bugTags和友盟也找不到崩溃信息。

查看代码也是正常的,无明显问题。调试启动也正常。

然后全组人通过checkout分支的方法,逐步尝试,终于定位到是在程序入口存储launchOption时的问题。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
}

虽然launchOptions类型是NSDictionary,但是不符合NSUserDefault的存储格式。

关于NSUserDefaults存储数据的问题,验证有以下两条结论:

  • 存储字典时,字典key必须为字符串
  • 存储字典时,字典的value,必须是以下几种NSData, NSString, NSNumber, NSDate,不能为自定义的对象

具体原因看链接: NSUserDefaults存储数据crash问题总结

2.首页弹框和系统权限框冲突不展示的问题

在测试过程中,发现在系统权限滞后处理后,在同意隐私政策进入首页时,依次弹出了系统权限的网络、定位、通知等弹框,但是首页的优惠券弹框没有显示。

首页弹框是通过MMPopView实现的,查看了MMPopView的源码,它是通过创建一个window,再把它的level设置为statusBar+1,提高优先级来展示的。

问题原因应该是和系统权限弹框的window冲突了,所以首页弹框不展示。

解决方法:

  • 通过把弹框添加在指定的window上来解决;
  • 通过在优惠券弹框上添加自定义视图蒙层及背景蒙层点击手势事件实现点击空白消失的处理。