简体   繁体   English

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

[英]Grant access to NAB programatically on iOS 7.0 Simulator

Is it possible to grant access to the native address book (NAB) on iOS 7.0 Simulator programmatically? 是否可以通过编程方式在iOS 7.0 Simulator上授予对本机地址簿(NAB)的访问权限? I am writing xctest Unit Tests that need write access to NAB. 我正在编写需要对NAB进行写访问的 xctest单元测试。 The unit tests are run on iOS 7.0 Simulator and are part of Continuous Integration process and doesn't involve any user interaction. 单元测试在iOS 7.0 Simulator上运行,是Continuous Integration过程的一部分,不涉及任何用户交互。

Currently unless the user grants access explicitly via the “TestApp” Would like to Access Your Contacts alert, access to NAB is denied. 目前,除非用户通过“TestApp”明确授予访问权限想要访问“联系人”警报,否则将拒绝访问NAB。

In the spirit of sharing I am going to answer my own question. 本着分享的精神,我将回答我自己的问题。 Among other permissions, Address Book access permission is stored in TCC.db database that is located in /Library/TCC/ in the iPhone Simulator folder. 在其他权限中, 通讯簿访问权限存储在TCC.db数据库中,该数据库位于iPhone Simulator文件夹中的/Library/TCC/中。

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

Permissions are stored in the access table in TCC.db database. 权限存储在TCC.db数据库的access表中。 access table schema is: access表模式是: TCC.db架构

The fields we are interested in are: 我们感兴趣的领域是:

  1. service - the permission type service - 权限类型
  2. client - the app identifier client - 应用程序标识符
  3. allowed - permission granted? allowed - 授予许可?

In order to grant Access Book permission, and appropriate record should be inserted into the access table (or updated if already exists). 为了授予Access Book权限,应将相应的记录插入access表(如果已存在则更新)。 After the record was either inserted or updated the table should look like that: 插入或更新记录后,表格应如下所示: 更新后访问表

I've wrote the following method to update the TCC.db database. 我编写了以下方法来更新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);
}

Because of the obvious reasons, the target should be linked with libsqlite3.dylib . 由于显而易见的原因,目标应该与libsqlite3.dylib链接。

DO NOT forget to change the app identifier ( com.your.app.id ) in the updateSql to your app identifier. 不要忘记将updateSql中的应用程序标识符( com.your.app.idupdateSql为您的应用程序标识符。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM