bzr branch
http://bzr.ed.am/android/import-contacts
6
by edam
- added GPL header comments to all files |
1 |
/* |
2 |
* Importer.java |
|
3 |
* |
|
4 |
* Copyright (C) 2009 Tim Marston <edam@waxworlds.org> |
|
5 |
* |
|
6 |
* This file is part of the Import Contacts program (hereafter referred |
|
7 |
* to as "this program"). For more information, see |
|
8 |
* http://www.waxworlds.org/edam/software/android/import-contacts |
|
9 |
* |
|
10 |
* This program is free software: you can redistribute it and/or modify |
|
11 |
* it under the terms of the GNU General Public License as published by |
|
12 |
* the Free Software Foundation, either version 3 of the License, or |
|
13 |
* (at your option) any later version. |
|
14 |
* |
|
15 |
* This program is distributed in the hope that it will be useful, |
|
16 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
17 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
18 |
* GNU General Public License for more details. |
|
19 |
* |
|
20 |
* You should have received a copy of the GNU General Public License |
|
21 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
22 |
*/ |
|
23 |
||
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
24 |
package org.waxworlds.edam.importcontacts; |
1
by edam
Initial import |
25 |
|
26 |
import java.util.HashMap; |
|
27 |
import java.util.Iterator; |
|
28 |
import java.util.Set; |
|
29 |
import java.util.regex.Matcher; |
|
30 |
import java.util.regex.Pattern; |
|
31 |
||
32 |
import android.content.ContentUris; |
|
33 |
import android.content.ContentValues; |
|
34 |
import android.content.SharedPreferences; |
|
35 |
import android.net.Uri; |
|
36 |
import android.os.Message; |
|
37 |
import android.provider.Contacts; |
|
38 |
||
37
by edam
- updated TODO and NEWS |
39 |
|
1
by edam
Initial import |
40 |
public class Importer extends Thread |
41 |
{ |
|
3
by edam
- added "all done" message |
42 |
public final static int ACTION_ABORT = 1; |
43 |
public final static int ACTION_ALLDONE = 2; |
|
1
by edam
Initial import |
44 |
|
45 |
public final static int RESPONSE_NEGATIVE = 0; |
|
46 |
public final static int RESPONSE_POSITIVE = 1; |
|
47 |
||
48 |
public final static int RESPONSEEXTRA_NONE = 0; |
|
49 |
public final static int RESPONSEEXTRA_ALWAYS = 1; |
|
50 |
||
51 |
private Doit _doit; |
|
52 |
private int _response; |
|
53 |
private int _responseExtra; |
|
54 |
private int _mergeSetting; |
|
55 |
private int _lastMergeDecision; |
|
56 |
private boolean _abort = false; |
|
3
by edam
- added "all done" message |
57 |
private boolean _isFinished = false; |
39
by edam
- pulled contacts cache out in to seperate class |
58 |
private ContactsCache _contactsCache = null; |
1
by edam
Initial import |
59 |
|
60 |
public class ContactData |
|
61 |
{ |
|
62 |
class PhoneData |
|
63 |
{ |
|
64 |
public String _number; |
|
65 |
public int _type; |
|
66 |
public boolean _isPreferred; |
|
67 |
||
68 |
public PhoneData( String number, int type, boolean isPreferred ) { |
|
69 |
_number = number; |
|
70 |
_type = type; |
|
71 |
_isPreferred = isPreferred; |
|
72 |
} |
|
73 |
||
74 |
public String getNumber() { |
|
75 |
return _number; |
|
76 |
} |
|
77 |
||
78 |
public int getType() { |
|
79 |
return _type; |
|
80 |
} |
|
81 |
||
82 |
public boolean isPreferred() { |
|
83 |
return _isPreferred; |
|
84 |
} |
|
85 |
} |
|
86 |
||
87 |
class EmailData |
|
88 |
{ |
|
89 |
private String _email; |
|
90 |
public int _type; |
|
91 |
private boolean _isPreferred; |
|
92 |
||
93 |
public EmailData( String email, int type, boolean isPreferred ) { |
|
94 |
_email = email; |
|
95 |
_type = type; |
|
96 |
_isPreferred = isPreferred; |
|
97 |
} |
|
98 |
||
99 |
public String getAddress() { |
|
100 |
return _email; |
|
101 |
} |
|
102 |
||
103 |
public int getType() { |
|
104 |
return _type; |
|
105 |
} |
|
106 |
||
107 |
public boolean isPreferred() { |
|
108 |
return _isPreferred; |
|
109 |
} |
|
110 |
} |
|
111 |
||
37
by edam
- updated TODO and NEWS |
112 |
class AddressData |
113 |
{ |
|
114 |
private String _address; |
|
115 |
public int _type; |
|
116 |
||
117 |
public AddressData( String address, int type ) { |
|
118 |
_address = address; |
|
119 |
_type = type; |
|
120 |
} |
|
121 |
||
122 |
public String getAddress() { |
|
123 |
return _address; |
|
124 |
} |
|
125 |
||
126 |
public int getType() { |
|
127 |
return _type; |
|
128 |
} |
|
129 |
} |
|
130 |
||
1
by edam
Initial import |
131 |
public String _name = null; |
132 |
public HashMap< String, PhoneData > _phones = null; |
|
133 |
public HashMap< String, EmailData > _emails = null; |
|
37
by edam
- updated TODO and NEWS |
134 |
public HashMap< String, AddressData > _addresses = null; |
1
by edam
Initial import |
135 |
|
136 |
protected void setName( String name ) |
|
137 |
{ |
|
138 |
_name = name; |
|
139 |
} |
|
140 |
||
141 |
public String getName() |
|
142 |
{ |
|
143 |
return _name; |
|
144 |
} |
|
145 |
||
146 |
protected void addPhone( String number, int type, boolean isPreferred ) |
|
147 |
{ |
|
148 |
if( _phones == null ) _phones = new HashMap< String, PhoneData >(); |
|
149 |
if( !_phones.containsKey( number ) ) |
|
150 |
_phones.put( number, |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
151 |
new PhoneData( number, type, isPreferred ) ); |
1
by edam
Initial import |
152 |
} |
153 |
||
154 |
protected void addEmail( String email, int type, boolean isPreferred ) |
|
155 |
{ |
|
156 |
if( _emails == null ) _emails = new HashMap< String, EmailData >(); |
|
157 |
if( !_emails.containsKey( email ) ) |
|
158 |
_emails.put( email, new EmailData( email, type, isPreferred ) ); |
|
159 |
} |
|
37
by edam
- updated TODO and NEWS |
160 |
|
161 |
protected void addAddress( String address, int type ) |
|
162 |
{ |
|
163 |
if( _addresses == null ) _addresses = |
|
164 |
new HashMap< String, AddressData >(); |
|
165 |
if( !_addresses.containsKey( address ) ) |
|
166 |
_addresses.put( address, new AddressData( address, type ) ); |
|
167 |
} |
|
1
by edam
Initial import |
168 |
} |
169 |
||
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
170 |
@SuppressWarnings("serial") |
1
by edam
Initial import |
171 |
protected class AbortImportException extends Exception { }; |
172 |
||
173 |
public Importer( Doit doit ) |
|
174 |
{ |
|
175 |
_doit = doit; |
|
176 |
||
177 |
SharedPreferences prefs = getSharedPreferences(); |
|
9
by edam
- added scroll view to all layouts |
178 |
_mergeSetting = prefs.getInt( "merge_setting", Doit.ACTION_PROMPT ); |
1
by edam
Initial import |
179 |
} |
180 |
||
181 |
@Override |
|
182 |
public void run() |
|
183 |
{ |
|
184 |
try |
|
185 |
{ |
|
39
by edam
- pulled contacts cache out in to seperate class |
186 |
// update UI |
187 |
setProgressMessage( R.string.doit_caching ); |
|
188 |
||
189 |
// build a cache of existing contacts |
|
190 |
_contactsCache = new ContactsCache(); |
|
191 |
_contactsCache.buildCache( _doit ); |
|
1
by edam
Initial import |
192 |
|
193 |
// do the import |
|
194 |
onImport(); |
|
195 |
||
196 |
// done! |
|
3
by edam
- added "all done" message |
197 |
finish( ACTION_ALLDONE ); |
1
by edam
Initial import |
198 |
} |
199 |
catch( AbortImportException e ) |
|
200 |
{} |
|
3
by edam
- added "all done" message |
201 |
|
202 |
// flag as finished to prevent interrupts |
|
203 |
setIsFinished(); |
|
204 |
} |
|
205 |
||
206 |
synchronized private void setIsFinished() |
|
207 |
{ |
|
208 |
_isFinished = true; |
|
1
by edam
Initial import |
209 |
} |
210 |
||
211 |
protected void onImport() throws AbortImportException |
|
212 |
{ |
|
213 |
} |
|
214 |
||
215 |
public void wake() |
|
216 |
{ |
|
217 |
wake( 0, RESPONSEEXTRA_NONE ); |
|
218 |
} |
|
219 |
||
220 |
public void wake( int response ) |
|
221 |
{ |
|
222 |
wake( response, RESPONSEEXTRA_NONE ); |
|
223 |
} |
|
224 |
||
225 |
synchronized public void wake( int response, int responseExtra ) |
|
226 |
{ |
|
227 |
_response = response; |
|
228 |
_responseExtra = responseExtra; |
|
229 |
notify(); |
|
230 |
} |
|
231 |
||
3
by edam
- added "all done" message |
232 |
synchronized public boolean setAbort() |
1
by edam
Initial import |
233 |
{ |
3
by edam
- added "all done" message |
234 |
if( !_isFinished && !_abort ) { |
235 |
_abort = true; |
|
236 |
notify(); |
|
237 |
return true; |
|
238 |
} |
|
239 |
return false; |
|
1
by edam
Initial import |
240 |
} |
241 |
||
242 |
protected SharedPreferences getSharedPreferences() |
|
243 |
{ |
|
244 |
return _doit.getSharedPreferences(); |
|
245 |
} |
|
246 |
||
247 |
protected void showError( int res ) throws AbortImportException |
|
248 |
{ |
|
249 |
showError( _doit.getText( res ).toString() ); |
|
250 |
} |
|
251 |
||
252 |
synchronized protected void showError( String message ) |
|
253 |
throws AbortImportException |
|
254 |
{ |
|
255 |
checkAbort(); |
|
256 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
257 |
_doit._handler, Doit.MESSAGE_ERROR, message ) ); |
1
by edam
Initial import |
258 |
try { |
259 |
wait(); |
|
260 |
} |
|
261 |
catch( InterruptedException e ) { } |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
262 |
|
3
by edam
- added "all done" message |
263 |
// no need to check if an abortion happened during the wait, we are |
264 |
// about to finish anyway! |
|
265 |
finish( ACTION_ABORT ); |
|
1
by edam
Initial import |
266 |
} |
267 |
||
268 |
protected void showFatalError( int res ) throws AbortImportException |
|
269 |
{ |
|
270 |
showFatalError( _doit.getText( res ).toString() ); |
|
271 |
} |
|
272 |
||
273 |
synchronized protected void showFatalError( String message ) |
|
274 |
throws AbortImportException |
|
275 |
{ |
|
276 |
checkAbort(); |
|
277 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
278 |
_doit._handler, Doit.MESSAGE_ERROR, message ) ); |
1
by edam
Initial import |
279 |
try { |
280 |
wait(); |
|
281 |
} |
|
282 |
catch( InterruptedException e ) { } |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
283 |
|
3
by edam
- added "all done" message |
284 |
// no need to check if an abortion happened during the wait, we are |
285 |
// about to finish anyway! |
|
286 |
finish( ACTION_ABORT ); |
|
1
by edam
Initial import |
287 |
} |
288 |
||
289 |
protected boolean showContinue( int res ) throws AbortImportException |
|
290 |
{ |
|
291 |
return showContinue( _doit.getText( res ).toString() ); |
|
292 |
} |
|
293 |
||
294 |
synchronized protected boolean showContinue( String message ) |
|
295 |
throws AbortImportException |
|
296 |
{ |
|
297 |
checkAbort(); |
|
298 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
299 |
_doit._handler, Doit.MESSAGE_CONTINUEORABORT, message ) ); |
1
by edam
Initial import |
300 |
try { |
301 |
wait(); |
|
302 |
} |
|
303 |
catch( InterruptedException e ) { } |
|
3
by edam
- added "all done" message |
304 |
|
305 |
// check if an abortion happened during the wait |
|
306 |
checkAbort(); |
|
307 |
||
1
by edam
Initial import |
308 |
return _response == RESPONSE_POSITIVE; |
309 |
} |
|
310 |
||
311 |
protected void setProgressMessage( int res ) throws AbortImportException |
|
312 |
{ |
|
313 |
checkAbort(); |
|
314 |
_doit._handler.sendMessage( Message.obtain( _doit._handler, |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
315 |
Doit.MESSAGE_SETPROGRESSMESSAGE, getText( res ) ) ); |
1
by edam
Initial import |
316 |
} |
317 |
||
318 |
protected void setProgressMax( int maxProgress ) |
|
319 |
throws AbortImportException |
|
320 |
{ |
|
321 |
checkAbort(); |
|
322 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
323 |
_doit._handler, Doit.MESSAGE_SETMAXPROGRESS, |
324 |
new Integer( maxProgress ) ) ); |
|
1
by edam
Initial import |
325 |
} |
326 |
||
327 |
protected void setTmpProgress( int tmpProgress ) throws AbortImportException |
|
328 |
{ |
|
329 |
checkAbort(); |
|
330 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
331 |
_doit._handler, Doit.MESSAGE_SETTMPPROGRESS, |
332 |
new Integer( tmpProgress ) ) ); |
|
1
by edam
Initial import |
333 |
} |
334 |
||
335 |
protected void setProgress( int progress ) throws AbortImportException |
|
336 |
{ |
|
337 |
checkAbort(); |
|
338 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
339 |
_doit._handler, Doit.MESSAGE_SETPROGRESS, |
340 |
new Integer( progress ) ) ); |
|
1
by edam
Initial import |
341 |
} |
342 |
||
3
by edam
- added "all done" message |
343 |
protected void finish( int action ) throws AbortImportException |
1
by edam
Initial import |
344 |
{ |
3
by edam
- added "all done" message |
345 |
// update UI to reflect action |
346 |
int message; |
|
347 |
switch( action ) |
|
348 |
{ |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
349 |
case ACTION_ALLDONE: message = Doit.MESSAGE_ALLDONE; break; |
3
by edam
- added "all done" message |
350 |
default: // fall through |
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
351 |
case ACTION_ABORT: message = Doit.MESSAGE_ABORT; break; |
3
by edam
- added "all done" message |
352 |
} |
353 |
_doit._handler.sendEmptyMessage( message ); |
|
1
by edam
Initial import |
354 |
|
3
by edam
- added "all done" message |
355 |
// stop |
356 |
throw new AbortImportException(); |
|
1
by edam
Initial import |
357 |
} |
358 |
||
359 |
protected CharSequence getText( int res ) |
|
360 |
{ |
|
361 |
return _doit.getText( res ); |
|
362 |
} |
|
363 |
||
364 |
protected boolean isImportRequired( String name ) |
|
365 |
throws AbortImportException |
|
366 |
{ |
|
367 |
checkAbort(); |
|
368 |
return isImportRequired( name, _mergeSetting ); |
|
369 |
} |
|
370 |
||
3
by edam
- added "all done" message |
371 |
synchronized private boolean isImportRequired( String name, |
372 |
int mergeSetting ) throws AbortImportException |
|
1
by edam
Initial import |
373 |
{ |
374 |
_lastMergeDecision = mergeSetting; |
|
375 |
||
376 |
// handle special cases |
|
377 |
switch( mergeSetting ) |
|
378 |
{ |
|
9
by edam
- added scroll view to all layouts |
379 |
case Doit.ACTION_KEEP: |
1
by edam
Initial import |
380 |
// if we keep contacts on duplicate, we better check for one |
39
by edam
- pulled contacts cache out in to seperate class |
381 |
return !_contactsCache.exists( name ); |
1
by edam
Initial import |
382 |
|
9
by edam
- added scroll view to all layouts |
383 |
case Doit.ACTION_PROMPT: |
1
by edam
Initial import |
384 |
// if we are prompting on duplicate, we better check for one |
39
by edam
- pulled contacts cache out in to seperate class |
385 |
if( !_contactsCache.exists( name ) ) |
1
by edam
Initial import |
386 |
return true; |
387 |
||
388 |
// ok, it exists, so do prompt |
|
389 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
390 |
_doit._handler, Doit.MESSAGE_MERGEPROMPT, name ) ); |
1
by edam
Initial import |
391 |
try { |
392 |
wait(); |
|
393 |
} |
|
394 |
catch( InterruptedException e ) { } |
|
395 |
||
3
by edam
- added "all done" message |
396 |
// check if an abortion happened during the wait |
397 |
checkAbort(); |
|
398 |
||
1
by edam
Initial import |
399 |
// if "always" was selected, make choice permenant |
400 |
if( _responseExtra == RESPONSEEXTRA_ALWAYS ) |
|
401 |
_mergeSetting = _response; |
|
402 |
||
36
by edam
- formatting: removed some double-indents on overrunning lines |
403 |
// recurse, with our new merge setting |
1
by edam
Initial import |
404 |
return isImportRequired( name, _response ); |
405 |
} |
|
406 |
||
407 |
// for all other cases (either overwriting or merging) we will need the |
|
408 |
// imported data |
|
409 |
return true; |
|
410 |
} |
|
411 |
||
412 |
protected void skipContact() throws AbortImportException |
|
413 |
{ |
|
414 |
checkAbort(); |
|
3
by edam
- added "all done" message |
415 |
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTSKIPPED ); |
1
by edam
Initial import |
416 |
} |
417 |
||
418 |
protected void importContact( ContactData contact ) |
|
419 |
throws AbortImportException |
|
420 |
{ |
|
421 |
checkAbort(); |
|
422 |
||
3
by edam
- added "all done" message |
423 |
// if( !showContinue( "====[ IMPORTING ]====\n: " + contact._name ) ) |
424 |
// finish( ACTION_ABORT ); |
|
1
by edam
Initial import |
425 |
|
426 |
ContentValues values = new ContentValues(); |
|
427 |
boolean uiInformed = false; |
|
428 |
||
429 |
// does contact exist already? |
|
430 |
Uri contactUri = null; |
|
431 |
Long id; |
|
39
by edam
- pulled contacts cache out in to seperate class |
432 |
if( ( id = (Long)_contactsCache.getId( contact._name ) ) != null ) |
1
by edam
Initial import |
433 |
{ |
434 |
// should we skip this import altogether? |
|
9
by edam
- added scroll view to all layouts |
435 |
if( _lastMergeDecision == Doit.ACTION_KEEP ) return; |
1
by edam
Initial import |
436 |
|
437 |
// get contact's URI |
|
438 |
contactUri = ContentUris.withAppendedId( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
439 |
Contacts.People.CONTENT_URI, id ); |
1
by edam
Initial import |
440 |
|
441 |
// should we destroy the existing contact before importing? |
|
9
by edam
- added scroll view to all layouts |
442 |
if( _lastMergeDecision == Doit.ACTION_OVERWRITE ) { |
1
by edam
Initial import |
443 |
_doit.getContentResolver().delete( contactUri, null, null ); |
444 |
contactUri = null; |
|
445 |
||
36
by edam
- formatting: removed some double-indents on overrunning lines |
446 |
// update the UI |
447 |
_doit._handler.sendEmptyMessage( |
|
448 |
Doit.MESSAGE_CONTACTOVERWRITTEN ); |
|
1
by edam
Initial import |
449 |
uiInformed = true; |
450 |
||
451 |
// update cache |
|
39
by edam
- pulled contacts cache out in to seperate class |
452 |
_contactsCache.remove( contact._name ); |
1
by edam
Initial import |
453 |
} |
454 |
} |
|
455 |
||
456 |
// if we don't have a contact URI it is because the contact never |
|
457 |
// existed or because we deleted it |
|
458 |
if( contactUri == null ) |
|
459 |
{ |
|
460 |
// create a new contact |
|
461 |
values.put( Contacts.People.NAME, contact._name ); |
|
462 |
contactUri = _doit.getContentResolver().insert( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
463 |
Contacts.People.CONTENT_URI, values ); |
1
by edam
Initial import |
464 |
id = ContentUris.parseId( contactUri ); |
465 |
if( id <= 0 ) return; // shouldn't happen! |
|
466 |
||
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
467 |
// try to add them to the "My Contacts" group |
468 |
try { |
|
469 |
Contacts.People.addToMyContactsGroup( |
|
12
by edam
- bugfix: add contacts to the "my contacts" group didn't actually work on a real device. So we're doing it a different way. |
470 |
_doit.getContentResolver(), id ); |
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
471 |
} |
36
by edam
- formatting: removed some double-indents on overrunning lines |
472 |
catch( IllegalStateException e ) { |
473 |
// ignore any failure |
|
474 |
} |
|
1
by edam
Initial import |
475 |
|
476 |
// update cache |
|
39
by edam
- pulled contacts cache out in to seperate class |
477 |
_contactsCache.put( id, contact._name ); |
1
by edam
Initial import |
478 |
|
479 |
// update UI |
|
480 |
if( !uiInformed ) { |
|
3
by edam
- added "all done" message |
481 |
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTCREATED ); |
1
by edam
Initial import |
482 |
uiInformed = true; |
483 |
} |
|
484 |
} |
|
485 |
||
486 |
// update UI |
|
487 |
if( !uiInformed ) |
|
3
by edam
- added "all done" message |
488 |
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTMERGED ); |
1
by edam
Initial import |
489 |
|
490 |
// import contact parts |
|
491 |
if( contact._phones != null ) |
|
492 |
importContactPhones( contactUri, contact._phones ); |
|
493 |
if( contact._emails != null ) |
|
494 |
importContactEmails( contactUri, contact._emails ); |
|
37
by edam
- updated TODO and NEWS |
495 |
if( contact._addresses != null ) |
496 |
importContactAddresses( contactUri, contact._addresses ); |
|
1
by edam
Initial import |
497 |
} |
498 |
||
499 |
private void importContactPhones( Uri contactUri, |
|
500 |
HashMap< String, ContactData.PhoneData > phones ) |
|
501 |
{ |
|
502 |
Long contactId = ContentUris.parseId( contactUri ); |
|
503 |
Uri contactPhonesUri = Uri.withAppendedPath( contactUri, |
|
504 |
Contacts.People.Phones.CONTENT_DIRECTORY ); |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
505 |
Set< String > phonesKeys = phones.keySet(); |
7
by edam
- new contact's phone numebrs and email addresses are added to the caches after those contacts are updated to account for the situation where the same contact is imported again from another file (or the contact exists twice in the same file!?) |
506 |
|
507 |
// add phone numbers |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
508 |
Iterator< String > i = phonesKeys.iterator(); |
1
by edam
Initial import |
509 |
while( i.hasNext() ) { |
510 |
ContactData.PhoneData phone = phones.get( i.next() ); |
|
511 |
||
512 |
// we don't want to add this number if it's crap, or it already |
|
513 |
// exists (which would cause a duplicate to be created). We don't |
|
514 |
// take in to account the type when checking for duplicates. This is |
|
515 |
// intentional: types aren't really very reliable. We assume that |
|
516 |
// if the number exists at all, it doesn't need importing. Because |
|
517 |
// of this, we also can't update the cache (which we don't need to |
|
518 |
// anyway, so it's not a problem). |
|
519 |
String number = sanitisePhoneNumber( phone._number ); |
|
520 |
if( number == null ) continue; |
|
39
by edam
- pulled contacts cache out in to seperate class |
521 |
if( _contactsCache.hasNumber( contactId, number ) ) continue; |
1
by edam
Initial import |
522 |
|
523 |
// add phone number |
|
524 |
ContentValues values = new ContentValues(); |
|
525 |
values.put( Contacts.Phones.TYPE, phone._type ); |
|
526 |
values.put( Contacts.Phones.NUMBER, phone._number ); |
|
527 |
if( phone._isPreferred ) values.put( Contacts.Phones.ISPRIMARY, 1 ); |
|
528 |
_doit.getContentResolver().insert( contactPhonesUri, values ); |
|
37
by edam
- updated TODO and NEWS |
529 |
|
530 |
// and add this address to the cache to prevent a addition of |
|
531 |
// duplicate date from another file |
|
39
by edam
- pulled contacts cache out in to seperate class |
532 |
_contactsCache.addNumber( contactId, number ); |
7
by edam
- new contact's phone numebrs and email addresses are added to the caches after those contacts are updated to account for the situation where the same contact is imported again from another file (or the contact exists twice in the same file!?) |
533 |
} |
1
by edam
Initial import |
534 |
} |
535 |
||
536 |
private void importContactEmails( Uri contactUri, |
|
537 |
HashMap< String, ContactData.EmailData > emails ) |
|
538 |
{ |
|
539 |
Long contactId = ContentUris.parseId( contactUri ); |
|
540 |
Uri contactContactMethodsUri = Uri.withAppendedPath( contactUri, |
|
541 |
Contacts.People.ContactMethods.CONTENT_DIRECTORY ); |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
542 |
Set< String > emailsKeys = emails.keySet(); |
7
by edam
- new contact's phone numebrs and email addresses are added to the caches after those contacts are updated to account for the situation where the same contact is imported again from another file (or the contact exists twice in the same file!?) |
543 |
|
544 |
// add email addresses |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
545 |
Iterator< String > i = emailsKeys.iterator(); |
1
by edam
Initial import |
546 |
while( i.hasNext() ) { |
547 |
ContactData.EmailData email = emails.get( i.next() ); |
|
548 |
||
37
by edam
- updated TODO and NEWS |
549 |
// we don't want to add this email address if it exists already or |
550 |
// we would introduce duplicates. |
|
1
by edam
Initial import |
551 |
String address = sanitiseEmailAddress( email.getAddress() ); |
552 |
if( address == null ) continue; |
|
39
by edam
- pulled contacts cache out in to seperate class |
553 |
if( _contactsCache.hasEmail( contactId, address ) ) continue; |
1
by edam
Initial import |
554 |
|
555 |
// add phone number |
|
556 |
ContentValues values = new ContentValues(); |
|
557 |
values.put( Contacts.ContactMethods.KIND, Contacts.KIND_EMAIL ); |
|
558 |
values.put( Contacts.ContactMethods.DATA, email.getAddress() ); |
|
559 |
values.put( Contacts.ContactMethods.TYPE, email.getType() ); |
|
560 |
if( email.isPreferred() ) |
|
561 |
values.put( Contacts.ContactMethods.ISPRIMARY, 1 ); |
|
562 |
_doit.getContentResolver().insert( contactContactMethodsUri, |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
563 |
values ); |
37
by edam
- updated TODO and NEWS |
564 |
|
565 |
// and add this address to the cache to prevent a addition of |
|
566 |
// duplicate date from another file |
|
39
by edam
- pulled contacts cache out in to seperate class |
567 |
_contactsCache.addEmail( contactId, address ); |
1
by edam
Initial import |
568 |
} |
37
by edam
- updated TODO and NEWS |
569 |
} |
570 |
||
571 |
private void importContactAddresses( Uri contactUri, |
|
572 |
HashMap< String, ContactData.AddressData > addresses ) |
|
573 |
{ |
|
574 |
Long contactId = ContentUris.parseId( contactUri ); |
|
575 |
Uri contactContactMethodsUri = Uri.withAppendedPath( contactUri, |
|
576 |
Contacts.People.ContactMethods.CONTENT_DIRECTORY ); |
|
577 |
Set< String > addressesKeys = addresses.keySet(); |
|
578 |
||
579 |
// add addresses |
|
580 |
Iterator< String > i = addressesKeys.iterator(); |
|
7
by edam
- new contact's phone numebrs and email addresses are added to the caches after those contacts are updated to account for the situation where the same contact is imported again from another file (or the contact exists twice in the same file!?) |
581 |
while( i.hasNext() ) { |
37
by edam
- updated TODO and NEWS |
582 |
ContactData.AddressData address = addresses.get( i.next() ); |
583 |
||
584 |
// we don't want to add this address if it exists already or we |
|
585 |
// would introduce duplicates |
|
586 |
if( address == null ) continue; |
|
39
by edam
- pulled contacts cache out in to seperate class |
587 |
if( _contactsCache.hasAddress( contactId, address.getAddress() ) ) |
37
by edam
- updated TODO and NEWS |
588 |
continue; |
589 |
||
590 |
// add postal address |
|
591 |
ContentValues values = new ContentValues(); |
|
592 |
values.put( Contacts.ContactMethods.KIND, Contacts.KIND_POSTAL ); |
|
593 |
values.put( Contacts.ContactMethods.DATA, address.getAddress() ); |
|
594 |
values.put( Contacts.ContactMethods.TYPE, address.getType() ); |
|
595 |
_doit.getContentResolver().insert( contactContactMethodsUri, |
|
596 |
values ); |
|
597 |
||
598 |
// and add this address to the cache to prevent a addition of |
|
599 |
// duplicate date from another file |
|
39
by edam
- pulled contacts cache out in to seperate class |
600 |
_contactsCache.addAddress( contactId, address.getAddress() ); |
7
by edam
- new contact's phone numebrs and email addresses are added to the caches after those contacts are updated to account for the situation where the same contact is imported again from another file (or the contact exists twice in the same file!?) |
601 |
} |
1
by edam
Initial import |
602 |
} |
603 |
||
3
by edam
- added "all done" message |
604 |
synchronized protected void checkAbort() throws AbortImportException |
1
by edam
Initial import |
605 |
{ |
606 |
if( _abort ) { |
|
607 |
// stop |
|
608 |
throw new AbortImportException(); |
|
609 |
} |
|
610 |
} |
|
611 |
||
39
by edam
- pulled contacts cache out in to seperate class |
612 |
static public String sanitisePhoneNumber( String number ) |
1
by edam
Initial import |
613 |
{ |
614 |
number = number.replaceAll( "[-\\(\\) ]", "" ); |
|
24
by edam
- import phone numbers even when they have no specified type (default to mobile) |
615 |
Pattern p = Pattern.compile( "^[\\+0-9#*]+" ); |
1
by edam
Initial import |
616 |
Matcher m = p.matcher( number ); |
617 |
if( m.lookingAt() ) return m.group( 0 ); |
|
618 |
return null; |
|
619 |
} |
|
620 |
||
39
by edam
- pulled contacts cache out in to seperate class |
621 |
static public String sanitiseEmailAddress( String address ) |
1
by edam
Initial import |
622 |
{ |
623 |
address = address.trim(); |
|
624 |
Pattern p = Pattern.compile( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
625 |
"^[^ @]+@[a-zA-Z]([-a-zA-Z0-9]*[a-zA-z0-9])?(\\.[a-zA-Z]([-a-zA-Z0-9]*[a-zA-z0-9])?)+$" ); |
1
by edam
Initial import |
626 |
Matcher m = p.matcher( address ); |
627 |
if( m.matches() ) { |
|
628 |
String[] bits = address.split( "@" ); |
|
629 |
return bits[ 0 ] + "@" + bits[ 1 ].toLowerCase(); |
|
630 |
} |
|
631 |
return null; |
|
632 |
} |
|
633 |
} |