You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by be...@apache.org on 2012/10/08 14:21:48 UTC
ios commit: Fixed CB-902 Contacts Permissions in iOS6
Updated Branches:
refs/heads/master db3846983 -> 4a3b22064
Fixed CB-902 Contacts Permissions in iOS6
Made necessary updates to support changes for contacts privacy settings in iOS 6.
Fixed bug in peoplePickerNavigationControllerDidCancel where setting allowsEditing to true and canceling w/o selecting a contact would crash.
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/commit/4a3b2206
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/tree/4a3b2206
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/diff/4a3b2206
Branch: refs/heads/master
Commit: 4a3b22064e67c90a4237397ee8205b52cd2e14f1
Parents: db38469
Author: Becky Gibson <be...@apache.org>
Authored: Mon Oct 8 08:04:31 2012 -0400
Committer: Becky Gibson <be...@apache.org>
Committed: Mon Oct 8 08:12:20 2012 -0400
----------------------------------------------------------------------
CordovaLib/Classes/CDVContacts.h | 15 +
CordovaLib/Classes/CDVContacts.m | 526 ++++++++++++++++++++-------------
2 files changed, 328 insertions(+), 213 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/4a3b2206/CordovaLib/Classes/CDVContacts.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVContacts.h b/CordovaLib/Classes/CDVContacts.h
index 4cf7734..17470c0 100644
--- a/CordovaLib/Classes/CDVContacts.h
+++ b/CordovaLib/Classes/CDVContacts.h
@@ -134,3 +134,18 @@
@property (nonatomic, strong) CDVPlugin* contactsPlugin;
@end
+@interface CDVAddressBookAccessError : NSObject
+{}
+@property (assign) CDVContactError errorCode;
+- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code;
+@end
+
+typedef void (^CDVAddressBookWorkerBlock)(
+ ABAddressBookRef addressBook,
+ CDVAddressBookAccessError * error
+ );
+@interface CDVAddressBookHelper : NSObject
+{}
+
+- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock;
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/4a3b2206/CordovaLib/Classes/CDVContacts.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVContacts.m b/CordovaLib/Classes/CDVContacts.m
index 62f4080..8d7ce30 100644
--- a/CordovaLib/Classes/CDVContacts.m
+++ b/CordovaLib/Classes/CDVContacts.m
@@ -90,23 +90,29 @@ dispatch_queue_t workQueue = nil;
{
NSString* callbackId = command.callbackId;
- CDVNewContactsController* npController = [[CDVNewContactsController alloc] init];
+ CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+ CDVContacts* __unsafe_unretained weakSelf = self; // play it safe to avoid retain cycles
- ABAddressBookRef ab = ABAddressBookCreate();
-
- npController.addressBook = ab; // a CF retaining assign
- CFRelease(ab);
+ [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errCode) {
+ if (addrBook == NULL) {
+ // permission was denied or other error just return (no error callback)
+ return;
+ }
+ CDVNewContactsController* npController = [[CDVNewContactsController alloc] init];
+ npController.addressBook = addrBook; // a CF retaining assign
+ CFRelease (addrBook);
- npController.newPersonViewDelegate = self;
- npController.callbackId = callbackId;
+ npController.newPersonViewDelegate = self;
+ npController.callbackId = callbackId;
- UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:npController];
+ UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:npController];
- if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
- [self.viewController presentViewController:navController animated:YES completion:nil];
- } else {
- [self.viewController presentModalViewController:navController animated:YES];
- }
+ if ([weakSelf.viewController respondsToSelector:@selector(presentViewController:::)]) {
+ [weakSelf.viewController presentViewController:navController animated:YES completion:nil];
+ } else {
+ [weakSelf.viewController presentModalViewController:navController animated:YES];
+ }
+ }];
}
- (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person
@@ -135,43 +141,53 @@ dispatch_queue_t workQueue = nil;
NSString* callbackId = command.callbackId;
ABRecordID recordID = [[command.arguments objectAtIndex:0] intValue];
NSDictionary* options = [command.arguments objectAtIndex:1 withDefault:[NSNull null]];
-
bool bEdit = [options isKindOfClass:[NSNull class]] ? false : [options existsValue:@"true" forKey:@"allowsEditing"];
- ABAddressBookRef addrBook = ABAddressBookCreate();
- ABRecordRef rec = ABAddressBookGetPersonWithRecordID(addrBook, recordID);
- if (rec) {
- CDVDisplayContactViewController* personController = [[CDVDisplayContactViewController alloc] init];
- personController.displayedPerson = rec;
- personController.personViewDelegate = self;
- personController.allowsEditing = NO;
+ CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+ CDVContacts* __unsafe_unretained weakSelf = self; // play it safe to avoid retain cycles
- // create this so DisplayContactViewController will have a "back" button.
- UIViewController* parentController = [[UIViewController alloc] init];
- UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:parentController];
+ [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errCode) {
+ if (addrBook == NULL) {
+ // permission was denied or other error - return error
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? errCode.errorCode:UNKNOWN_ERROR];
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+ return;
+ }
+ ABRecordRef rec = ABAddressBookGetPersonWithRecordID (addrBook, recordID);
- [navController pushViewController:personController animated:YES];
+ if (rec) {
+ CDVDisplayContactViewController* personController = [[CDVDisplayContactViewController alloc] init];
+ personController.displayedPerson = rec;
+ personController.personViewDelegate = self;
+ personController.allowsEditing = NO;
- if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
- [self.viewController presentViewController:navController animated:YES completion:nil];
- } else {
- [self.viewController presentModalViewController:navController animated:YES];
- }
+ // create this so DisplayContactViewController will have a "back" button.
+ UIViewController* parentController = [[UIViewController alloc] init];
+ UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:parentController];
- if (bEdit) {
- // create the editing controller and push it onto the stack
- ABPersonViewController* editPersonController = [[ABPersonViewController alloc] init];
- editPersonController.displayedPerson = rec;
- editPersonController.personViewDelegate = self;
- editPersonController.allowsEditing = YES;
- [navController pushViewController:editPersonController animated:YES];
- }
- } else {
- // no record, return error
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:UNKNOWN_ERROR];
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
- }
- CFRelease(addrBook);
+ [navController pushViewController:personController animated:YES];
+
+ if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
+ [self.viewController presentViewController:navController animated:YES completion:nil];
+ } else {
+ [self.viewController presentModalViewController:navController animated:YES];
+ }
+
+ if (bEdit) {
+ // create the editing controller and push it onto the stack
+ ABPersonViewController* editPersonController = [[ABPersonViewController alloc] init];
+ editPersonController.displayedPerson = rec;
+ editPersonController.personViewDelegate = self;
+ editPersonController.allowsEditing = YES;
+ [navController pushViewController:editPersonController animated:YES];
+ }
+ } else {
+ // no record, return error
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:UNKNOWN_ERROR];
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+ }
+ CFRelease (addrBook);
+ }];
}
- (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
@@ -247,12 +263,21 @@ dispatch_queue_t workQueue = nil;
if (picker.allowsEditing) {
// get the info after possible edit
- ABAddressBookRef addrBook = ABAddressBookCreate();
+ // if we got this far, user has already approved/ disapproved addressBook access
+ ABAddressBookRef addrBook = nil;
+ if (&ABAddressBookCreateWithOptions != NULL) {
+ addrBook = ABAddressBookCreateWithOptions(NULL, NULL);
+ } else {
+ // iOS 4 & 5
+ addrBook = ABAddressBookCreate();
+ }
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addrBook, [[picker.pickedContactDictionary objectForKey:kW3ContactId] integerValue]);
- CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
- NSArray* fields = [picker.options objectForKey:@"fields"];
- NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
- picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
+ if (person) {
+ CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
+ NSArray* fields = [picker.options objectForKey:@"fields"];
+ NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
+ picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
+ }
CFRelease(addrBook);
}
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:picker.pickedContactDictionary];
@@ -273,83 +298,93 @@ dispatch_queue_t workQueue = nil;
dispatch_async([CDVContacts getWorkQueue], ^{
// from Apple: Important You must ensure that an instance of ABAddressBookRef is used by only one thread.
- // which is why ABAddressBookCreate() is done within the dispatch queue.
+ // which is why address book is created within the dispatch queue.
// more details here: http: //blog.byadrian.net/2012/05/05/ios-addressbook-framework-and-gcd/
- ABAddressBookRef addrBook = ABAddressBookCreate ();
-
- NSArray* foundRecords = nil;
- // get the findOptions values
- BOOL multiple = NO; // default is false
- NSString* filter = nil;
- if (![findOptions isKindOfClass:[NSNull class]]) {
- id value = nil;
- filter = (NSString*)[findOptions objectForKey:@"filter"];
- value = [findOptions objectForKey:@"multiple"];
- if ([value isKindOfClass:[NSNumber class]]) {
- // multiple is a boolean that will come through as an NSNumber
- multiple = [(NSNumber*) value boolValue];
- // NSLog(@"multiple is: %d", multiple);
- }
- }
-
- NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
+ CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+ CDVContacts* __unsafe_unretained weakSelf = self; // play it safe to avoid retain cycles
+ // it gets uglier, block within block.....
+ [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errCode) {
+ if (addrBook == NULL) {
+ // permission was denied or other error - return error
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? errCode.errorCode:UNKNOWN_ERROR];
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+ return;
+ }
- NSMutableArray* matches = nil;
- if (!filter || [filter isEqualToString:@""]) {
- // get all records
- foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople (addrBook);
- if (foundRecords && [foundRecords count] > 0) {
- // create Contacts and put into matches array
- // doesn't make sense to ask for all records when multiple == NO but better check
- int xferCount = multiple == YES ? [foundRecords count] : 1;
- matches = [NSMutableArray arrayWithCapacity:xferCount];
-
- for (int k = 0; k < xferCount; k++) {
- CDVContact* xferContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)[foundRecords objectAtIndex:k]];
- [matches addObject:xferContact];
- xferContact = nil;
+ NSArray* foundRecords = nil;
+ // get the findOptions values
+ BOOL multiple = NO; // default is false
+ NSString* filter = nil;
+ if (![findOptions isKindOfClass:[NSNull class]]) {
+ id value = nil;
+ filter = (NSString*)[findOptions objectForKey:@"filter"];
+ value = [findOptions objectForKey:@"multiple"];
+ if ([value isKindOfClass:[NSNumber class]]) {
+ // multiple is a boolean that will come through as an NSNumber
+ multiple = [(NSNumber*) value boolValue];
+ // NSLog(@"multiple is: %d", multiple);
+ }
}
- }
- } else {
- foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople (addrBook);
- matches = [NSMutableArray arrayWithCapacity:1];
- BOOL bFound = NO;
- int testCount = [foundRecords count];
-
- for (int j = 0; j < testCount; j++) {
- CDVContact* testContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)[foundRecords objectAtIndex:j]];
- if (testContact) {
- bFound = [testContact foundValue:filter inFields:returnFields];
- if (bFound) {
- [matches addObject:testContact];
+
+ NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
+
+ NSMutableArray* matches = nil;
+ if (!filter || [filter isEqualToString:@""]) {
+ // get all records
+ foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople (addrBook);
+ if (foundRecords && [foundRecords count] > 0) {
+ // create Contacts and put into matches array
+ // doesn't make sense to ask for all records when multiple == NO but better check
+ int xferCount = multiple == YES ? [foundRecords count]:1;
+ matches = [NSMutableArray arrayWithCapacity:xferCount];
+
+ for (int k = 0; k < xferCount; k++) {
+ CDVContact* xferContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)[foundRecords objectAtIndex:k]];
+ [matches addObject:xferContact];
+ xferContact = nil;
+ }
+ }
+ } else {
+ foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople (addrBook);
+ matches = [NSMutableArray arrayWithCapacity:1];
+ BOOL bFound = NO;
+ int testCount = [foundRecords count];
+
+ for (int j = 0; j < testCount; j++) {
+ CDVContact* testContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)[foundRecords objectAtIndex:j]];
+ if (testContact) {
+ bFound = [testContact foundValue:filter inFields:returnFields];
+ if (bFound) {
+ [matches addObject:testContact];
+ }
+ testContact = nil;
+ }
}
- testContact = nil;
}
- }
- }
- NSMutableArray* returnContacts = [NSMutableArray arrayWithCapacity:1];
-
- if (matches != nil && [matches count] > 0) {
- // convert to JS Contacts format and return in callback
- // - returnFields determines what properties to return
- @autoreleasepool {
- int count = multiple == YES ? [matches count] : 1;
-
- for (int i = 0; i < count; i++) {
- CDVContact* newContact = [matches objectAtIndex:i];
- NSDictionary* aContact = [newContact toDictionary:returnFields];
- [returnContacts addObject:aContact];
+ NSMutableArray* returnContacts = [NSMutableArray arrayWithCapacity:1];
+
+ if (matches != nil && [matches count] > 0) {
+ // convert to JS Contacts format and return in callback
+ // - returnFields determines what properties to return
+ @autoreleasepool {
+ int count = multiple == YES ? [matches count]:1;
+
+ for (int i = 0; i < count; i++) {
+ CDVContact* newContact = [matches objectAtIndex:i];
+ NSDictionary* aContact = [newContact toDictionary:returnFields];
+ [returnContacts addObject:aContact];
+ }
+ }
}
- }
- }
- // return found contacts (array is empty if no contacts found)
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:returnContacts];
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
- // NSLog(@"findCallback string: %@", jsString);
+ // return found contacts (array is empty if no contacts found)
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:returnContacts];
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+ // NSLog(@"findCallback string: %@", jsString);
- if (addrBook) {
- CFRelease (addrBook);
- }
+ if (addrBook) {
+ CFRelease (addrBook);
+ }
+ }];
}); // end of workQueue block
return;
@@ -361,117 +396,134 @@ dispatch_queue_t workQueue = nil;
NSDictionary* contactDict = [command.arguments objectAtIndex:0];
dispatch_async([CDVContacts getWorkQueue], ^{
+ CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+ CDVContacts* __unsafe_unretained weakSelf = self; // play it safe to avoid retain cycles
+
+ [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errorCode) {
+ CDVPluginResult* result = nil;
+ if (addrBook == NULL) {
+ // permission was denied or other error - return error
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? errorCode.errorCode:UNKNOWN_ERROR];
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+ return;
+ }
+
+ bool bIsError = FALSE, bSuccess = FALSE;
+ BOOL bUpdate = NO;
+ CDVContactError errCode = UNKNOWN_ERROR;
+ CFErrorRef error;
+ NSNumber* cId = [contactDict valueForKey:kW3ContactId];
+ CDVContact* aContact = nil;
+ ABRecordRef rec = nil;
+ if (cId && ![cId isKindOfClass:[NSNull class]]) {
+ rec = ABAddressBookGetPersonWithRecordID (addrBook, [cId intValue]);
+ if (rec) {
+ aContact = [[CDVContact alloc] initFromABRecord:rec];
+ bUpdate = YES;
+ }
+ }
+ if (!aContact) {
+ aContact = [[CDVContact alloc] init];
+ }
+
+ bSuccess = [aContact setFromContactDict:contactDict asUpdate:bUpdate];
+ if (bSuccess) {
+ if (!bUpdate) {
+ bSuccess = ABAddressBookAddRecord (addrBook, [aContact record], &error);
+ }
+ if (bSuccess) {
+ bSuccess = ABAddressBookSave (addrBook, &error);
+ }
+ if (!bSuccess) { // need to provide error codes
+ bIsError = TRUE;
+ errCode = IO_ERROR;
+ } else {
+ // give original dictionary back? If generate dictionary from saved contact, have no returnFields specified
+ // so would give back all fields (which W3C spec. indicates is not desired)
+ // for now (while testing) give back saved, full contact
+ NSDictionary* newContact = [aContact toDictionary:[CDVContact defaultFields]];
+ // NSString* contactStr = [newContact JSONRepresentation];
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newContact];
+ }
+ } else {
+ bIsError = TRUE;
+ errCode = IO_ERROR;
+ }
+ CFRelease (addrBook);
+
+ if (bIsError) {
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
+ }
+
+ if (result) {
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+ }
+ }];
+ }); // end of queue
+}
+
+- (void)remove:(CDVInvokedUrlCommand*)command
+{
+ NSString* callbackId = command.callbackId;
+ NSNumber* cId = [command.arguments objectAtIndex:0];
+
+ CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
+ CDVContacts* __unsafe_unretained weakSelf = self; // play it safe to avoid retain cycles
+
+ [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError * errorCode) {
+ CDVPluginResult* result = nil;
+ if (addrBook == NULL) {
+ // permission was denied or other error - return error
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? errorCode.errorCode:UNKNOWN_ERROR];
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+ return;
+ }
+
bool bIsError = FALSE, bSuccess = FALSE;
- BOOL bUpdate = NO;
CDVContactError errCode = UNKNOWN_ERROR;
CFErrorRef error;
- CDVPluginResult* result = nil;
-
- ABAddressBookRef addrBook = ABAddressBookCreate ();
- NSNumber* cId = [contactDict valueForKey:kW3ContactId];
- CDVContact* aContact = nil;
ABRecordRef rec = nil;
- if (cId && ![cId isKindOfClass:[NSNull class]]) {
+ if (cId && ![cId isKindOfClass:[NSNull class]] && ([cId intValue] != kABRecordInvalidID)) {
rec = ABAddressBookGetPersonWithRecordID (addrBook, [cId intValue]);
if (rec) {
- aContact = [[CDVContact alloc] initFromABRecord:rec];
- bUpdate = YES;
- }
- }
- if (!aContact) {
- aContact = [[CDVContact alloc] init];
- }
-
- bSuccess = [aContact setFromContactDict:contactDict asUpdate:bUpdate];
- if (bSuccess) {
- if (!bUpdate) {
- bSuccess = ABAddressBookAddRecord (addrBook, [aContact record], &error);
- }
- if (bSuccess) {
- bSuccess = ABAddressBookSave (addrBook, &error);
- }
- if (!bSuccess) { // need to provide error codes
- bIsError = TRUE;
- errCode = IO_ERROR;
+ bSuccess = ABAddressBookRemoveRecord (addrBook, rec, &error);
+ if (!bSuccess) {
+ bIsError = TRUE;
+ errCode = IO_ERROR;
+ } else {
+ bSuccess = ABAddressBookSave (addrBook, &error);
+ if (!bSuccess) {
+ bIsError = TRUE;
+ errCode = IO_ERROR;
+ } else {
+ // set id to null
+ // [contactDict setObject:[NSNull null] forKey:kW3ContactId];
+ // result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: contactDict];
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+ // NSString* contactStr = [contactDict JSONRepresentation];
+ }
+ }
} else {
- // give original dictionary back? If generate dictionary from saved contact, have no returnFields specified
- // so would give back all fields (which W3C spec. indicates is not desired)
- // for now (while testing) give back saved, full contact
- NSDictionary* newContact = [aContact toDictionary:[CDVContact defaultFields]];
- // NSString* contactStr = [newContact JSONRepresentation];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newContact];
+ // no record found return error
+ bIsError = TRUE;
+ errCode = UNKNOWN_ERROR;
}
} else {
+ // invalid contact id provided
bIsError = TRUE;
- errCode = IO_ERROR;
+ errCode = INVALID_ARGUMENT_ERROR;
}
- CFRelease (addrBook);
+ if (addrBook) {
+ CFRelease (addrBook);
+ }
if (bIsError) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
}
-
if (result) {
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
+ [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
}
- }); // end of queue
-}
-
-- (void)remove:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
- NSNumber* cId = [command.arguments objectAtIndex:0];
- bool bIsError = FALSE, bSuccess = FALSE;
- CDVContactError errCode = UNKNOWN_ERROR;
- CFErrorRef error;
- ABAddressBookRef addrBook = nil;
- ABRecordRef rec = nil;
- CDVPluginResult* result = nil;
-
- // NSMutableDictionary* contactDict = options;
- addrBook = ABAddressBookCreate();
- // NSNumber* cId = [contactDict valueForKey:kW3ContactId];
- if (cId && ![cId isKindOfClass:[NSNull class]] && ([cId intValue] != kABRecordInvalidID)) {
- rec = ABAddressBookGetPersonWithRecordID(addrBook, [cId intValue]);
- if (rec) {
- bSuccess = ABAddressBookRemoveRecord(addrBook, rec, &error);
- if (!bSuccess) {
- bIsError = TRUE;
- errCode = IO_ERROR;
- } else {
- bSuccess = ABAddressBookSave(addrBook, &error);
- if (!bSuccess) {
- bIsError = TRUE;
- errCode = IO_ERROR;
- } else {
- // set id to null
- // [contactDict setObject:[NSNull null] forKey:kW3ContactId];
- // result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: contactDict];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
- // NSString* contactStr = [contactDict JSONRepresentation];
- }
- }
- } else {
- // no record found return error
- bIsError = TRUE;
- errCode = UNKNOWN_ERROR;
- }
- } else {
- // invalid contact id provided
- bIsError = TRUE;
- errCode = INVALID_ARGUMENT_ERROR;
- }
-
- if (addrBook) {
- CFRelease(addrBook);
- }
- if (bIsError) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
- }
- if (result) {
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
- }
-
+ }];
return;
}
@@ -496,3 +548,51 @@ dispatch_queue_t workQueue = nil;
}
@end
+@implementation CDVAddressBookAccessError
+
+@synthesize errorCode;
+
+- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code
+{
+ self = [super init];
+ if (self) {
+ self.errorCode = code;
+ }
+ return self;
+}
+
+@end
+
+@implementation CDVAddressBookHelper
+
+- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock
+{
+ // !! caller is responsible for releasing AddressBook!!
+ ABAddressBookRef addressBook;
+
+ if (&ABAddressBookCreateWithOptions != NULL) {
+ CFErrorRef error = nil;
+ // CFIndex status = ABAddressBookGetAuthorizationStatus();
+ addressBook = ABAddressBookCreateWithOptions(NULL, &error);
+ // NSLog(@"addressBook access: %lu", status);
+ ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
+ // callback can occur in background, address book must be accessed on thread it was created on
+ dispatch_sync (dispatch_get_main_queue (), ^{
+ if (error) {
+ workerBlock (NULL, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
+ } else if (!granted) {
+ workerBlock (NULL, [[CDVAddressBookAccessError alloc] initWithCode:PERMISSION_DENIED_ERROR]);
+ } else {
+ // access granted
+ workerBlock (addressBook, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
+ }
+ });
+ });
+ } else {
+ // iOS 4 or 5 no checks needed
+ addressBook = ABAddressBookCreate ();
+ workerBlock (addressBook, NULL);
+ }
+}
+
+@end