How to take permission of contact access in iOS5? - iphone

I am making an application which is compatible with iOS5 and it I want to take permission before to access the user contact list. In iOS6 I am able to do this but in iOS5 I have not found any code for to this. I am using it to access the contact list -
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef all = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex n = ABAddressBookGetPersonCount(addressBook);
for( int i = 0 ; i < n ; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex(all, i);
ABMultiValueRef *phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
//CFRelease(phones);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
CFRelease(phoneNumberRef);
// NSString *s = #"foo/bar:baz.foo";
NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:#"+- *#( )"];
phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet: doNotWant] componentsJoinedByString: #""];
NSLog(#"phone number new %#", phoneNumber);
}
}
Please suggest how to do this.

Since the Address Book permission requirement was only recently added as of iOS 6 you don't have to ask for permission.
If you still want to do that then you would simply show an UIAlertView and record the user's choice in NSUserDefaults.
Note though that if the user upgrades from iOS 5 to 6 he would be asked again, so you would have to disable your iOS 5 permission dialog in that case.

Related

Getting phone numbers from Facebook synced / "Unified Info" address book contacts

I need to be able to read the contacts' phone number from the user's address book. The problem is that if the user has chosen to sync these contacts via Facebook, they are no longer accessible via the following code (which does work for non-synced contacts):
ABMultiValueRef phones = ABRecordCopyValue(record, kABPersonPhoneProperty);
DLog(#"Found %ld phones", ABMultiValueGetCount(phones));
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(phones, j);
NSString *phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(locLabel);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
CFRelease(phoneNumberRef);
CFRelease(locLabel);
DLog(#" - %# (%#)", phoneNumber, phoneLabel);
[numbersArr addObject:phoneNumber];
}
The log result is [Line 126] Found 0 phones
I have tried to use CFArrayRef userNumbers = ABMultiValueCopyArrayOfAllValues(phoneNumbers);
, but this also returns nothing: [Line 118] Got user numbers: (null)
So I tried to dig into the social profiles, and this also returns nothing!
// Try to get phone numbers from social profile
ABMultiValueRef profiles = ABRecordCopyValue(record, kABPersonSocialProfileProperty);
CFIndex multiCount = ABMultiValueGetCount(profiles);
for (CFIndex i=0; i<multiCount; i++) {
NSDictionary* profile = (__bridge NSDictionary*)ABMultiValueCopyValueAtIndex(profiles, i);
NSLog(#"TESTING - Profile: %#", profile);
}
DLog(#"Got profiles: %#", profiles);
CFRelease(profiles);
Yet the log entry is:
[Line 161] Got profiles: ABMultiValueRef 0x1ddbb5c0 with 0 value(s)
If the above results are all not yielding me anything, how am I supposed to know they're a Facebook user & get their phone info?
From Apple Support:
We do not have any APIs that will return a unified Address Book
contact. However, you can retrieve phone numbers of contacts that
appear as unified in Contacts on your device by first using
ABPersonCopyArrayOfAllLinkedPeople to retrieve all linked contacts,
then iterating through these contacts to fetch their respective phone
numbers. Note that phone numbers that do not appear in the UI in
Contacts will not be returned by Address Book APIs. See below for a
snippet of code that will allow you to do so:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
//Fetch all linked contacts
CFArrayRef linkedPerson = ABPersonCopyArrayOfAllLinkedPeople(person);
//Iterate through each linked contact to fetch the phone numbers
for (CFIndex i = 0; i < CFArrayGetCount(linkedPerson); i++)
{
ABRecordRef contact = CFArrayGetValueAtIndex(linkedPerson,i);
ABMutableMultiValueRef multi = ABRecordCopyValue(contact, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++)
{
CFStringRef label = ABMultiValueCopyLabelAtIndex(multi, i);
CFStringRef number = ABMultiValueCopyValueAtIndex(multi, i);
CFRelease(label);
CFRelease(number);
}
CFRelease(multi);
}
CFRelease(linkedPerson);
return YES;

Strange ios 5 error in addressbook

I have done the following to get record for user info from address book.
- (ABRecordRef)findRecordNSString *)phoneNumber
{
if (phoneNumber == nil)
return nil;
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef all = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex n = ABAddressBookGetPersonCount(addressBook);
ABRecordRef record;
//NSLog(#"The Record : %d", record);
int count = 0;
for( int i = 0 ; i < n ; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex(all, i);
ABMultiValueRef phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
NSString *newPhoneNumber = (NSString *)phoneNumberRef;
if([newPhoneNumber isEqualToStringhoneNumber])
{
//NSLog(#"Phone Ref: %#", phoneNumberRef);
NSLog(#"Record New: %d", ref);
record = ref;
i=(int)n;
count = 1;
}
CFRelease(phoneNumberRef);
[newPhoneNumber release];
}
}
[addressBook release];
return record;
}
but i am getting an error when I try to open the viewController in ios5 device but it works in simulator and ios 4.
the error is
Program received signal: “EXC_BAD_ACCESS”.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Can't find dlopen function, so it is not possible to load shared libraries.)
Also after this error if I forcefully clos the app by double tapping home button and then quit manually the app will only show a black screen. Any idea regarding this?
Just commented the line
CFIndex n = ABAddressBookGetPersonCount(addressBook);
And replaced with this to get total number of records
CFIndex n = CFArrayGetCount(all);
Because the count is different for all(Array) and for the variable n.
Hope this will help others too.

iPhone address book problem

I'm having a bit of an issue with using the address book to get the names of the contacts from the device into my own contacts view within my application.
The code I have works fine on the emulator but I when tested on an iPhone 4 it will crash, the application seems to work fine if there are two or less contacts but 3 or more and the application crashes.
Here is the code I am using to get the names of contacts into an array.
ABAddressBookRef addressBook;
bool wantToSaveChanges = YES;
bool didSave;
CFErrorRef error = NULL;
addressBook = ABAddressBookCreate();
listOfContacts = [[NSMutableArray alloc]init];
int i;
int len = (int) ABAddressBookGetPersonCount(addressBook);
for(i = 1; i< (len+1); i++){
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, (ABRecordID) i);
NSString* name = (NSString *)ABRecordCopyCompositeName(person);
ABMultiValueRef number = (NSString *)ABRecordCopyValue(person,kABPersonPhoneProperty);
NSString *mobileNum = (NSString *)ABMultiValueCopyValueAtIndex(number, 0 );
NSLog(#"Name = %#", name);
NSLog(#"Number = %#", mobileNum);
[listOfContacts addObject:name];
[name release];
[mobileNum release];
}
if(ABAddressBookHasUnsavedChanges(addressBook)){
if(wantToSaveChanges){
didSave = ABAddressBookSave(addressBook, &error);
if(!didSave){
//Error
}
}
else{
ABAddressBookRevert(addressBook);
}
}
When it crashes this is the line that gets highlighted in Xcode:
NSString* name = (NSString *)ABRecordCopyCompositeName(person);
And the error states:
Thread 1: Program received signal: "EXC_BAD_ACCESS"
Can anyone see what the problem might be? I dont understand why it would work on the emulator but not on the device? And also why it works for up to two contacts but not 3 or more??
Just a guess:
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, (ABRecordID) i);
This line looks fishy for me. I doubt that the record IDs are numbered from 1 to whatever. Especially if you have deleted an entry.
This would explain why it works on the simulator, I guess you just added some test contacts and never deleted one.
Here is how I solved it:
(Note how I make sure to call only active records, also I created a customized Contact class)
This code takes care of edge case like: email/phone doesn't exist, or exists more than once...
+(NSArray *)getAddressBook{
ABAddressBookRef addressBook;
bool wantToSaveChanges = YES;
bool didSave;
CFErrorRef error = NULL;
addressBook = ABAddressBookCreate();
NSMutableArray *listOfContacts = [[NSMutableArray alloc]init];
CFArrayRef array=ABAddressBookCopyArrayOfAllPeople(addressBook);
int len=CFArrayGetCount(array);
for (int i = 0; i<len; i++){
ABRecordRef person = CFArrayGetValueAtIndex(array, i);
if (ABRecordGetRecordType(person)==kABPersonType){
NSString *firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
ABMultiValueRef emails = (ABMultiValueRef)ABRecordCopyValue(person,kABPersonEmailProperty);
ABMultiValueRef numbers = (ABMultiValueRef)ABRecordCopyValue(person,kABPersonPhoneProperty);
int sumEmails=ABMultiValueGetCount(emails);
int sumNumbers=ABMultiValueGetCount(numbers);
for (int j=0; j<(sumNumbers>sumEmails?sumNumbers:sumEmails); j++) {
ACL_AB_Contact *contact=[[ACL_AB_Contact alloc]initWithFirstName:firstName LastName:lastName];
if (j<sumEmails){
contact.emailAddress=(NSString *)ABMultiValueCopyValueAtIndex(emails,j);
}
if (j<sumNumbers){
contact.phoneNumber=(NSString *)ABMultiValueCopyValueAtIndex(numbers,j);
}
[contact logContact];
[listOfContacts addObject:contact];
[contact release];
}
}
}
if(ABAddressBookHasUnsavedChanges(addressBook)){
if(wantToSaveChanges){
didSave = ABAddressBookSave(addressBook, &error);
if(!didSave){
//Error
}
}
else{
ABAddressBookRevert(addressBook);
}
}
return [listOfContacts autorelease];
}
The record IDs are dynamic. It means that if you add 2 contacts and then remove the first, you will have only a contact with id "2". So I wouln't use a for statement to get through the contacts. Follow the Address Book Programming Guide

Import AddressBook Contact Info, how to handle empty fields?

I am importing contacts info into some textfields, but the app crashes if there are no entries for certain fields, like phone, email, etc.
Here are my textfields:
First Name
Middle Name
Last Name
Main Phone
Mobile Phone
Email Address
Website
Suppose the selected contact doesnt have a second Phone number (in this case: Mobile Phone) or there are no URL entries for the contact. The app crashes.
*ABMutableMultiValueRef phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSMutableArray *phones = [[NSMutableArray alloc] init];
int i;
for (i = 0; i < ABMultiValueGetCount(phoneMulti); i++) {
NSString *aPhone = [(NSString*)ABMultiValueCopyValueAtIndex(phoneMulti, i) autorelease];
[phones addObject:aPhone];
}
accountPhone1TextField.text = [phones objectAtIndex:0];
accountPhone2TextField.text = [phones objectAtIndex:1];
CFRelease(phoneMulti);
[phones release];*
Or if I am trying to get an email address from the contact and it doesnt exist this will crash:
NSString *anEmail = [(NSString*)ABMultiValueCopyValueAtIndex(emailMulti, i) autorelease];
//Variable is not a CFString
***** UPDATE *****
Ended up using the following code:
ABMutableMultiValueRef emailMulti = ABRecordCopyValue(person, kABPersonEmailProperty);
NSMutableDictionary *myEmailDict = [NSMutableDictionary dictionaryWithCapacity:ABMultiValueGetCount(emailMulti)];
for (CFIndex i = 0; i < ABMultiValueGetCount(emailMulti); i++) {
emailLabel = ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(emailMulti, i));
email = ABMultiValueCopyValueAtIndex(emailMulti, i);
[myEmailDict setObject:(NSString*)email forKey:(NSString*)emailLabel];
CFRelease(email);
CFRelease(emailLabel);
}
if (phones.count > 0) {
accountPhone1TextField.text = [phones objectAtIndex:0];
}
if (phones.count > 1) {
accountPhone2TextField.text = [phones objectAtIndex:1];
}

Issue regarding retrieving all email id's from address book in iphone

I am newbie to Address book programming. I want to retrieve all email id's from address book.The issue is below code gets the all data for one record(one person). but When i add more than one contact in address book. it crushes without showing any exception.
Any suggestions? Thanks in advance.
self.pastUrls = [[NSMutableArray alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *addresses = (NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook);
// you could probably do some kind of enumeration but I'm doing old fashoined way
int i;
for(i = 0; i < [addresses count]; i++) {
ABRecordRef record = [addresses objectAtIndex:i];
ABMultiValueRef multiValue = ABRecordCopyValue(record, kABPersonEmailProperty);
NSLog(#"%#",multiValue);
int count = ABMultiValueGetCount(multiValue);
NSLog(#"%d",count);
int j;
for(j = 0; j < count; j++) {
NSString *label = (NSString *)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(multiValue, i));
NSString *value = (NSString *)ABMultiValueCopyValueAtIndex(multiValue, i);
//NSLog(#"Email for %#: %#", label, value);
[pastUrls addObject:value];
}
}
Regards,
sathish
There are a couple of online tutorials here that should help:
http://iphone.zcentric.com/2008/09/19/access-the-address-book/
https://developer.apple.com/iphone/library/documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/100-Introduction/Introduction.html
Apple's Address Book Programming Guide for iOS includes a sample project that will get you started with general principles for accessing address book data, including email addresses.