iOS14 隐私适配及部分解决方案

做者|盛兰雅(岚遥)ios

编辑|橙子君算法

出品|阿里巴巴新零售淘系技术macos

在刚刚结束的线上 WWDC 2020 发布会上苹果向咱们展现了新的 iOS14 系统。iOS14 的适配,很重要的一环就集中在用户隐私和安全方面。小程序

在 iOS13 及之前,当用户首次访问应用程序时,会被要求开放大量权限,好比相册、定位、联系人,实际上该应用可能仅仅须要一个选择图片功能,却被要求开放整个照片库的权限,这确实是不合理的。对于相册,在 iOS14 中引入了 “LimitedPhotos Library” 的概念,用户能够授予应用访问其一部分的照片,对于应用来讲,仅能读取到用户选择让应用来读取的照片,让咱们看到了 Apple 对于用户隐私的尊重。这仅仅是一部分,在iOS14 中,能够看到诸多相似的保护用户隐私的措施,也须要咱们升级适配。安全

最近在调研 iOS14的适配方案,本文主要分享一下 iOS14 上对于隐私受权的变动和部分适配方案,欢迎补充指正。bash

适配点

相册

iOS14 新增了“Limited Photo Library Access” 模式,在受权弹窗中增长了 Select Photo 选项。用户能够在 App 请求调用相册时选择部分照片让 App 读取。从 App 的视⻆来看,你的相册里就只有这几张照片,App 没法得知其它照片的存在。网络

iOS14 中当用户选择 “PHAuthorizationStatusLimited” 时,若是未进行适配,有可能会在每次触发相册功能时都进行弹窗询问用户是否须要修改照片权限。session

对于这种状况可经过在Info.plist中设置“PHPhotoLibraryPreventAutomaticLimitedAccessAlert”的值为 YES 来阻止该弹窗反复弹出,而且可经过下面这个API来主动控制什么时候弹出PHPickerViewController 进行照片选择。app

