在iOS 7.0模拟器上编程授予对NAB的访问权限

6
有没有可能通过编程的方式授权访问iOS 7.0模拟器上的本地通讯录(NAB)? 我正在编写xctest单元测试,需要对NAB进行写访问。这些单元测试在iOS 7.0模拟器上运行,并且是持续集成过程的一部分,不涉及任何用户交互。
目前,除非用户通过“TestApp想要访问您的联系人”警报明确授权,否则将拒绝访问NAB。

iOS 8版本的这个问题:http://stackoverflow.com/q/30106320/476716 - OrangeDog
2个回答

7
在分享的精神下,我将回答自己的问题。除了其他权限之外,通讯录访问权限存储在TCC.db数据库中,该数据库位于iPhone模拟器文件夹中/Library/TCC/
e.g. /Users/useriko/Library/Application Support/iPhone Simulator/7.1-64/Applications/[appGUID]/Library/TCC/TCC.db

权限存储在TCC.db数据库的access表中。access表模式如下: TCC.db schema 我们感兴趣的字段是:
  1. service - 权限类型
  2. client - 应用程序标识符
  3. allowed - 是否授予权限
为了授予"Access Book"权限,应将适当的记录插入到access表中(如果已存在,则更新)。插入或更新记录后,表格应该如下所示: access table after update 我编写了以下方法来更新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)为您的应用程序标识符。


1
有任何关于如何在 Swift3 中实现它的想法吗? - Async-
@Async 抱歉,我不知道。 - tonymontana

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接