Custom addressbook for ABPeoplePickerNavigationController on iPhone - iphone

I am trying to create a custom addressbook on the iPhone by adding new records to the device address book (basically, merging a private contact list with the device AB). I then want to let the user select a contact, which I thought I could do with the .addressbook property of ABPeoplePickerNavigationController:
ABAddressBookRef contacts = ABAddressBookCreate();
for (PrivateUserType *user in rosterItems)
{
CFErrorRef err = NULL;
ABRecordRef ref = ABPersonCreate();
ABRecordSetValue(ref, kABPersonLastNameProperty, (CFStringRef)user.lastName, &err);
if (err != NULL)
{
NSString *errorStr = [(NSString *)CFErrorCopyDescription(err) autorelease];
NSLog(#"Can not set name: %#", errorStr);
}
...
ABAddressBookAddRecord(contacts, ref, &err);
if (err != NULL)
{
NSString *errorStr = [(NSString *)CFErrorCopyDescription(err) autorelease];
NSLog(#"Error adding XMPP roster user to addressbook: %#", errorStr);
}
}
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.addressBook = contacts;
[viewController presentModalViewController:picker animated:YES];
[picker release];
The entries are successfully added to the addressbook (which I can verify if I do an ABAddressBookSave() after the loop to add everything in). However, the entries are not shown by picker (unless I save contacts, which of course saves all changes into the device addressbook).
Is there a way to do this? This is on iOS 4.3.1.
Thanks!

As Toro said, you need save any changes to database first. ABPeoplePickerNavigationController not intended to work with uncommit data or with custom data.
You can see rather fresh topic on Apple Dev Forums
https://devforums.apple.com/message/370070#370070
where similar question was asked. And guy from Apple says that "I can't see any way to do this." But he suggest filling a bug for this to implement this feature in future release of iOS.
All you can do now is code your own UI for this AddressBook from the ground :(
updated: he-he. I found your question on App Dev Forum too )))

You need to save any changes to database by ABAddressBookSave() method.
The apple doc link.

Related

contact notes are not transferred when exporting/importing via the built-in vCard representation methods

Using the ABPersonCreateVCardRepresentationWithPeople method for export, and the ABPersonCreatePeopleInSourceWithVCardRepresentation for import, I have successfully transfered contact data between devices. However, the data in the contact's "notes" field isn't transfered.
Here's my export function:
+(NSData*)exportContactsToVcard:(NSArray*)contacts
{
NSMutableArray *people = [NSMutableArray arrayWithCapacity:contacts.count];
ABAddressBookRef ab = ABAddressBookCreate();
for (Contact *contact in contacts)
{
ABRecordRef person = ABAddressBookGetPersonWithRecordID(ab,contact.contactId);
[people addObject:(__bridge id)person];
}
NSData *vCard = (__bridge NSData*)ABPersonCreateVCardRepresentationWithPeople((__bridge CFArrayRef) people);
return vCard;
}
and part of my import function:
+(NSArray*)importContactsFromVcardData:(NSData*)vcardData
{
NSMutableArray *addedContactIds = [NSMutableArray array];
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(addressBook);
NSArray *createdPeople = (__bridge_transfer NSArray*)ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource,(__bridge CFDataRef)vcardData);
CFErrorRef error = NULL;
for (id person in createdPeople)
{
error = NULL;
ABRecordRef personRecord = (__bridge ABRecordRef)person;
NSString *notes = (__bridge NSString *)ABRecordCopyValue(personRecord, kABPersonNoteProperty);
In the last line, notes is always nil, even if the contact had notes before it was exported. All the other standard contact fields seem to be in place.
For example, if I replace the last line with:
NSString *firstName = (__bridge NSString *)ABRecordCopyValue(personRecord, kABPersonFirstNameProperty);
the firstName string will hold the contact's first name.
Any idea how I can work around this, and get the contact notes?
Thanks.
For testing purposes, you can export a vCard from Address Book. Then drag it to TextEdit to look at the various fields.
At the bottom you'll find something like this:
NOTE:This is a note!
Also, see this link for info on the vCard format:
http://en.wikipedia.org/wiki/VCard
ABPersonCreateVCardRepresentationWithPeople will only transfer the important contact details of a vCard...thats my identifying in much tests with the vCard and the iOS import-export function. It has many mistakes, e.g. if you try to import it with social networks like facebook, it won't do it with (just look in my other thread THREADLINK )
But if you try to add some vCard Information over ABNewPersonViewController, it will work perfectly.

Setting person properties

Working on someone else's code. I am really confused about whats exactly happening in this code.
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef persons = ABAddressBookGetPersonWithRecordID(addressBook, x);
CFErrorRef *error=NULL;
ABAddressBookRemoveRecord(addressBook, persons, error);
ABAddressBookSave(addressBook, error);
ABRecordRef persons = ABPersonCreate();
ABRecordSetValue(persons, kABPersonFirstNameProperty, firstName , nil);
What should be done is that, a ABRecordRef person should be created. His properties should be set and his record/details should be displayed. He should never be saved in the address book. Is this the way to do it. Need help.
Edit: Apart from setting properties to person, the following code is added to push the view controller to view the person.
MyContactDetailViewcontroller *personContactDetail = [[MyContactDetailViewcontroller alloc] init];
personContactDetail.displayedPerson = persons;
personContactDetail.passedSelectedContactData = selectedContactsOnlyData;
[self.navigationController pushViewController:personContactDetail animated:YES];
[personContactDetail release];
MyContactDetailViewcontroller subclass ABPersonViewController. Or is it more apt to use ABUnknownPersonViewController.
Do you find any cases where the contacts could be duplicated in address book
This is exactly what is happening here.. I will explain..
ABAddressBookCreate creates a new address book from data from the addressbook database, so any changes you make to ABAddressBookRef will only be saved to actual addressbook database once you call ABAddressBookSave(). so what it is doing is getting the reference for the person with recordid- x. Than you are creating a new person entry using
ABRecordRef persons = ABPersonCreate();
and than you are setting its value, but this is available to this particular object and not stored in the database unless you call... ABAddressBookSave()
hoping this helps you... :)