[[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:self];
复制代码

在 iOS14 中官方推荐使用 PHPicker 来替代原 API 进行图片选择。PHPicker 为独立进程,会在视图最顶层进行展现,应用内没法对其进行截图也没法直接访问到其内的数据。框架

一、UIImagePickerController -> PHPickerViewController, UIImagePickerViewController 功能受限,每次只能选择一张图片,将逐渐被废弃。

二、PHPicker 支持多选,支持搜索,支持按 image,video,livePhotos 等进行选择。

新API及迁移demo:

@interface ViewController () <PHPickerViewControllerDelegate>
  
  @property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (nonatomic, strong) NSArray<NSItemProvider *> *itemProviders;
  
@end
  
@implementation ViewController
  
  - (void)viewDidLoad {
      [super viewDidLoad];
      // Do any additional setup after loading the view.
}
  
  - (IBAction)button:(id)sender {
      // 如下 API 仅为 iOS14 only
      PHPickerConfiguration *configuration = [[PHPickerConfiguration alloc] init];
      configuration.filter = [PHPickerFilter videosFilter]; // 可配置查询用户相册中文件的类型,支持三种
    configuration.selectionLimit = 0; // 默认为1,为0时表示可多选。
  
      PHPickerViewController *picker = [[PHPickerViewController alloc] initWithConfiguration:configuration];
      picker.delegate = self;
      // picker vc,在选完图片后须要在回调中手动 dismiss
    [self presentViewController:picker animated:YES completion:^{
  
      }];
  }
  
#pragma mark - Delegate
  
  - (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results {
      [picker dismissViewControllerAnimated:YES completion:nil];
      if (!results || !results.count) {
          return;
      }
      NSItemProvider *itemProvider = results.firstObject.itemProvider;
      if ([itemProvider canLoadObjectOfClass:UIImage.class]) {
          __weak typeof(self) weakSelf = self;
          [itemProvider loadObjectOfClass:UIImage.class completionHandler:^(__kindof id<NSItemProviderReading>  _Nullable object, NSError * _Nullable error) {
              if ([object isKindOfClass:UIImage.class]) {
                  __strong typeof(self) strongSelf = weakSelf;
                  dispatch_async(dispatch_get_main_queue(), ^{
                      strongSelf.imageView.image = (UIImage *)object;
                  });
              }
          }]; 
      }
    }
复制代码

须要注意的是,在 limit Photo 模式下,AssetsLibrary 访问相册会失败;在 writeOnly 模式下,AssetLibrary 也会有显示问题。建议还在使用 AssetsLibrary 的同窗尽快迁移到新 API。

受权相关:旧 API 废弃,增长 PHAccessLevel 参数。若是再使用之前的API来获取权限状态, PHAuthorizationStatusLimited 状态下也会返回 PHAuthorizationStatusAuthorized

typedef NS_ENUM(NSInteger, PHAccessLevel) {
  PHAccessLevelAddOnly = 1, // 仅容许添加照片
  PHAccessLevelReadWrite = 2, // 容许访问照片,limitedLevel 必须为 readWrite
} API_AVAILABLE(macos(10.16), ios(14), tvos(14));

// 查询权限
PHAccessLevel level = PHAccessLevelReadWrite;
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatusForAccessLevel:level];
  switch (status) {
      case PHAuthorizationStatusLimited:
          NSLog(@"limited");
          break;
      case PHAuthorizationStatusDenied:
          NSLog(@"denied");
          break;
      case PHAuthorizationStatusAuthorized:
          NSLog(@"authorized");
          break;
      default:
          break;
}

// 请求权限,需注意 limited 权限尽在 accessLevel 为 readAndWrite 时生效
[PHPhotoLibrary requestAuthorizationForAccessLevel:level handler:^(PHAuthorizationStatus status) {
  switch (status) {
      case PHAuthorizationStatusLimited:
          NSLog(@"limited");
          break;
      case PHAuthorizationStatusDenied:
          NSLog(@"denied");
          break;
      case PHAuthorizationStatusAuthorized:
          NSLog(@"authorized");
          break;
      default:
          break; 
  }
}];
复制代码

定位

在 iOS13 及之前,App 请求用户定位受权时为以下形态:一旦用户赞成应用获取定位信息,当前应用就能够获取到用户的精肯定位。

iOS14 新增用户大体位置选项可供用户选择,缘由是大多数 App 实际上并不须要获取用户到用户最准确的定位信息。iOS14 受权弹窗新增的 Precise的开关默认会选中精确位置。用户经过这个开关能够进行更改,当把这个值设为 On 时,地图上会显示精确位置;切换为Off时,将显示用户的大体位置。

对于对用户位置敏感度不高的 App 来讲,这个彷佛无影响,可是对于强依赖精确位置的 App 适配工做就显得很是重要了。能够经过用户在 “隐私设置” 中设置来开启精肯定位,可是可能用户宁肯放弃使用这个应用也不肯意开启。这个时候,iOS14 在 CLLocationManager 新增两个方法可用于向用户申请临时开启一次精确位置权限。

使用方式也很简单,须要首先在 Info.plist 中配置“NSLocationTemporaryUsageDescriptionDictionary”字典中须要配置 key 和 value 代表使用位置的缘由,以及具体的描述。

在本例中,key 即为获取用户权限时传的 "purposeKey",最终呈现给用户的就是左图,右图为当App主动关闭精肯定位权限申请。

对于地理位置不敏感的App 来讲,iOS14 也能够经过直接在 info.plist 中添加 NSLocationDefaultAccuracyReduced 为 true 默认请求大概位置。

这样设置以后,即便用户想要为该 App 开启精肯定位权限,也没法开启。

也能够直接经过API来根据不一样的需求设置不一样的定位精确度。

须要注意的是,当 App 在 Background 模式下,若是并未得到精确位置受权,那么 Beacon 及其余位置敏感功能都将受到限制。

Local Network

iOS14 当 App 要使用 Bonjour 服务时或者访问本地局域网,使用 mDNS 服务等,都须要受权,开发者须要在 Info.plist 中详细描述使用的为哪一种服务以及用途。下图为须要无需申请权限与须要受权的服务:

在 "隐私设置" 中也能够查看和修改具体有哪些 App 正在使用 LocalNetwork

若是应用中须要使用 LocalNetwork 须要在 Info.plist 中配置两个选项,详细描述为何须要使用该权限,以及须要列出具体使用 LocalNetwork 的服务列表。

对于使用了下列包含 Bonjour 的 framework,都须要更新描述.

Wi-Fi Address

iOS8 - iOS13 ,用户在不一样的网络间切换和接入时,mac 地址都不会改变,这也就使得网络运营商仍是能够经过 mac 地址对用户进行匹配和用户信息收集,生成完整的用户信息。iOS14 提供 Wifi 加密服务,每次接入不一样的 WiFi 使用的 mac 地址都不一样。每过 24 小时,mac 地址还会更新一次。须要关注是否有使用用户网络 mac 地址的服务。

下图为 iOS13 及以前用户接入网络时 mac 地址并不会进行改变

下图为 iOS14 用户接入 Wi-Fi 时 mac 地址的变化状况

而且用户也能够自行选择是否开启 private Wi-Fi address

剪切板

在 iOS14 中,读取用户剪切板的数据会弹出提示。

弹出提示的缘由是使用 UIPasteboard 访问用户数据,访问如下数据都会弹出 toast 提示。

兼容方案:若是应用访问剪切板仅仅用于判断是否为URL格式,则 iOS14 新增了两个 API 能够用于规避该提示。若是应用想直接访问剪切板的数据,暂时可能没法作到规避该提示。iOS14 新增两种 UIPasteboardDetectionPattern。

上面的两个 API 可用于规避提示,但只能用于判断剪切板中是否有 URL,并非真正的访问剪贴板数据,也拿不到剪切板的真实数据。下面两个 API 能够得到具体的 URL 信息,可是会触发剪切板提示。而且实测当用户剪切板中包含多个 URL 时只会返回第一个。

使用示例

NSSet *patterns = [[NSSet alloc] initWithObjects:UIPasteboardDetectionPatternProbableWebURL, nil];
[[UIPasteboard generalPasteboard] detectPatternsForPatterns:patterns completionHandler:^(NSSet<UIPasteboardDetectionPattern> * _Nullable result, NSError * _Nullable error) {
    if (result && result.count) {
            // 当前剪切板中存在 URL
    }
}];
复制代码

相机和麦克风

iOS14 中 App 使用相机和麦克风时会有图标提示以及绿点和黄点提示,而且会显示当前是哪一个 App 在使用此功能。咱们没法控制是否显示该提示。

会触发录音小黄点的代码示例:

AVAudioRecorder *recorder = [[AVAudioRecorder alloc] initWithURL:recorderPath settings:nil error:nil];
[recorder record];
复制代码

触发相机小绿点的代码示例:

AVCaptureDeviceInput *videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoCaptureDevice error:nil];
AVCaptureSession *session = [[AVCaptureSession alloc] init];
if ([session canAddInput:videoInput]) {
    [session addInput:videoInput];
}
[session startRunning];
复制代码

