检测从ABAddressBookRegisterExternalChangeCallback中更改的内容

我正在使用ABAddressBookRegisterExternalChangeCallback获取用户的AddressbookBook中的外部更改。 我正在使用下面的代码注册callback:

ABAddressBookRef ntificationaddressbook = ABAddressBookCreate(); ABAddressBookRegisterExternalChangeCallback(ntificationaddressbook, MyAddressBookExternalChangeCallback, self); 

当这个callback被调用时,MyAddressBookExternalChangeCallback被调用成功

 void MyAddressBookExternalChangeCallback (ABAddressBookRef ntificationaddressbook,CFDictionaryRef info,void *context) { NSLog(@"Changed Detected......"); } 

我有以下问题:

  1. 如何检测哪些联系人发生了变化,以及在该联系人上执行了哪些操作(添加,更新,删除) 。 我需要获取该联系人的recordID。 可能吗 ?

不幸的是,如果不可能,那么像viber,tango,watsapp这样的应用程序是如何获取变化信息的呢?

  1. 我得到只有当应用程序在后台如果应用程序被终止时调用的callback方法是否有任何方法来获取更改通知。

请帮忙。 提前致谢。

我find解决scheme来查找地址簿中发生了什么变化。 我不确定它是否是一个精确的,但一些如何工作。

为地址簿创build回叫通知: –

  ABAddressBookRef ntificationaddressbook = ABAddressBookCreate(); ABAddressBookRegisterExternalChangeCallback(ntificationaddressbook, MyAddressBookExternalChangeCallback, self); 