iphone: how to detect last caller number programmatically?

Is there any way to detect last caller number & call duration on iPhone, I am able to get all notification (Core Telephony) but don't know how to get caller number.
You can't, the API will not allow you to do this.
I think apple will never allow this due to privacy concerns.
According to api you cant do it... but here something which might help you ... though I haven't tried it myself...
http://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/
Apple officially don't allow.You cann't access the database of the other application then your one.
You can use this
if ([name isEqualToString:#"kCTCallIdentificationChangeNotification"])
{
// CTCallCenter *center = [[CTCallCenter alloc] init];
// center.callEventHandler = ^(CTCall *call) {
// NSLog(#”call:%#”, [call description]);
// };
//NSDictionary *info = (NSDictionary *)userInfo;
CTCall *call = (CTCall *)[info objectForKey:#"kCTCall"];
NSString *caller = CTCallCopyAddress(NULL, call);
NSLog(#"caller:%#",caller);
//CTCallDisconnect(call);
/* or one of the following functions: CTCallAnswer
CTCallAnswerEndingActive
CTCallAnswerEndingAllOthers
CTCallAnswerEndingHeld
*/
//if ([caller isEqualToString:#"+1555665753"])
if ([caller isEqualToString:#"+918740061911"])
{
NSLog(#"disconnecting call");
//disconnect this call
CTCallDisconnect(call);
}
}

Pretty interesting question regarding address book in iPhone

HI all i have seen the example of apple name as 'QUICK CONTACTS' and here is an error in the
person view controller. here it always show same data with two names
// Fetch the address book
ABAddressBookRef addressBook = ABAddressBookCreate();
// Search for the person named "Appleseed" in the address book
NSArray *people = (NSArray *)ABAddressBookCopyPeopleWithName(addressBook, CFSTR("Appleseed"));
// Display "Appleseed" information if found in the address book
if ((people != nil) && [people count])
{
ABRecordRef person = (ABRecordRef)[*people objectAtIndex:0*];
ABPersonViewController *picker = [[[ABPersonViewController alloc] init] autorelease];
picker.personViewDelegate = self;
picker.displayedPerson = person;
// Allow users to edit the person’s information
picker.allowsEditing = YES;
[self.navigationController pushViewController:picker animated:YES];
}
here it always show same information for two person with same name how can we remove this error.
quite confused with what you wanna ask.. if you are getting same data that means you the same data feed in two times ..are you working on a simulator ?

how to create groups in contacts in iPhone apps?

I am developing an iPhone application which handles groups in iPhone contacts, but as my observation there is no facility to create groups in iPhone contacts, but in the SDK we have been given a framework for creating and managing groups, so I decided to create groups from application interface and add contacts to that created groups.
Can anyone help how to create groups in iPhone contacts or is my approach correct to create groups from app?
If you have found the solution, suggest to close this question. If not, the following code is for your reference:
- (void)addNewGroup:(NSString *)groupName
{
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef newGroup = ABGroupCreate();
// Save groupName into ABRecord
CFErrorRef error = NULL;
BOOL result = ABRecordSetValue(newGroup, kABGroupNameProperty, (CFTypeRef)groupName, &error);
if (!result)
{
NSLog(#"Failed to create new group reference with error, %#", error);
CFRelease(addressBook);
return;
}
result = ABAddressBookAddRecord(addressBook, newGroup, &error);
if (!result)
{
NSLog(#"Failed to save new group record to address book with error, %#", error);
CFRelease(addressBook);
return;
}
result = ABAddressBookSave(addressBook,&error);
if (!result)
{
NSLog(#"Failed to save change back to address book with error, %#", error);
}
CFRelease(addressBook);
}