IDFA

IDFA 全称为 Identity for Advertisers ,即广告标识符。用来标记用户,目前最普遍的用途是用于投放广告、个性化推荐等。

在 iOS13 及之前,系统会默认为用户开启容许追踪设置,咱们能够简单的经过代码来获取到用户的 IDFA 标识符。

if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) {
    NSString *idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
    NSLog(@"%@", idfaString);
}
复制代码

可是在 iOS14 中,这个判断用户是否容许被追踪的方法已经废弃。

iOS14 中,系统会默认为用户关闭广告追踪权限。

✎ 对于这种状况,咱们须要去请求用户权限。首先须要在 Info.plist 中配置" NSUserTrackingUsageDescription " 及描述文案,接着使用 AppTrackingTransparency 框架中的 ATTrackingManager 中的 requestTrackingAuthorizationWithCompletionHandler 请求用户权限,在用户受权后再去访问 IDFA 才可以获取到正确信息。

#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>

- (void)testIDFA {
    if (@available(iOS 14, *)) {
        [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
            if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
                NSString *idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
            }
        }];
    } else {
        // 使用原方式访问 IDFA
    }
}
复制代码

对于用户拒绝受权 UserTracking 的状况,能够考虑接入苹果的 SKAdNetwork 框架进行广告分析。感兴趣的同窗可进一步了解:developer.apple.com/documentati…

上传 AppStore

更加严格的隐私审核,可让用户在下载 App 以前就知道此 App 将会须要哪些权限。目前苹果商店要求全部应用在上架时都必须提供一份隐私政策。若是引入了第三方收集用户信息等SDK,都须要向苹果说明是这些信息的用途。

总结

对于此次 iOS14 的隐私权限大升级和新尝试,体现了苹果对于用户隐私的尊重。

从用户角度来讲,近年来愈来愈精准的广告投放让咱们愈来愈感受本身被”监视“着,这次升级后,咱们有了更多保护本身隐私的方式以及避免广告骚扰的方法,苹果此举无疑会加大咱们对其的好感度和信任感。但从另外一个角度来讲,对于 IDFA 的限制,可能会致使以前许多依靠广告投放收入的免费 App 难以继续维持生计,也可能也会致使免费 App 的数量有所下降。从开发者的角度来讲,除了对 iOS14 隐私升级的积极适配外,也让咱们感觉到了 iOS14 中对于用户隐私的重视无疑会提升获取用户行为信息的成本。

冲击最大的应该就是广告行业,对于目前的推荐算法和用户拉新都会受到影响,如何在充分尊重用户隐私的前提下进行广告的精准投放对于开发者和广告商来讲都是一个不小的机遇和挑战。

下一期,咱们聊聊 【Metal 新特性详解|带来的技术启发和思考】,敬请持续关注~

参考资料

WWDC 2020 Apple Developer

Developer Documentation

手淘客户端—小程序与跨平台技术部

咱们是支撑小程序、小游戏、Flutter 等跨平台技术的核心团队,有技术广度和也有技术深度,咱们须要 iOS、Android、C++、Flutter、Canvas、游戏引擎、WebGL 等各方面的人才。若是你善于学习,这是一个很好的接触跨领域知识的机会。

若是你是个对技术有追求对小伙伴,请别犹豫,马上联系我! 📮:lanya.sly@alibaba-inc.com

相关文章
相关标签/搜索