/android/import-contacts

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