/android/import-contacts

To get this branch, use:
bzr branch http://bzr.ed.am/android/import-contacts
6 by edam
- added GPL header comments to all files
1
/*
2
 * Doit.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
1 by edam
Initial import
24
package org.waxworlds.importcontacts;
25
26
import android.app.AlertDialog;
27
import android.app.Dialog;
28
import android.content.DialogInterface;
29
import android.content.Intent;
30
import android.os.Bundle;
31
import android.os.Handler;
32
import android.os.Message;
33
import android.view.LayoutInflater;
34
import android.view.View;
35
import android.view.View.OnClickListener;
36
import android.widget.Button;
37
import android.widget.CheckBox;
38
import android.widget.CompoundButton;
39
import android.widget.LinearLayout;
40
import android.widget.ProgressBar;
41
import android.widget.TextView;
2 by edam
- added toaster message about import abortion in onPause()
42
import android.widget.Toast;
1 by edam
Initial import
43
44
public class Doit extends WizardActivity
45
{
46
	private final static int DIALOG_ERROR = 0;
47
	private final static int DIALOG_CONTINUEORABORT = 1;
48
	private final static int DIALOG_MERGEPROMPT = 2;
49
3 by edam
- added "all done" message
50
	public final static int MESSAGE_FINISHED_ALLDONE = 0;
51
	public final static int MESSAGE_FINISHED = 1;
52
	public final static int MESSAGE_FINISHED_GOBACK = 2;
53
	public final static int MESSAGE_ERROR = 3;
54
	public final static int MESSAGE_CONTINUEORABORT = 4;
55
	public final static int MESSAGE_SETPROGRESSMESSAGE = 5;
56
	public final static int MESSAGE_SETMAXPROGRESS = 6;
57
	public final static int MESSAGE_SETTMPPROGRESS = 7;
58
	public final static int MESSAGE_SETPROGRESS = 8;
59
	public final static int MESSAGE_MERGEPROMPT = 9;
60
	public final static int MESSAGE_CONTACTOVERWRITTEN = 10;
61
	public final static int MESSAGE_CONTACTCREATED = 11;
62
	public final static int MESSAGE_CONTACTMERGED = 12;
63
	public final static int MESSAGE_CONTACTSKIPPED = 13;
64
9 by edam
- added scroll view to all layouts
65
	public final static int ACTION_PROMPT = 0;
66
	public final static int ACTION_KEEP = 1;
67
	public final static int ACTION_MERGE_MERGE = 2;
68
	public final static int ACTION_OVERWRITE = 3;
69
1 by edam
Initial import
70
	private boolean _startedProgress;
71
	private int _maxProgress;
72
	private int _tmpProgress;
73
	private int _progress;
74
	protected String _dialogMessage;
75
	private Dialog _mergePromptDialog;
76
	private boolean _mergePromptAlwaysSelected;
77
78
	private int _countOverwrites;
79
	private int _countCreates;
80
	private int _countMerges;
81
	private int _countSkips;
82
3 by edam
- added "all done" message
83
	protected Importer _importer = null;
1 by edam
Initial import
84
85
	public Handler _handler;
86
87
	public class DoitHandler extends Handler
88
	{
89
		@Override
90
		public void handleMessage( Message msg ) {
91
			switch( msg.what )
92
			{
3 by edam
- added "all done" message
93
			case MESSAGE_FINISHED_ALLDONE:
94
				( (TextView)findViewById( R.id.doit_alldone ) ).
95
						setVisibility( View.VISIBLE );
96
				// fall through
97
			case MESSAGE_FINISHED:
1 by edam
Initial import
98
				( (LinearLayout)findViewById( R.id.doit_closedisplay ) ).
99
						setVisibility( View.VISIBLE );
100
				break;
3 by edam
- added "all done" message
101
			case MESSAGE_FINISHED_GOBACK:
1 by edam
Initial import
102
				( (Button)findViewById( R.id.back ) ).setEnabled( true );
103
				break;
3 by edam
- added "all done" message
104
			case MESSAGE_ERROR:
1 by edam
Initial import
105
				Doit.this._dialogMessage = (String)msg.obj;
106
				showDialog( DIALOG_ERROR );
107
				break;
3 by edam
- added "all done" message
108
			case MESSAGE_CONTINUEORABORT:
1 by edam
Initial import
109
				Doit.this._dialogMessage = (String)msg.obj;
110
				showDialog( DIALOG_CONTINUEORABORT );
111
				break;
3 by edam
- added "all done" message
112
			case MESSAGE_SETPROGRESSMESSAGE:
1 by edam
Initial import
113
				( (TextView)findViewById( R.id.doit_percentage ) ).
114
						setText( (String)msg.obj );
115
				break;
3 by edam
- added "all done" message
116
			case MESSAGE_SETMAXPROGRESS:
1 by edam
Initial import
117
				if( _maxProgress > 0 ) {
118
					if( _tmpProgress == _maxProgress )
119
						_tmpProgress = (Integer)msg.obj;
120
					if( _progress == _maxProgress )
121
						_progress = (Integer)msg.obj;
122
				}
123
				_maxProgress = (Integer)msg.obj;
124
				updateProgress();
125
				break;
3 by edam
- added "all done" message
126
			case MESSAGE_SETTMPPROGRESS:
1 by edam
Initial import
127
				_tmpProgress = (Integer)msg.obj;
128
				updateProgress();
129
				break;
3 by edam
- added "all done" message
130
			case MESSAGE_SETPROGRESS:
1 by edam
Initial import
131
				_startedProgress = true;
132
				_progress = (Integer)msg.obj;
133
				updateProgress();
134
				break;
3 by edam
- added "all done" message
135
			case MESSAGE_MERGEPROMPT:
1 by edam
Initial import
136
				_dialogMessage = (String)msg.obj;
137
				showDialog( DIALOG_MERGEPROMPT );
138
				break;
3 by edam
- added "all done" message
139
			case MESSAGE_CONTACTOVERWRITTEN:
1 by edam
Initial import
140
				_countOverwrites++;
141
				updateStats();
142
				break;
3 by edam
- added "all done" message
143
			case MESSAGE_CONTACTCREATED:
1 by edam
Initial import
144
				_countCreates++;
145
				updateStats();
146
				break;
3 by edam
- added "all done" message
147
			case MESSAGE_CONTACTMERGED:
1 by edam
Initial import
148
				_countMerges++;
149
				updateStats();
150
				break;
3 by edam
- added "all done" message
151
			case MESSAGE_CONTACTSKIPPED:
1 by edam
Initial import
152
				_countSkips++;
153
				updateStats();
154
				break;
155
			default:
156
				super.handleMessage( msg );
157
			}
158
		}
159
	}
160
161
	@Override
162
	protected void onCreate(Bundle savedInstanceState)
163
	{
164
		setContentView( R.layout.doit );
165
		super.onCreate( savedInstanceState );
166
167
		// hide page 2
168
		( findViewById( R.id.doit_page_2 ) ).setVisibility( View.GONE );
169
170
		// set up begin button
171
		Button begin = (Button)findViewById( R.id.doit_begin );
172
		begin.setOnClickListener( new View.OnClickListener() {
173
			public void onClick( View view ) {
174
				importContacts();
175
			}
176
		} );
177
178
		// set up close button
179
		Button close = (Button)findViewById( R.id.doit_close );
180
		close.setOnClickListener( new View.OnClickListener() {
181
			public void onClick( View view ) {
182
				setResult( RESULT_CANCELED );
183
				finish();
184
			}
185
		} );
186
187
		_startedProgress = false;
188
		_maxProgress = 0;
189
		_tmpProgress = 0;
190
		_progress = 0;
191
		_handler = new DoitHandler();
192
193
		_countOverwrites = 0;
194
		_countCreates = 0;
195
		_countMerges = 0;
196
		_countSkips = 0;
197
198
		updateProgress();
199
		updateStats();
200
	}
201
202
	@Override
203
	protected void onPause()
204
	{
205
		super.onPause();
206
2 by edam
- added toaster message about import abortion in onPause()
207
		// saving the state of an import sounds complicated! Lets just abort!
1 by edam
Initial import
208
		abortImport();
209
3 by edam
- added "all done" message
210
		// destroy some stuff
211
		_importer = null;
212
		_handler = null;
1 by edam
Initial import
213
	}
214
215
	@Override
216
	protected Dialog onCreateDialog(int id)
217
	{
218
		switch( id )
219
		{
220
		case DIALOG_ERROR:
221
			return new AlertDialog.Builder( this )
222
					.setIcon( R.drawable.alert_dialog_icon )
223
					.setTitle( R.string.error_title )
224
					.setMessage( "" )
225
					.setPositiveButton( R.string.error_ok,
226
							new DialogInterface.OnClickListener() {
227
						public void onClick(DialogInterface dialog,
228
								int whichButton) {
229
							Doit.this._importer.wake();
230
						}
231
					} )
232
					.setOnCancelListener( _dialogOnCancelListener )
233
					.create();
234
		case DIALOG_CONTINUEORABORT:
235
			return new AlertDialog.Builder( this )
236
					.setIcon( R.drawable.alert_dialog_icon )
237
					.setTitle( R.string.error_title )
238
					.setMessage( "" )
239
					.setPositiveButton( R.string.error_continue,
240
							new DialogInterface.OnClickListener() {
241
						public void onClick(DialogInterface dialog,
242
								int whichButton) {
243
							Doit.this._importer.wake(
244
									Importer.RESPONSE_POSITIVE );
245
						}
246
					} )
247
					.setNegativeButton( R.string.error_abort,
248
							new DialogInterface.OnClickListener() {
249
						public void onClick(DialogInterface dialog,
250
								int whichButton) {
251
							Doit.this._importer.wake(
252
									Importer.RESPONSE_NEGATIVE );
253
						}
254
					} )
255
					.setOnCancelListener( _dialogOnCancelListener )
256
					.create();
257
		case DIALOG_MERGEPROMPT:
258
			// custom layout in an AlertDialog
259
			LayoutInflater factory = LayoutInflater.from( this );
260
			final View dialogView = factory.inflate(
261
					R.layout.mergeprompt, null );
262
			( (CheckBox)dialogView.findViewById( R.id.mergeprompt_always ) ).
263
					setOnCheckedChangeListener(
264
							new CompoundButton.OnCheckedChangeListener() {
265
				public void onCheckedChanged( CompoundButton buttonView,
266
						boolean isChecked ) {
267
					Doit.this._mergePromptAlwaysSelected = isChecked;
268
				}
269
			} );
270
			( (Button)dialogView.findViewById( R.id.merge_keep ) ).
271
					setOnClickListener( _mergePromptButtonListener );
272
			( (Button)dialogView.findViewById( R.id.merge_overwrite ) ).
273
					setOnClickListener( _mergePromptButtonListener );
274
			( (Button)dialogView.findViewById( R.id.merge_merge ) ).
275
					setOnClickListener( _mergePromptButtonListener );
276
			_mergePromptAlwaysSelected = false;
277
			return new AlertDialog.Builder( this )
278
					.setIcon( R.drawable.alert_dialog_icon )
279
					.setTitle( R.string.mergeprompt_title )
280
					.setView( dialogView )
281
					.setOnCancelListener( _dialogOnCancelListener )
282
					.create();
283
		}
284
		return null;
285
	}
286
287
    private OnClickListener _mergePromptButtonListener = new OnClickListener() {
288
		public void onClick( View view ) {
289
			int responseExtra = _mergePromptAlwaysSelected?
290
					Importer.RESPONSEEXTRA_ALWAYS : Importer.RESPONSEEXTRA_NONE;
291
			Doit.this._mergePromptDialog.dismiss();
9 by edam
- added scroll view to all layouts
292
			Doit.this._mergePromptDialog = null;	// don't keep a reference!
293
			Doit.this._importer.wake( convertIdToAction( view.getId() ),
294
					responseExtra );
1 by edam
Initial import
295
		}
296
	};
297
9 by edam
- added scroll view to all layouts
298
	public static int convertIdToAction( int id ) {
299
		switch( id ) {
300
		case R.id.merge_keep:		return ACTION_KEEP;
301
		case R.id.merge_merge:		return ACTION_MERGE_MERGE;
302
		case R.id.merge_overwrite:	return ACTION_OVERWRITE;
303
		default: return ACTION_PROMPT;
304
		}
305
	}
306
307
	public static int convertActionToId( int action ) {
308
		switch( action ) {
309
		case ACTION_KEEP:		return R.id.merge_keep;
310
		case ACTION_MERGE_MERGE:return R.id.merge_merge;
311
		case ACTION_OVERWRITE:	return R.id.merge_overwrite;
312
		default: return R.id.merge_prompt;
313
		}
314
	}
315
1 by edam
Initial import
316
	private DialogInterface.OnCancelListener _dialogOnCancelListener =
317
			new DialogInterface.OnCancelListener() {
318
		public void onCancel( DialogInterface dialog ) {
319
			setResult( RESULT_CANCELED );
320
			finish();
321
		}
322
	};
323
324
	@Override
325
	protected void onActivityResult( int requestCode, int resultCode,
326
			Intent data )
327
	{
2 by edam
- added toaster message about import abortion in onPause()
328
		// if we're cancelling, abort any import
1 by edam
Initial import
329
		if( resultCode == RESULT_CANCELED )
330
			abortImport();
331
	}
332
333
	@Override
334
	protected void onPrepareDialog(int id, Dialog dialog)
335
	{
336
		switch( id )
337
		{
338
		case DIALOG_ERROR:	// fall through
339
		case DIALOG_CONTINUEORABORT:
340
			// set dialog message
341
			( (AlertDialog)dialog ).setMessage( _dialogMessage );
342
			break;
343
		case DIALOG_MERGEPROMPT:
344
			// set contact's name
345
			( (TextView)dialog.findViewById( R.id.mergeprompt_name ) ).setText(
346
					_dialogMessage );
347
			// and set up reference to dialog
348
			_mergePromptDialog = dialog;
349
			break;
350
		}
351
352
		super.onPrepareDialog( id, dialog );
353
	}
354
355
	private void importContacts()
356
	{
357
		// switch interfaces
358
		( findViewById( R.id.doit_page_1 ) ).setVisibility( View.GONE );
359
		( findViewById( R.id.doit_page_2 ) ).setVisibility( View.VISIBLE );
360
361
		// disable back button
362
		( (Button)findViewById( R.id.back ) ).setEnabled( false );
363
364
		// create importer
365
		_importer = new VCFImporter( this );
366
367
		// start the service's thread
368
		_importer.start();
369
	}
370
371
	private void updateProgress()
372
	{
373
		ProgressBar bar = (ProgressBar)findViewById( R.id.doit_progress );
374
		TextView outOf = (TextView)findViewById( R.id.doit_outof );
375
376
		if( _maxProgress > 0 )
377
		{
378
			bar.setMax( _maxProgress );
379
			bar.setSecondaryProgress( _tmpProgress );
380
381
			if( _startedProgress )
382
			{
383
				( (TextView)findViewById( R.id.doit_percentage ) ).setText(
384
						(int)Math.round( 100 * _progress / _maxProgress ) + "%" );
385
				outOf.setText( _progress + "/" + _maxProgress );
386
				bar.setProgress( _progress );
387
			}
388
		}
389
	}
390
391
	private void updateStats()
392
	{
393
		( (TextView)findViewById( R.id.doit_overwrites ) ).setText(
394
				"" + _countOverwrites );
395
		( (TextView)findViewById( R.id.doit_creates ) ).setText(
396
				"" + _countCreates );
397
		( (TextView)findViewById( R.id.doit_merges ) ).setText(
398
				"" + _countMerges );
399
		( (TextView)findViewById( R.id.doit_skips ) ).setText(
400
				"" + _countSkips );
401
	}
402
403
	private void abortImport()
404
	{
405
		if( _importer != null )
406
		{
3 by edam
- added "all done" message
407
			// try and flag worker thread - did we need to?
408
			if( _importer.setAbort() )
409
			{
410
				// wait for worker thread to end
411
				while( true ) {
412
					try {
413
						_importer.join();
414
						break;
415
					}
416
					catch( InterruptedException e ) {}
1 by edam
Initial import
417
				}
3 by edam
- added "all done" message
418
419
				// notify the user
420
		        Toast.makeText( this, R.string.doit_importaborted,
421
		        		Toast.LENGTH_LONG ).show();
1 by edam
Initial import
422
			}
423
		}
424
	}
425
}