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