发生通知时,请添加以下代码: –

 void MyAddressBookExternalChangeCallback (ABAddressBookRef ntificationaddressbook,CFDictionaryRef info,void *context) { NSTimeInterval timeStampone = [[NSDate date] timeIntervalSince1970]; NSNumber *timeStamponeobj= [NSNumber numberWithDouble: timeStampone]; NSLog(@"Start Process"); NSUserDefaults *userdefs = [[NSUserDefaults alloc]init]; NSMutableArray *arraytemp = [[NSMutableArray alloc]init]; CFArrayRef peopleRefs = ABAddressBookCopyArrayOfAllPeopleInSource(ntificationaddressbook, kABSourceTypeLocal); NSMutableArray *changedrecords = [[NSMutableArray alloc]init]; ABAddressBookRevert(ntificationaddressbook); CFIndex count = CFArrayGetCount(peopleRefs); for (CFIndex i=0; i < count; i++) { ABRecordRef ref = CFArrayGetValueAtIndex(peopleRefs, i); NSDate* datemod = ( NSDate *)(ABRecordCopyValue(ref, kABPersonModificationDateProperty)); NSDate *lastopened = [userdefs valueForKey:@"LastOpenedDate"]; NSTimeInterval datemodifiedtime =[datemod timeIntervalSince1970]; NSNumber *modifieddatenumber= [NSNumber numberWithDouble: datemodifiedtime]; NSTimeInterval lastopeddate = [lastopened timeIntervalSince1970]; NSNumber *lastopenednumber= [NSNumber numberWithDouble: lastopeddate]; if ([modifieddatenumber intValue]>[lastopenednumber intValue]) { ABRecordRef aSource = CFArrayGetValueAtIndex(peopleRefs,i); int recordid = ABRecordGetRecordID(aSource); [changedrecords addObject:[NSString stringWithFormat:@"%d",recordid]]; } } NSString *arraystring= [changedrecords componentsJoinedByString:@","]; [userdefs setValue:arraystring forKey:@"ArrayOfChangedPeopleString"]; [userdefs setValue:changedrecords forKey:@"ArrayOfChangedPeople"]; //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if ([arraystring isEqualToString:@"(null)"]) { arraystring = [arraystring stringByReplacingOccurrencesOfString:@"(null)" withString:@""]; } NSLog(@"arraychangedstring= %@ and length = %d",arraystring,arraystring.length); NSLog(@"Must send data to the server here for this changed people array= %@",changedrecords); if (arraystring.length>2) { NSLog(@"inside if"); ABAddressBookRef addressBook = ABAddressBookCreate(); CFArrayRef allSources = ABAddressBookCopyArrayOfAllPeople( addressBook ); [userdefs setValue:@"" forKey:@"ArrayOfChangedPeopleString"]; [userdefs setValue:@"" forKey:@"ArrayOfChangedPeople"]; for (int i = 0; i<[changedrecords count]; i++) { NSString *recordid= [changedrecords objectAtIndex:i]; int nPeople = [recordid intValue]; [IntoochUtil current_function_name:@"Inside getcontactdetails - Start"]; if(nPeople != 0){ // for (CFIndex i = nPeople_start; i < (nPeople_end); i++) // { // NSString *reocrdid = [NSString stringWithFormat: @"Record %ld",i]; // NSLog(@"Recordid= %@",reocrdid); NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; //common field NSString *first_name =nil; NSString *mid_name = nil ; NSString *last_name =nil ; NSString *basic_email =nil ; NSString *basic_mobile =nil ; NSString *other_phone=nil; NSString *pager_phone= nil; //personal filed NSString *Home_email =nil ; NSString*home_mobile =nil ; NSString*home_address =nil; //business filed NSString *work_email =nil ; NSString *company_name =nil ; NSString *job_title =nil ; NSString*work_mobile =nil ; NSString *iphone = nil; NSString *main = nil; NSString *work_address =nil ; NSString *home_fax, *work_fax, *other_fax =nil; NSString *birthday = nil; // NSString *blogs = nil; NSString *record_id; ABRecordRef aSource = ABAddressBookGetPersonWithRecordID(addressBook, nPeople); // Fetch all groups included in the current source // Getting Record id from address book int recordid = ABRecordGetRecordID(aSource); record_id = [NSString stringWithFormat:@"%d",recordid]; // Getting Names from address book // CFStringRef firstName = ABRecordCopyValue(aSource, kABPersonFirstNameProperty); first_name= ABRecordCopyValue(aSource, kABPersonFirstNameProperty); // first_name=[NSString stringWithFormat:@"%@",firstName]; // CFRelease(firstName); // NSLog(@"First name= %@",first_name); NSMutableDictionary *dict_name = [[NSMutableDictionary alloc]init]; if (!([first_name isEqualToString:@"(null)"]|| first_name == nil || first_name.length ==0)) { [dict_name setValue:first_name forKey:@"FirstName"]; } [first_name release]; mid_name= ABRecordCopyValue(aSource, kABPersonMiddleNameProperty); // NSLog(@"mid name = %@",mid_name); // CFRelease(midname); if (!([mid_name isEqualToString:@"(null)"]|| mid_name == nil || mid_name.length ==0)) { [dict_name setValue:mid_name forKey:@"MiddleName"]; } [mid_name release]; last_name = ABRecordCopyValue(aSource, kABPersonLastNameProperty); // NSLog(@"Last Name= %@",last_name); // CFRelease(lastName); if (!([last_name isEqualToString:@"(null)"]|| last_name == nil || last_name.length ==0)) { [dict_name setValue:last_name forKey:@"LastName"]; } [last_name release]; NSString *dictNamestring = [NSString stringWithFormat:@"%@",dict_name]; if (!([dictNamestring isEqualToString:@"(null)"]|| dictNamestring == nil || dictNamestring.length <4)) { [dict setValue:dict_name forKey:@"Names"]; } // [dict_name release]; // Getting Phone numbers from address book NSMutableDictionary *dict_phone = [[NSMutableDictionary alloc]init]; ABMultiValueRef phones =(NSString*)ABRecordCopyValue(aSource, kABPersonPhoneProperty); NSString* mobileLabel; for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) { mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i); if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel]) { home_mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i) ; [dict_phone setValue:home_mobile forKey:@"Mobile"]; } else if ([mobileLabel isEqualToString:(NSString*)kABHomeLabel]) { basic_mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i); [dict_phone setValue:basic_mobile forKey:@"Home"]; } else if([mobileLabel isEqualToString:(NSString *)kABWorkLabel]) { work_mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i); [dict_phone setValue:work_mobile forKey:@"Work"]; } else if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneIPhoneLabel]) { iphone = (NSString*)ABMultiValueCopyValueAtIndex(phones, i); [dict_phone setValue:iphone forKey:@"iPhone"]; } else if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMainLabel]) { main = (NSString*)ABMultiValueCopyValueAtIndex(phones, i); [dict_phone setValue:main forKey:@"Main"]; } else if ([mobileLabel isEqualToString:(NSString*)kABOtherLabel]) { other_phone = (NSString*)ABMultiValueCopyValueAtIndex(phones, i); [dict_phone setValue:other_phone forKey:@"OtherPhone"]; } else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhonePagerLabel]) { pager_phone = (NSString*)ABMultiValueCopyValueAtIndex(phones, i); [dict_phone setValue:pager_phone forKey:@"Pager"]; } else { NSLog(@"%@ label is not processed",mobileLabel); } } CFRelease(phones); NSString *dictphonestring = [NSString stringWithFormat:@"%@",dict_phone]; if (!([dictphonestring isEqualToString:@"(null)"]|| dictphonestring == nil || dictphonestring.length <4)) { [dict setValue:dict_phone forKey:@"PhoneNos"]; } // [dict_phone release]; // Getting Fax numbers from address book NSMutableDictionary *dict_fax = [[NSMutableDictionary alloc]init]; ABMultiValueRef faxes =(NSString*)ABRecordCopyValue(aSource, kABPersonPhoneProperty); NSString* FaxLabel; for(CFIndex i = 0; i < ABMultiValueGetCount(faxes); i++) { FaxLabel = (NSString*)ABMultiValueCopyLabelAtIndex(faxes, i); if([FaxLabel isEqualToString:(NSString *)kABPersonPhoneHomeFAXLabel]) { home_fax = (NSString*)ABMultiValueCopyValueAtIndex(faxes, i) ; [dict_fax setValue:home_fax forKey:@"Home"]; } if ([FaxLabel isEqualToString:(NSString*)kABPersonPhoneWorkFAXLabel]) { work_fax = (NSString*)ABMultiValueCopyValueAtIndex(faxes, i); [dict_fax setValue:work_fax forKey:@"Work"]; } if([FaxLabel isEqualToString:(NSString *)kABPersonPhoneOtherFAXLabel]) { other_fax = (NSString*)ABMultiValueCopyValueAtIndex(faxes, i); [dict_fax setValue:other_fax forKey:@"Other"]; } } CFRelease(faxes); NSString *dictfaxstring = [NSString stringWithFormat:@"%@",dict_fax]; if (!([dictfaxstring isEqualToString:@"(null)"]|| dictfaxstring == nil || dictfaxstring.length <4)) { [dict setValue:dict_fax forKey:@"FaxNos"]; } [dict_fax release]; // Getting emails from address book ABMultiValueRef email = ABRecordCopyValue(aSource, kABPersonEmailProperty); NSMutableDictionary *dict_email = [[NSMutableDictionary alloc]init]; NSString* email_lbl; for(CFIndex i = 0; i < ABMultiValueGetCount(email); i++) { email_lbl = (NSString*)ABMultiValueCopyLabelAtIndex(email, i); if([email_lbl isEqualToString:(NSString *)kABHomeLabel]) { Home_email = [(NSString*)ABMultiValueCopyValueAtIndex(email, i)retain]; [dict_email setValue:Home_email forKey:@"Home"]; } else if([email_lbl isEqualToString:(NSString *)kABWorkLabel]) { work_email = [(NSString*)ABMultiValueCopyValueAtIndex(email, i)retain]; [dict_email setValue:work_email forKey:@"Work"]; } else if([email_lbl isEqualToString:(NSString *)kABOtherLabel]) { basic_email = [(NSString*)ABMultiValueCopyValueAtIndex(email, i)retain]; [dict_email setValue:basic_email forKey:@"Other"]; } else { NSLog(@"%@ label is processed as other",email_lbl); basic_email = [(NSString*)ABMultiValueCopyValueAtIndex(email, i)retain]; [dict_email setValue:basic_email forKey:@"Other"]; } } CFRelease(email); NSString *dictemailstring = [NSString stringWithFormat:@"%@",dict_email]; if (!([dictemailstring isEqualToString:@"(null)"]|| dictemailstring == nil || dictemailstring.length <4)) { [dict setValue:dict_email forKey:@"Emails"]; } // [dict_email release]; company_name = ABRecordCopyValue(aSource, kABPersonOrganizationProperty); // NSLog(@"Company name= %@",company_name); job_title = ABRecordCopyValue(aSource, kABPersonJobTitleProperty); // NSLog(@"Job title= %@",job_title); NSDate *birthdate = ABRecordCopyValue(aSource, kABPersonBirthdayProperty); NSString *birthdate_string = [NSString stringWithFormat:@"%@",birthdate]; if (!([birthdate_string isEqualToString:@"(null)"]|| birthdate_string == nil || birthdate_string.length ==0)) { NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:birthdate]; NSInteger day = [components day]; NSInteger month = [components month]; NSInteger year = [components year]; birthday = [NSString stringWithFormat:@"%d-%d-%d",day,month,year]; NSLog(@"birthday= %@",birthday); } [birthdate release]; // Getting addressess from address book ABMultiValueRef address =(NSString*)ABRecordCopyValue(aSource, kABPersonAddressProperty); NSDictionary *dict_address = [[NSMutableDictionary alloc]init]; NSString* addLabel; for(CFIndex i = 0; i < ABMultiValueGetCount(address); i++) { addLabel=(NSString*)ABMultiValueCopyLabelAtIndex(address, i); if ([addLabel isEqualToString:(NSString*)kABWorkLabel]) { NSMutableDictionary *dict_work_add = [(NSMutableDictionary *)ABMultiValueCopyValueAtIndex(address, i)retain]; work_address=[NSString stringWithFormat:@"%@ %@ %@ %@ %@",[dict_work_add objectForKey:@"Street"],[dict_work_add objectForKey:@"City"],[dict_work_add objectForKey:@"State"],[dict_work_add objectForKey:@"Country"],[dict_work_add objectForKey:@"ZIP"]] ; work_address = [work_address stringByReplacingOccurrencesOfString:@"(null)" withString:@""]; work_address = [work_address stringByReplacingOccurrencesOfString:@"\n" withString:@""]; // NSLog(@"work address = [%@] and length= %d",work_address,work_address.length); if (!([work_address isEqualToString:@"(null)"]|| work_address == nil || work_address.length ==0)) { [dict_address setValue:work_address forKey:@"Work"]; } } if ([addLabel isEqualToString:(NSString*)kABHomeLabel]) { NSMutableDictionary *dict_home_add = [(NSMutableDictionary *)ABMultiValueCopyValueAtIndex(address, i)retain]; home_address = [NSString stringWithFormat:@"%@ %@ %@ %@ %@",[dict_home_add objectForKey:@"Street"],[dict_home_add objectForKey:@"City"],[dict_home_add objectForKey:@"State"],[dict_home_add objectForKey:@"Country"],[dict_home_add objectForKey:@"ZIP"]]; home_address = [home_address stringByReplacingOccurrencesOfString:@"(null)" withString:@""]; home_address = [home_address stringByReplacingOccurrencesOfString:@"\n" withString:@""]; // NSLog(@"home address = [%@] and length= %d",home_address,home_address.length); if (!([home_address isEqualToString:@"(null)"]|| home_address == nil || home_address.length ==0)) { [dict_address setValue:home_address forKey:@"Home"]; } } } CFRelease(address); NSString *dictaddrssstring = [NSString stringWithFormat:@"%@",dict_address]; if (!([dictaddrssstring isEqualToString:@"(null)"]|| dictaddrssstring == nil || dictaddrssstring.length <4)) { [dict setValue:dict_address forKey:@"Addresses"]; } [dict_address release]; // Getting Social Networks from address book ABMultiValueRef social =(NSString*)ABRecordCopyValue(aSource, kABPersonSocialProfileProperty); NSMutableDictionary *dict_social = [[NSMutableDictionary alloc]init]; if (social) { for (int i = 0 ; i < ABMultiValueGetCount(social); i++) { NSDictionary *socialDict = (NSDictionary *)ABMultiValueCopyValueAtIndex(social, i); NSString *twitterid; if ([socialDict[@"service"] isEqualToString:(NSString*)kABPersonSocialProfileServiceTwitter]) { twitterid = (NSString*)socialDict[@"username"]; [dict_social setValue:twitterid forKey:@"Twitter"]; } NSString *facebookid; if ([socialDict[@"service"] isEqualToString:(NSString*)kABPersonSocialProfileServiceFacebook]) { facebookid = (NSString*)socialDict[@"username"]; [dict_social setValue:facebookid forKey:@"Facebook"]; } NSString *linkedinid; if ([socialDict[@"service"] isEqualToString:(NSString*)kABPersonSocialProfileServiceLinkedIn]) { linkedinid = (NSString*)socialDict[@"username"]; [dict_social setValue:linkedinid forKey:@"LinkedIn"]; } NSString *gamecenterid; if ([socialDict[@"service"] isEqualToString:(NSString*)kABPersonSocialProfileServiceGameCenter]) { gamecenterid = (NSString*)socialDict[@"username"]; [dict_social setValue:gamecenterid forKey:@"GameCenter"]; } NSString *myspaceid; if ([socialDict[@"service"] isEqualToString:(NSString*)kABPersonSocialProfileServiceMyspace]) { myspaceid = (NSString*)socialDict[@"username"]; [dict_social setValue:myspaceid forKey:@"MySpace"]; } NSString *flickerid; if ([socialDict[@"service"] isEqualToString:(NSString*)kABPersonSocialProfileServiceFlickr]) { flickerid = (NSString*)socialDict[@"username"]; [dict_social setValue:flickerid forKey:@"Flicker"]; } [socialDict release]; } CFRelease(social); } NSString *dictsocialstring = [NSString stringWithFormat:@"%@",dict_social]; if (!([dictsocialstring isEqualToString:@"(null)"]|| dictsocialstring == nil || dictsocialstring.length <4)) { [dict setValue:dict_social forKey:@"SocialNetworks"]; } [dict_social release]; // Getting Other Fields from address book NSMutableDictionary *dict_others = [[NSMutableDictionary alloc]init]; if (!([company_name isEqualToString:@"(null)"]||company_name == nil || company_name.length ==0)) { [dict_others setValue:company_name forKey:@"CompanyName"]; } if (!([job_title isEqualToString:@"(null)"]||job_title == nil || job_title.length ==0)) { [dict_others setValue:job_title forKey:@"JobTitle"]; } if (!([birthday isEqualToString:@"1-1-2001"]||[birthday isEqualToString:@"(null)"]||birthday == nil || birthday.length ==0)) { [dict_others setValue:birthday forKey:@"BirthDay"]; } NSString *dictothersstring = [NSString stringWithFormat:@"%@",dict_others]; if (!([dictothersstring isEqualToString:@"(null)"]|| dictothersstring == nil || dictothersstring.length <4)) { [dict setValue:dict_others forKey:@"OtherInfo"]; } [dict_others release]; [dict setValue:record_id forKey:@"RecordID"]; //This NSLog(@"Value for Dict is========= %@ =========",dict); NSString *namedictionstring = [NSString stringWithFormat:@"%@",dict_name]; NSString *emaildictstring = [NSString stringWithFormat:@"%@",dict_email]; NSString *phonedictstring = [NSString stringWithFormat:@"%@",dict_phone]; // NSLog(@"name dict length= %d email dict length= %d phone dict length = %d",namedictionstring.length,emaildictstring.length,phonedictstring.length); // [array_addressbook addObject:dict]; if (phonedictstring.length >3) { [arraytemp addObject:dict]; } else { if (emaildictstring.length>3 && namedictionstring.length) { [arraytemp addObject:dict] ; } else { NSLog(@"Contact is not valid= %@",dict_name); } } [dict_name release]; [dict_phone release]; [dict_email release]; [dict release]; [company_name release]; [job_title release]; /* CFRelease(firstName); CFRelease(midname); CFRelease(lastName); CFRelease(jobtitle); CFRelease(birthday_c); CFRelease(companyname);*/ // } } } NSString *json_array_string = [arraytemp JSONRepresentation]; [IntoochUtil current_function_name:@"Inside getcontactdetails - End"]; NSLog(@"Json String To send= %@",json_array_string); if (allSources) { CFRelease(allSources); } if (addressBook) { CFRelease(addressBook); } } else { NSLog(@"This is empty.... nothing to perform"); NSMutableArray *arrayofdeletedpeoples= [[NSMutableArray alloc]init]; ABAddressBookRef addressbook = ABAddressBookCreate(); CFArrayRef allPeoples= ABAddressBookCopyArrayOfAllPeople(addressbook); NSMutableArray *arrayofrecordIDCallback = [[NSMutableArray alloc]init]; int count = CFArrayGetCount(allPeoples); for (int i =0; i<count; i++) { ABRecordRef aSource = CFArrayGetValueAtIndex(allPeoples,i); NSString * recordid = [NSString stringWithFormat:@"%d",ABRecordGetRecordID(aSource)]; [arrayofrecordIDCallback addObject:recordid]; } NSLog(@"arrayofrecordIDCallback = %@ and count= %d",arrayofrecordIDCallback,[arrayofrecordIDCallback count]); NSMutableArray *arrayofallrecordids = [userdefs valueForKey:@"AllRecordIDSBackGround"]; NSLog(@"arrayofallrecordids= %@ and count= %d",arrayofallrecordids,[arrayofallrecordids count]); for (int i=0 ; i< [arrayofallrecordids count]; i++) { if ([arrayofrecordIDCallback containsObject:[arrayofallrecordids objectAtIndex:i]]) { } else { [arrayofdeletedpeoples addObject:[arrayofallrecordids objectAtIndex:i]]; } } NSLog(@"Array of deleted peoples= %@",arrayofdeletedpeoples); [arrayofdeletedpeoples release]; [arrayofallrecordids release]; [arrayofrecordIDCallback release]; if (allPeoples) { CFRelease(allPeoples); } if (addressbook) { CFRelease(addressbook); } } //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [changedrecords release]; [userdefs release]; [arraytemp release]; NSLog(@"Ends Process"); NSTimeInterval timeStamptwo = [[NSDate date] timeIntervalSince1970]; NSNumber *timeStamptwoObj = [NSNumber numberWithDouble: timeStamptwo]; NSLog(@"Time Difference= %d",[timeStamptwoObj intValue]-[timeStamponeobj intValue]); } 

是的,这是真的,你不能得到有关电话簿更改的具体通知。 当callback通知触发时,您将需要同步数据。

 void MyAddressBookExternalChangeCallback (ABAddressBookRef ntificationaddressbook,CFDictionaryRef info,void *context) { NSLog(@"Changed Detected......"); // synch data } 

像viber,tango,watsapp等应用程序也做同样的事情,但在后台线程

如果应用程序被终止,那么当应用程序启动时,您将需要同步数据,如didFinishLaunchingWithOptions

据我所知,你不知道有什么区别 – 我自己碰到这个问题。

我的解决scheme是:

我有一个本地的基于Core Data的地址簿,每次得到这个通知时,我都会运行一个后台线程来同步数据,并最终通知所有的变化。

在第一次,我使用sqlite在本地数据库中的所有数据倾倒,然后在外部更改我从联系人数据库转储新的数据在伪数据库中的sqlite,然后发射大长比较查询基于已更改。 在我们的案例中,主要关注的是电话号码和姓名。 一旦你得到更新更新,在您的联系人数据库在sqlite。 我想甚至whatsapp正在做类似的事情。 我检查了反映由whatsapp和我们的应用程序几乎相似的变化所花费的时间。 实际上,我的应用程序在反映变化方面比whatsapp快了2秒。 希望这会有所帮助。