W duchu dzielenia się zamierzam odpowiedzieć na moje własne pytanie. Pośród innych uprawnień, Książka adresowa uprawnienia dostępu są przechowywane w bazie danych TCC.db
, która znajduje się pod numerem /Library/TCC/
w folderze iPhone Simulator.
e.g. /Users/useriko/Library/Application Support/iPhone Simulator/7.1-64/Applications/[appGUID]/Library/TCC/TCC.db
Uprawnienia są przechowywane w tabeli w bazie danych TCC.db access
. access
schematu tabela:
Pola jesteśmy zainteresowani są:
service
- typ pozwolenie
client
- identyfikator aplikacji
allowed
- uprawnienie przyznane?
W celu przyznania dostęp do książki pozwolenie i odpowiedni zapis powinien zostać wstawiony do tabeli access
(lub aktualizowane, jeśli już istnieje). Po wstawieniu lub aktualizacji rekordu tabela powinna wyglądać następująco:
Napisałem następującą metodę aktualizacji bazy danych 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);
}
Ponieważ z oczywistych względów, cel ten powinien być połączony z libsqlite3.dylib.
NIE NIE zapomnij zmienić identyfikator aplikacji (com.your.app.id) w updateSql
do identyfikatora aplikacji.
iOS 8 wersji tego pytania: http://stackoverflow.com/q/30106320/476716 – OrangeDog