-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathAddressBookMap.m
315 lines (243 loc) · 11.3 KB
/
AddressBookMap.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
//
// FastAddressBook.m
// ringring.io
//
// Created by Peter Kosztolanyi on 02/02/2014.
//
//
#import <UIKit/UIKit.h>
#import "LinphoneManager.h"
#import "LinphoneHelper.h"
#import "AddressBookMap.h"
static NSMutableDictionary *addressBookMap;
@implementation AddressBookMap
// Refresh the Fast AddressBookMap
+ (void)reload
{
CFErrorRef error = NULL;
addressBookMap = [[NSMutableDictionary alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
//boolean variable stands for directory access
__block BOOL isaccess = NO;
//ABAddressBookRequestAccessWithCompletion use to request access to address book data
//this function is availabile in iOS 6.0
//iOS >=6
if(ABAddressBookRequestAccessWithCompletion != NULL) {
//Create the semaphore, specifying the initial pool size
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
//ask to grand or deny access
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
isaccess = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
//iOS 5 or older
else {
isaccess = YES;
}
if (isaccess)
{
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
// Sort contacts by first names
CFArraySortValues((__bridge CFMutableArrayRef)(allContacts),
CFRangeMake(0, CFArrayGetCount((__bridge CFArrayRef)(allContacts))),
(CFComparatorFunction) ABPersonComparePeopleByName,
kABPersonSortByFirstName);
for (CFIndex i = 0; i < ABAddressBookGetPersonCount(addressBook); i++) {
ABRecordRef recordRef = (__bridge ABRecordRef)allContacts[i];
// Loop through all emails
ABMultiValueRef emails = ABRecordCopyValue(recordRef, kABPersonEmailProperty);
for (CFIndex j = 0; j < ABMultiValueGetCount(emails); j++) {
// Get contact details from AddressBook
NSString *email = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(emails, j);
[addressBookMap setValue:(__bridge id)(recordRef)
forKey:email];
}
CFRetain(recordRef);
}
CFRelease(addressBook);
}
}
// Get all list of contacts from AddressBookMap
+ (NSMutableArray *)getContactList:(NSMutableArray *)emailList
{
NSMutableArray *contactList = [[NSMutableArray alloc] init];
// Create ABAddressBookRef only one time to improve performance
CFErrorRef error = nil;
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &error);
// Foreach every email in the list
for (id email in emailList) {
// Get ABRecordRef from the pre-loaded AddressBookMap
ABRecordRef aRecordRef = (__bridge ABRecordRef)([addressBookMap objectForKey:email]);
// Get first and last names by ABRecordRef
NSString *aFirstName = (__bridge_transfer NSString *)ABRecordCopyValue(aRecordRef, kABPersonFirstNameProperty);
NSString *aLastName = (__bridge_transfer NSString *)ABRecordCopyValue(aRecordRef, kABPersonLastNameProperty);
// To get the image correctly we need the original ABRecordRef
UIImage *anImage = nil;
ABRecordID recordId = ABRecordGetRecordID(aRecordRef);
ABRecordRef origContactRef = ABAddressBookGetPersonWithRecordID(addressBookRef, recordId);
// Get the image
if (ABPersonHasImageData(origContactRef)) {
anImage = [UIImage imageWithData:(__bridge_transfer NSData *)
ABPersonCopyImageDataWithFormat(origContactRef, kABPersonImageFormatThumbnail)];
//ABPersonCopyImageData(aRecordRef)];
}
// Create new contact if email exists in the address book
if (aRecordRef) {
Contact *contact = [[Contact alloc] initWithEmail:email
withFirstName:aFirstName
withLastName:aLastName
withImage:anImage];
// Put the new contact into the result array
[contactList addObject:contact];
}
}
// Release ABAddressBookRef
CFRelease(addressBookRef);
return contactList;
}
// Get one specific contact from AddressBookMap
+ (Contact *)getContactWithEmail:(NSString *)email
{
NSMutableArray *contactList = [[NSMutableArray alloc] init];
[contactList addObject:email];
NSMutableArray *contacts = [self getContactList:contactList];
// Get first contact if there is any
Contact *contact;
if ([contacts count] != 0)
contact = [contacts objectAtIndex:0];
return contact;
}
// Get every contacts from myContacts
+ (NSMutableArray *)getMyContacts
{
NSMutableArray *myContacts = [NSMutableArray array];
// Connect to database
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneHelper logc:LinphoneLoggerError format:"Database not ready"];
return myContacts;
}
// Select every message from the remote email address
const char *sql = "SELECT id, contact_email, first_name, last_name FROM my_contacts ORDER BY contact_email ASC";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneHelper logc:LinphoneLoggerError format:"Can't execute the query: %s (%s)", sql, sqlite3_errmsg(database)];
return myContacts;
}
int err;
while ((err = sqlite3_step(sqlStatement)) == SQLITE_ROW) {
Contact *contact = [[Contact alloc] initWithEmail:[NSString stringWithUTF8String: (const char*) sqlite3_column_text(sqlStatement, 0)]
withFirstName:[NSString stringWithUTF8String: (const char*) sqlite3_column_text(sqlStatement, 1)]
withLastName:[NSString stringWithUTF8String: (const char*) sqlite3_column_text(sqlStatement, 2)]
withImage:nil];
[myContacts addObject:contact];
}
if (err != SQLITE_DONE) {
[LinphoneHelper logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
return myContacts;
}
sqlite3_finalize(sqlStatement);
return myContacts;
}
// Get every contacts from AddressBookMap
+ (NSMutableArray *)getAddressBookContacts:(NSMutableArray *)excludeContacts
{
NSMutableArray *emailList = [[NSMutableArray alloc] init];
for (id email in addressBookMap) {
// Do not add email to the list if it's in the exclude list parameter
bool excludeEmail = false;
if (excludeContacts) {
for (Contact *contact in excludeContacts) {
if ([contact.email isEqualToString:email]) {
excludeEmail = true;
}
break;
}
}
if (!excludeEmail) {
[emailList addObject:email];
}
}
return [self getContactList:emailList];
}
// Concat My Contacts and AddressBook Contacts
+ (NSMutableArray *)getAllContacts
{
NSMutableArray *excludeContactList = [[NSMutableArray alloc] init];
// Exclude the registered user from the contact list
Contact *registeredContact = [[Contact alloc] initWithDefault:[LinphoneHelper registeredEmail]];
[excludeContactList addObject:registeredContact];
return [self getAddressBookContacts:excludeContactList];
}
// Get recent call contacts from AddressBookMap
+ (NSMutableArray *)getRecentCallContacts:(const MSList *)logList;
{
const MSList *logListRef;
NSMutableArray *emailList = [[NSMutableArray alloc] init];
// Get a list of emails from logs
logListRef = logList;
while(logListRef != NULL) {
LinphoneCallLog *callLog = (LinphoneCallLog *) logListRef->data;
NSString *email = [LinphoneHelper emailFromCallLog:callLog];
[emailList addObject:email];
logListRef = ms_list_next(logListRef);
}
// Fast load contact details from AddressBookMap
NSMutableArray *contactList = [self getContactList:emailList];
// Create an array for the result recentContactList
NSMutableArray *recentContactList = [[NSMutableArray alloc] init];
// Foreach the contactList and populate the call log attributes
logListRef = logList;
for (id contact in contactList) {
LinphoneCallLog *callLog = (LinphoneCallLog *) logListRef->data;
RecentContact *recentContact = [[RecentContact alloc] initWithCallLog:callLog
withContact:contact];
[recentContactList addObject:recentContact];
logListRef = ms_list_next(logListRef);
}
return recentContactList;
}
// Get recent message contacts from AddressBookMap
+ (NSMutableArray *)getRecentMessageConntacts:(NSMutableArray *)messageLogList
{
NSMutableArray *emailList = [[NSMutableArray alloc] init];
// Get a list of email from message logs
for (Message *message in messageLogList) {
[emailList addObject:message.email];
}
// Fast load contact details from AddressBookMap
NSMutableArray *contactList = [self getContactList:emailList];
// Create an array for the result recentContactList
NSMutableArray *recentMessageContactList = [[NSMutableArray alloc] init];
// Foreach the contactList and populate the message log attributes
for (int i = 0; i < [contactList count]; i++) {
Message *message = messageLogList[i];
Contact *contact = contactList[i];
RecentContact *recentMessageContact = [[RecentContact alloc] initWithMessageLog:message
withContact:contact];
[recentMessageContactList addObject:recentMessageContact];
}
return recentMessageContactList;
}
+ (NSMutableArray *)getRecentContacts:(const MSList *)logList withMessageLogList:(NSMutableArray *)messageLogList
{
NSMutableArray *recentContacts = [[NSMutableArray alloc] init];
// Add recent calls to the list
for (RecentContact *recentCallContact in [self getRecentCallContacts:logList]) {
[recentContacts addObject:recentCallContact];
}
// Add recent messages to the list
for (RecentContact *recentMessageContact in [self getRecentMessageConntacts:messageLogList]) {
[recentContacts addObject:recentMessageContact];
}
// Sort calls and messages into the same list by date
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"recentDate"
ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedRecentContacts = [recentContacts sortedArrayUsingDescriptors:sortDescriptors];
return [sortedRecentContacts mutableCopy];
}
@end