【问题标题】:Grant access to NAB programatically on iOS 7.0 Simulator在 iOS 7.0 模拟器上以编程方式授予对 NAB 的访问权限
【发布时间】:2014-08-21 05:33:40
【问题描述】:

是否可以通过编程方式在 iOS 7.0 模拟器上授予对本机地址簿 (NAB) 的访问权限?我正在编写 xctest 需要对 NAB 进行 写入访问 的单元测试。单元测试在 iOS 7.0 模拟器 上运行,是持续集成过程的一部分,不涉及任何用户交互。

目前,除非用户通过“TestApp”想要访问您的联系人警报明确授予访问权限,否则访问 NAB 将被拒绝。

【问题讨论】:

标签: ios ios7 ios-simulator abaddressbook xctest


【解决方案1】:

本着分享的精神,我将回答我自己的问题。在其他权限中,通讯录访问权限存储在TCC.db 数据库中,该数据库位于iPhone Simulator 文件夹中的/Library/TCC/ 中。

e.g. /Users/useriko/Library/Application Support/iPhone Simulator/7.1-64/Applications/[appGUID]/Library/TCC/TCC.db

权限存储在 TCC.db 数据库的 access 表中。 access 表架构是:

我们感兴趣的领域是:

  1. service - 权限类型
  2. client   - 应用标识符
  3. allowed - 已授予权限?

为了授予Access Book 权限,应将适当的记录插入access 表(如果已经存在则更新)。插入或更新记录后,表应如下所示:

我编写了以下方法来更新 TCC.db 数据库。

#import <sqlite3.h>

- (void)grantAccessBookAccess {
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  // tccDbPath: /Users/useriko/Library/Application Support/iPhone Simulator/7.1-64/Applications/FB8DF5E9-94B8-4CA9-A167-43AFE794B94E/Document

  NSString *tccDbPath = nil;
  tccDbPath = [[[[paths objectAtIndex:0]
                  stringByDeletingLastPathComponent]  // remove Document
                  stringByDeletingLastPathComponent]  // remove [appGUID]
                  stringByDeletingLastPathComponent]; // remove Applications

  // tccDbPath: /Users/useriko/Library/Application Support/iPhone Simulator/7.1-64/

  tccDbPath = [[[tccDbPath stringByAppendingPathComponent:@"Library"]
                stringByAppendingPathComponent:@"TCC"]
                stringByAppendingPathComponent:@"TCC.db"];

  // tccDbPath: /Users/useriko/Library/Application Support/iPhone Simulator/7.1-64/Library/TCC/TCC.db

  sqlite3 *database;
  if(sqlite3_open([tccDbPath UTF8String], &database) != SQLITE_OK) {
    NSLog(@"Error while opening database. %s", sqlite3_errmsg(database));
    return;
  }

  NSString *updateSql = @"INSERT OR REPLACE INTO access (service, client, client_type, allowed, prompt_count) VALUES (\"kTCCServiceAddressBook\",\"com.your.app.id\",0,1,1);";

  int rc;
  char* errmsg;
  const char *sql = [updateSql UTF8String];
  rc = sqlite3_exec(database, sql, NULL, NULL, &errmsg);
  if (rc != SQLITE_OK) {
    NSLog(@"Error updating access table. %s", errmsg);
    sqlite3_free(errmsg);
  }

  sqlite3_close(database);
}

由于显而易见的原因,目标应该与libsqlite3.dylib链接。

不要忘记将 updateSql 中的应用标识符 (com.your.app.id) 更改为您的应用标识符。

【讨论】:

  • 任何想法如何在 swift3 中做到这一点?
  • @Async 抱歉。不知道。
【解决方案2】:

这个 Cocoapod 非常适合用于测试目的:https://github.com/plu/JPSimulatorHacks

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    相关资源
    最近更新 更多