4
* Copyright (C) 2011 to 2013 Tim Marston <tim@ed.am>
6
* This file is part of the Export Contacts program (hereafter referred
7
* to as "this program"). For more information, see
8
* http://ed.am/dev/android/export-contacts
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.
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.
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/>.
24
package am.ed.exportcontacts;
26
import java.util.ArrayList;
28
import android.content.SharedPreferences;
29
import android.os.Message;
32
public class Exporter extends Thread
34
public final static int ACTION_ABORT = 1;
35
public final static int ACTION_ALLDONE = 2;
37
public final static int RESPONSE_NEGATIVE = 0;
38
public final static int RESPONSE_POSITIVE = 1;
40
public final static int RESPONSEEXTRA_NONE = 0;
41
public final static int RESPONSEEXTRA_ALWAYS = 1;
44
private int _response;
45
private boolean _abort = false;
46
private boolean _is_finished = false;
49
* Data about a contact
51
public class ContactData
53
public final static int TYPE_HOME = 0;
54
public final static int TYPE_WORK = 1;
55
public final static int TYPE_MOBILE = 2; // only used with phones
56
public final static int TYPE_FAX_HOME = 3; // only used with phones
57
public final static int TYPE_FAX_WORK = 4; // only used with phones
58
public final static int TYPE_PAGER = 5; // only used with phones
60
class OrganisationDetail
62
protected String _org;
63
protected String _title;
65
public OrganisationDetail( String org, String title )
67
_org = org != null && org.length() > 0? org : null;
68
_title = title != null && title.length() > 0? title : null;
71
public String getOrganisation()
76
public String getTitle()
85
protected String _num;
87
public NumberDetail( int type, String num )
90
_num = num != null && num.length() > 0? num : null;
98
public String getNumber()
107
protected String _email;
109
public EmailDetail( int type, String email )
112
_email = email != null && email.length() > 0? email : null;
120
public String getEmail()
129
protected String _addr;
131
public AddressDetail( int type, String addr )
134
_addr = addr != null && addr.length() > 0? addr : null;
142
public String getAddress()
148
protected String _name = null;
149
protected ArrayList< OrganisationDetail > _organisations = null;
150
protected ArrayList< NumberDetail > _numbers = null;
151
protected ArrayList< EmailDetail > _emails = null;
152
protected ArrayList< AddressDetail > _addresses = null;
153
protected ArrayList< String > _notes = null;
154
protected String _birthday = null;
156
public void setName( String name )
158
_name = name != null && name.length() > 0? name : null;
161
public String getName()
166
public void addOrganisation( OrganisationDetail organisation )
168
if( organisation.getOrganisation() == null ) return;
169
if( _organisations == null )
170
_organisations = new ArrayList< OrganisationDetail >();
171
_organisations.add( organisation );
174
public ArrayList< OrganisationDetail > getOrganisations()
176
return _organisations;
179
public void addNumber( NumberDetail number )
181
if( number.getNumber() == null ) return;
182
if( _numbers == null )
183
_numbers = new ArrayList< NumberDetail >();
184
_numbers.add( number );
187
public ArrayList< NumberDetail > getNumbers()
192
public void addEmail( EmailDetail email )
194
if( email.getEmail() == null ) return;
195
if( _emails == null )
196
_emails = new ArrayList< EmailDetail >();
197
_emails.add( email );
200
public ArrayList< EmailDetail > getEmails()
205
public void addAddress( AddressDetail address )
207
if( address.getAddress() == null ) return;
208
if( _addresses == null )
209
_addresses = new ArrayList< AddressDetail >();
210
_addresses.add( address );
213
public ArrayList< AddressDetail > getAddresses()
218
public void addNote( String note )
221
_notes = new ArrayList< String >();
225
public ArrayList< String > getNotes()
230
public void setBirthday( String birthday )
232
_birthday = birthday;
235
public String getBirthday()
240
public String getPrimaryIdentifier()
245
if( _organisations != null &&
246
_organisations.get( 0 ).getOrganisation() != null )
247
return _organisations.get( 0 ).getOrganisation();
249
if( _numbers!= null &&
250
_numbers.get( 0 ).getNumber() != null )
251
return _numbers.get( 0 ).getNumber();
253
if( _emails!= null &&
254
_emails.get( 0 ).getEmail() != null )
255
return _emails.get( 0 ).getEmail();
257
// no primary identifier
262
@SuppressWarnings( "serial" )
263
protected class AbortExportException extends Exception { };
265
public Exporter( Doit doit )
276
setProgressMessage( R.string.doit_scanning );
282
finish( ACTION_ALLDONE );
284
catch( AbortExportException e )
287
// flag as finished to prevent interrupts
291
synchronized private void setIsFinished()
296
protected void exportContacts() throws AbortExportException
298
// set up a contact reader
299
Backend backend = null;
300
if( Integer.parseInt( android.os.Build.VERSION.SDK ) >= 5 )
301
backend = new ContactsContractBackend( _doit, this );
303
backend = new ContactsBackend( _doit, this );
305
// check we have contacts
306
int num_contacts = backend.getNumContacts();
307
if( num_contacts == 0 )
308
showError( R.string.error_nothingtodo );
310
// count the number of contacts and set the progress bar max
312
setProgressMax( num_contacts );
317
// loop through contacts
321
ContactData contact = new ContactData();
322
if( !backend.getNextContact( contact ) )
327
if( exportContact( contact ) )
328
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTWRITTEN );
330
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTSKIPPED );
331
setProgress( count++ );
333
setProgress( num_contacts );
343
synchronized public void wake( int response )
345
_response = response;
349
synchronized public boolean setAbort()
351
if( !_is_finished && !_abort ) {
359
protected SharedPreferences getSharedPreferences()
361
return _doit.getSharedPreferences();
364
protected void showError( int res ) throws AbortExportException
366
showError( _doit.getText( res ).toString() );
369
synchronized protected void showError( String message )
370
throws AbortExportException
373
_doit._handler.sendMessage( Message.obtain(
374
_doit._handler, Doit.MESSAGE_ERROR, message ) );
378
catch( InterruptedException e ) { }
380
// no need to check if an abortion happened during the wait, we are
381
// about to finish anyway!
382
finish( ACTION_ABORT );
385
protected void showContinueOrAbort( int res ) throws AbortExportException
387
showContinueOrAbort( _doit.getText( res ).toString() );
390
synchronized protected void showContinueOrAbort( String message )
391
throws AbortExportException
394
_doit._handler.sendMessage( Message.obtain(
395
_doit._handler, Doit.MESSAGE_CONTINUEORABORT, message ) );
399
catch( InterruptedException e ) { }
401
// if we're aborting, there's no need to check if an abortion happened
403
if( _response == RESPONSE_NEGATIVE )
404
finish( ACTION_ABORT );
409
protected void setProgressMessage( int res ) throws AbortExportException
412
_doit._handler.sendMessage( Message.obtain( _doit._handler,
413
Doit.MESSAGE_SETPROGRESSMESSAGE, getText( res ) ) );
416
protected void setProgressMax( int max_progress )
417
throws AbortExportException
420
_doit._handler.sendMessage( Message.obtain(
421
_doit._handler, Doit.MESSAGE_SETMAXPROGRESS,
422
Integer.valueOf( max_progress ) ) );
425
protected void setTmpProgress( int tmp_progress )
426
throws AbortExportException
429
_doit._handler.sendMessage( Message.obtain(
430
_doit._handler, Doit.MESSAGE_SETTMPPROGRESS,
431
Integer.valueOf( tmp_progress ) ) );
434
protected void setProgress( int progress ) throws AbortExportException
437
_doit._handler.sendMessage( Message.obtain(
438
_doit._handler, Doit.MESSAGE_SETPROGRESS,
439
Integer.valueOf( progress ) ) );
442
protected void finish( int action ) throws AbortExportException
444
// update UI to reflect action
448
case ACTION_ALLDONE: message = Doit.MESSAGE_ALLDONE; break;
449
default: // fall through
450
case ACTION_ABORT: message = Doit.MESSAGE_ABORT; break;
452
_doit._handler.sendEmptyMessage( message );
455
throw new AbortExportException();
458
protected CharSequence getText( int res )
460
return _doit.getText( res );
463
protected void skipContact() throws AbortExportException
466
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTSKIPPED );
469
synchronized protected void checkAbort() throws AbortExportException
473
throw new AbortExportException();
477
protected void preExport() throws AbortExportException
481
protected boolean exportContact( ContactData contact )
482
throws AbortExportException
484
throw new UnsupportedOperationException();
487
protected void postExport() throws AbortExportException