/android/import-contacts

To get this branch, use:
bzr branch http://bzr.ed.am/android/import-contacts
62 by edam
added preliminary (buggy) ContactsContract backend
1
/*
2
 * ContactsBackend.java
3
 *
95 by Tim Marston
added suopport for birthdays
4
 * Copyright (C) 2012 to 2013 Tim Marston <tim@ed.am>
62 by edam
added preliminary (buggy) ContactsContract backend
5
 *
6
 * This file is part of the Import Contacts program (hereafter referred
93 by Tim Marston
minor style tweaks
7
 * to as "this program").  For more information, see
62 by edam
added preliminary (buggy) ContactsContract backend
8
 * http://ed.am/dev/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
24
package am.ed.importcontacts;
25
26
import java.util.HashMap;
27
import java.util.HashSet;
28
29
import am.ed.importcontacts.ContactsCache.CacheIdentifier;
30
import am.ed.importcontacts.Importer.ContactData;
31
import android.annotation.TargetApi;
32
import android.app.Activity;
33
import android.content.ContentUris;
34
import android.content.ContentValues;
35
import android.database.Cursor;
36
import android.net.Uri;
37
import android.provider.ContactsContract;
38
import android.provider.ContactsContract.CommonDataKinds;
39
40
@TargetApi(5)
41
public class ContactsContractBackend implements Backend
42
{
43
	private Activity _activity = null;
44
	private HashMap< Long, Long > _aggregate_to_raw_ids = null;
45
46
	ContactsContractBackend( Activity activity )
47
	{
48
		_activity = activity;
49
		_aggregate_to_raw_ids = new HashMap< Long, Long >();
50
	}
51
52
	@Override
53
	public void populateCache( ContactsCache cache )
54
	{
55
		Cursor cur;
56
57
		// build a set of aggregate contact ids that haven't been added to the
58
		// cache yet
59
		HashSet< Long > unadded_ids = new HashSet< Long >();
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
60
		cur = _activity.getContentResolver().query(
61
			ContactsContract.Contacts.CONTENT_URI,
62 by edam
added preliminary (buggy) ContactsContract backend
62
			new String[] {
63
				ContactsContract.Contacts._ID,
64
			}, null, null, null );
65
		while( cur.moveToNext() ) {
66
			Long id = cur.getLong(
67
				cur.getColumnIndex( ContactsContract.Contacts._ID ) );
68
			unadded_ids.add( id );
69
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
70
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
71
72
		// build a mapping of the ids of raw contacts to the ids of their
73
		// aggregate contacts
74
		HashMap< Long, Long > raw_to_aggregate_ids =
75
			new HashMap< Long, Long >();
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
76
		cur = _activity.getContentResolver().query(
77
			ContactsContract.RawContacts.CONTENT_URI,
62 by edam
added preliminary (buggy) ContactsContract backend
78
			new String[] {
79
				ContactsContract.RawContacts._ID,
80
				ContactsContract.RawContacts.CONTACT_ID,
63 by edam
fixed selection of raw contacts in ContactsContract backend
81
			}, ContactsContract.RawContacts.DELETED + " = 0", null, null );
62 by edam
added preliminary (buggy) ContactsContract backend
82
		while( cur.moveToNext() ) {
83
			Long raw_id = cur.getLong(
84
				cur.getColumnIndex( ContactsContract.RawContacts._ID ) );
85
			Long id = cur.getLong(
86
				cur.getColumnIndex( ContactsContract.RawContacts.CONTACT_ID ) );
87
			raw_to_aggregate_ids.put( raw_id, id );
88
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
89
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
90
91
		// get structured names, primary ones first
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
92
		cur = _activity.getContentResolver().query(
93
			ContactsContract.Data.CONTENT_URI,
62 by edam
added preliminary (buggy) ContactsContract backend
94
			new String[] {
95
				ContactsContract.Data.RAW_CONTACT_ID,
96
				CommonDataKinds.StructuredName.DISPLAY_NAME,
97
			},
98
			ContactsContract.Data.MIMETYPE + " = '" +
99
				CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'",
100
			null, ContactsContract.Data.IS_PRIMARY + " DESC" );
101
		while( cur.moveToNext() ) {
102
			Long raw_id = cur.getLong( cur.getColumnIndex(
103
				ContactsContract.Data.RAW_CONTACT_ID ) );
104
			Long id = raw_to_aggregate_ids.get( raw_id );
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
105
			if( id != null )
62 by edam
added preliminary (buggy) ContactsContract backend
106
			{
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
107
				String name = cur.getString( cur.getColumnIndex(
108
					CommonDataKinds.StructuredName.DISPLAY_NAME ) );
109
62 by edam
added preliminary (buggy) ContactsContract backend
110
				// if this is a name for a contact for whom we have not added a
111
				// lookup, add a lookup for the contact id by name
112
				if( unadded_ids.contains( id ) ) {
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
113
					CacheIdentifier cache_identifier = CacheIdentifier.factory(
114
						CacheIdentifier.Type.NAME, name );
115
					if( cache_identifier != null ) {
116
						cache.addLookup( cache_identifier, id );
117
						unadded_ids.remove( id );
118
					}
62 by edam
added preliminary (buggy) ContactsContract backend
119
				}
120
			}
121
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
122
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
123
124
		// get contact organisations, primary ones first
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
125
		cur = _activity.getContentResolver().query(
126
			ContactsContract.Data.CONTENT_URI,
62 by edam
added preliminary (buggy) ContactsContract backend
127
			new String[] {
128
				ContactsContract.Data.RAW_CONTACT_ID,
129
				CommonDataKinds.Organization.COMPANY,
130
			},
131
			ContactsContract.Data.MIMETYPE + " = '" +
132
				CommonDataKinds.Organization.CONTENT_ITEM_TYPE + "'",
133
			null, ContactsContract.Data.IS_PRIMARY + " DESC" );
134
		while( cur.moveToNext() ) {
135
			Long raw_id = cur.getLong( cur.getColumnIndex(
136
				ContactsContract.Data.RAW_CONTACT_ID ) );
137
			Long id = raw_to_aggregate_ids.get( raw_id );
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
138
			if( id != null )
62 by edam
added preliminary (buggy) ContactsContract backend
139
			{
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
140
				String organisation = cur.getString( cur.getColumnIndex(
141
					CommonDataKinds.Organization.COMPANY ) );
142
62 by edam
added preliminary (buggy) ContactsContract backend
143
				// if this is an organisation name for a contact for whom we
144
				// have not added a lookup, add a lookup for the contact id
145
				// by organisation
146
				if( unadded_ids.contains( id ) ) {
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
147
					CacheIdentifier cache_identifier = CacheIdentifier.factory(
148
						CacheIdentifier.Type.ORGANISATION, organisation );
149
					if( cache_identifier != null ) {
150
						cache.addLookup( cache_identifier, id );
151
						unadded_ids.remove( id );
152
					}
62 by edam
added preliminary (buggy) ContactsContract backend
153
				}
154
155
				// add associated data
156
				cache.addAssociatedOrganisation( id, organisation );
157
			}
158
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
159
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
160
161
		// get all phone numbers, primary ones first
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
162
		cur = _activity.getContentResolver().query(
163
			ContactsContract.Data.CONTENT_URI,
62 by edam
added preliminary (buggy) ContactsContract backend
164
			new String[] {
165
				ContactsContract.Data.RAW_CONTACT_ID,
166
				CommonDataKinds.Phone.NUMBER,
167
			},
168
			ContactsContract.Data.MIMETYPE + " = '" +
169
				CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'",
170
			null, ContactsContract.Data.IS_PRIMARY + " DESC" );
171
		while( cur.moveToNext() ) {
172
			Long raw_id = cur.getLong( cur.getColumnIndex(
173
				ContactsContract.Data.RAW_CONTACT_ID ) );
174
			Long id = raw_to_aggregate_ids.get( raw_id );
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
175
			if( id != null )
62 by edam
added preliminary (buggy) ContactsContract backend
176
			{
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
177
				String number = cur.getString( cur.getColumnIndex(
178
					CommonDataKinds.Phone.NUMBER ) );
179
62 by edam
added preliminary (buggy) ContactsContract backend
180
				// if this is a number for a contact for whom we have not
181
				// added a lookup, add a lookup for the contact id by phone
182
				// number
183
				if( unadded_ids.contains( id ) ) {
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
184
					CacheIdentifier cache_identifier = CacheIdentifier.factory(
185
						CacheIdentifier.Type.PRIMARY_NUMBER, number );
186
					if( cache_identifier != null ) {
187
						cache.addLookup( cache_identifier, id );
188
						unadded_ids.remove( id );
189
					}
62 by edam
added preliminary (buggy) ContactsContract backend
190
				}
191
192
				// add associated data
193
				cache.addAssociatedNumber( id, number );
194
			}
195
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
196
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
197
198
		// get all email addresses, primary ones first
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
199
		cur = _activity.getContentResolver().query(
200
			ContactsContract.Data.CONTENT_URI,
62 by edam
added preliminary (buggy) ContactsContract backend
201
			new String[] {
202
				ContactsContract.Data.RAW_CONTACT_ID,
203
				CommonDataKinds.Email.DATA,
204
			},
205
			ContactsContract.Data.MIMETYPE + " = '" +
206
				CommonDataKinds.Email.CONTENT_ITEM_TYPE + "'",
207
			null, ContactsContract.Data.IS_PRIMARY + " DESC" );
208
		while( cur.moveToNext() ) {
209
			Long raw_id = cur.getLong( cur.getColumnIndex(
210
				ContactsContract.Data.RAW_CONTACT_ID ) );
211
			Long id = raw_to_aggregate_ids.get( raw_id );
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
212
			if( id != null )
62 by edam
added preliminary (buggy) ContactsContract backend
213
			{
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
214
				String email = cur.getString( cur.getColumnIndex(
215
					CommonDataKinds.Email.DATA ) );
216
62 by edam
added preliminary (buggy) ContactsContract backend
217
				// if this is an email address for a contact for whom we have
218
				// not added a lookup, add a lookup for the contact id by email
219
				// address
220
				if( unadded_ids.contains( id ) ) {
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
221
					CacheIdentifier cache_identifier = CacheIdentifier.factory(
222
						CacheIdentifier.Type.PRIMARY_EMAIL, email );
223
					if( cache_identifier != null ) {
224
						cache.addLookup( cache_identifier, id );
225
						unadded_ids.remove( id );
226
					}
62 by edam
added preliminary (buggy) ContactsContract backend
227
				}
228
229
				// add associated data
230
				cache.addAssociatedEmail( id, email );
231
			}
232
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
233
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
234
235
		// get all postal addresses, primary ones first
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
236
		cur = _activity.getContentResolver().query(
237
			ContactsContract.Data.CONTENT_URI,
62 by edam
added preliminary (buggy) ContactsContract backend
238
			new String[] {
239
				ContactsContract.Data.RAW_CONTACT_ID,
240
				CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS,
241
			},
242
			ContactsContract.Data.MIMETYPE + " = '" +
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
243
				CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE + "'",
62 by edam
added preliminary (buggy) ContactsContract backend
244
			null, ContactsContract.Data.IS_PRIMARY + " DESC" );
245
		while( cur.moveToNext() ) {
246
			Long raw_id = cur.getLong( cur.getColumnIndex(
247
				ContactsContract.Data.RAW_CONTACT_ID ) );
248
			Long id = raw_to_aggregate_ids.get( raw_id );
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
249
			if( id != null )
62 by edam
added preliminary (buggy) ContactsContract backend
250
			{
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
251
				String address = cur.getString( cur.getColumnIndex(
252
					CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS ) );
253
62 by edam
added preliminary (buggy) ContactsContract backend
254
				// add associated data
255
				cache.addAssociatedAddress( id, address );
256
			}
257
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
258
		cur.close();
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
259
260
		// get all notes
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
261
		cur = _activity.getContentResolver().query(
262
			ContactsContract.Data.CONTENT_URI,
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
263
			new String[] {
264
				ContactsContract.Data.RAW_CONTACT_ID,
265
				CommonDataKinds.Note.NOTE,
266
			},
267
			ContactsContract.Data.MIMETYPE + " = '" +
268
				CommonDataKinds.Note.CONTENT_ITEM_TYPE + "'",
269
			null, null );
270
		while( cur.moveToNext() ) {
271
			Long raw_id = cur.getLong( cur.getColumnIndex(
272
				ContactsContract.Data.RAW_CONTACT_ID ) );
273
			Long id = raw_to_aggregate_ids.get( raw_id );
274
			if( id != null )
275
			{
276
				String note = cur.getString( cur.getColumnIndex(
277
					CommonDataKinds.Note.NOTE ) );
278
279
				// add associated data
280
				cache.addAssociatedNote( id, note );
281
			}
282
		}
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
283
		cur.close();
95 by Tim Marston
added suopport for birthdays
284
285
		// get all birthdays
286
		cur = _activity.getContentResolver().query(
287
			ContactsContract.Data.CONTENT_URI,
288
			new String[] {
289
				ContactsContract.Data.RAW_CONTACT_ID,
290
				CommonDataKinds.Event.START_DATE,
291
			},
292
			ContactsContract.Data.MIMETYPE + " = '" +
293
				CommonDataKinds.Event.CONTENT_ITEM_TYPE + "' AND " +
294
				CommonDataKinds.Event.TYPE + " = '" +
295
				CommonDataKinds.Event.TYPE_BIRTHDAY + "'",
296
			null, null );
297
		while( cur.moveToNext() ) {
298
			Long raw_id = cur.getLong( cur.getColumnIndex(
299
				ContactsContract.Data.RAW_CONTACT_ID ) );
300
			Long id = raw_to_aggregate_ids.get( raw_id );
301
			if( id != null )
302
			{
303
				String birthday = cur.getString( cur.getColumnIndex(
304
					CommonDataKinds.Event.START_DATE ) );
305
306
				// add associated data
307
				cache.addAssociatedBirthday( id, birthday );
308
			}
309
		}
310
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
311
	}
312
313
	@Override
314
	public void deleteContact( Long id )
315
	{
316
		Uri contact_uri = ContentUris.withAppendedId(
317
			ContactsContract.Contacts.CONTENT_URI, id );
318
		_activity.getContentResolver().delete( contact_uri, null, null );
319
	}
320
321
	@Override
322
	public Long addContact( String name ) throws ContactCreationException
323
	{
324
		// create raw contact
325
		ContentValues values = new ContentValues();
326
		Uri contact_uri = _activity.getContentResolver().insert(
327
			ContactsContract.RawContacts.CONTENT_URI, values);
328
		Long raw_id = ContentUris.parseId( contact_uri );
329
		if( raw_id == 0 ) throw new ContactCreationException();
330
331
		// add name data for this raw contact
332
		if( name != null ) {
333
			values.put( ContactsContract.Data.RAW_CONTACT_ID, raw_id );
334
			values.put( ContactsContract.Data.MIMETYPE,
335
				CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE );
336
			values.put( CommonDataKinds.StructuredName.DISPLAY_NAME, name );
337
			_activity.getContentResolver().insert(
338
				ContactsContract.Data.CONTENT_URI, values );
339
		}
340
341
		// find corresponding aggregate contact
342
		contact_uri = Uri.withAppendedPath(
343
			ContentUris.withAppendedId(
344
				ContactsContract.RawContacts.CONTENT_URI, raw_id ),
345
			ContactsContract.RawContacts.Entity.CONTENT_DIRECTORY );
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
346
		Cursor cur = _activity.getContentResolver().query( contact_uri,
62 by edam
added preliminary (buggy) ContactsContract backend
347
			new String[] {
348
				ContactsContract.RawContacts.CONTACT_ID,
349
			}, null, null, null );
350
		Long id = null;
351
		if( cur.moveToNext() )
352
			id = cur.getLong(
353
				cur.getColumnIndex( ContactsContract.RawContacts.CONTACT_ID ) );
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
354
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
355
		if( id == null || id == 0 )
356
		{
357
			// we didn't find an aggregate contact id, so try to clean up (by
358
			// deleting the raw contact we just created) before bailing
359
			contact_uri = ContentUris.withAppendedId(
360
				ContactsContract.RawContacts.CONTENT_URI, id );
361
			_activity.getContentResolver().delete( contact_uri, null, null );
362
363
			throw new ContactCreationException();
364
		}
365
366
		return id;
367
	}
368
369
	/**
370
	 * Obtain the raw contact id for the phone-only raw contact that is
371
	 * associated with the aggregate contact id.  One will be created if
372
	 * necessary.
93 by Tim Marston
minor style tweaks
373
	 *
62 by edam
added preliminary (buggy) ContactsContract backend
374
	 * @param id the aggregate contact id
375
	 * @return the raw contact id
376
	 * @throws ContactCreationException
377
	 */
378
	Long obtainRawContact( Long id ) throws ContactCreationException
379
	{
380
		// attempt to lookup cached value
381
		Long raw_id = _aggregate_to_raw_ids.get( id );
382
		if( raw_id != null ) return raw_id;
383
384
		// find a corresponding raw contact that has no account name/type
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
385
		Cursor cur = _activity.getContentResolver().query(
62 by edam
added preliminary (buggy) ContactsContract backend
386
			ContactsContract.RawContacts.CONTENT_URI,
387
			new String[] {
388
				ContactsContract.RawContacts._ID,
63 by edam
fixed selection of raw contacts in ContactsContract backend
389
				ContactsContract.RawContacts.ACCOUNT_NAME,
62 by edam
added preliminary (buggy) ContactsContract backend
390
			},
63 by edam
fixed selection of raw contacts in ContactsContract backend
391
			ContactsContract.RawContacts.DELETED + " = 0 AND " +
392
				ContactsContract.RawContacts.CONTACT_ID + " = ? AND " +
62 by edam
added preliminary (buggy) ContactsContract backend
393
				"IFNULL( " + ContactsContract.RawContacts.ACCOUNT_NAME +
394
					", '' ) = '' AND " +
395
				"IFNULL( " + ContactsContract.RawContacts.ACCOUNT_TYPE +
396
					", '' ) = ''",
63 by edam
fixed selection of raw contacts in ContactsContract backend
397
			new String[] {
398
				String.valueOf( id ),
399
			}, null );
62 by edam
added preliminary (buggy) ContactsContract backend
400
		if( cur.moveToNext() )
401
			raw_id = cur.getLong(
402
				cur.getColumnIndex( ContactsContract.RawContacts._ID ) );
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
403
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
404
405
		// if one wasn't found, we'll need to create one
406
		if( raw_id == null ) {
407
			ContentValues values = new ContentValues();
408
			Uri contact_uri = _activity.getContentResolver().insert(
409
				ContactsContract.RawContacts.CONTENT_URI, values);
410
			raw_id = ContentUris.parseId( contact_uri );
411
			if( raw_id == 0 ) throw new ContactCreationException();
412
		}
413
414
		// save value in our cache
415
		_aggregate_to_raw_ids.put( id, raw_id );
416
		return raw_id;
417
	}
418
419
	private int convertTypeToBackendType( Class< ? > cls, int type )
420
		throws ContactCreationException
421
	{
422
		if( cls == CommonDataKinds.Phone.class )
423
		{
424
			switch( type )
425
			{
426
			case ContactData.TYPE_HOME:
427
				return CommonDataKinds.Phone.TYPE_HOME;
428
			case ContactData.TYPE_WORK:
429
				return CommonDataKinds.Phone.TYPE_WORK;
430
			case ContactData.TYPE_MOBILE:
431
				return CommonDataKinds.Phone.TYPE_MOBILE;
432
			case ContactData.TYPE_FAX_HOME:
433
				return CommonDataKinds.Phone.TYPE_FAX_HOME;
434
			case ContactData.TYPE_FAX_WORK:
435
				return CommonDataKinds.Phone.TYPE_FAX_WORK;
436
			case ContactData.TYPE_PAGER:
437
				return CommonDataKinds.Phone.TYPE_PAGER;
438
			}
439
		}
440
		else if( cls == CommonDataKinds.Email.class )
441
		{
442
			switch( type )
443
			{
444
			case ContactData.TYPE_HOME:
445
				return CommonDataKinds.Email.TYPE_HOME;
446
			case ContactData.TYPE_WORK:
447
				return CommonDataKinds.Email.TYPE_WORK;
448
			}
449
		}
450
		else if( cls == CommonDataKinds.StructuredPostal.class )
451
		{
452
			switch( type )
453
			{
454
			case ContactData.TYPE_HOME:
455
				return CommonDataKinds.StructuredPostal.TYPE_HOME;
456
			case ContactData.TYPE_WORK:
457
				return CommonDataKinds.StructuredPostal.TYPE_WORK;
458
			}
459
		}
460
461
		// still here?
462
		throw new ContactCreationException();
463
	}
464
465
	@Override
466
	public void addContactPhone( Long id, String number,
467
		ContactData.PreferredDetail data ) throws ContactCreationException
468
	{
469
		ContentValues values = new ContentValues();
470
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
471
			obtainRawContact( id ) );
472
		values.put( ContactsContract.Data.MIMETYPE,
473
			CommonDataKinds.Phone.CONTENT_ITEM_TYPE );
474
		values.put( CommonDataKinds.Phone.TYPE,
475
			convertTypeToBackendType( CommonDataKinds.Phone.class,
476
				data.getType() ) );
477
		values.put( CommonDataKinds.Phone.NUMBER, number );
478
		if( data.isPreferred() )
479
			values.put( CommonDataKinds.Phone.IS_PRIMARY, 1 );
480
481
		_activity.getContentResolver().insert(
482
			ContactsContract.Data.CONTENT_URI, values );
483
	}
484
485
	@Override
486
	public void addContactEmail( Long id, String email,
487
		ContactData.PreferredDetail data ) throws ContactCreationException
488
	{
489
		ContentValues values = new ContentValues();
490
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
491
			obtainRawContact( id ) );
492
		values.put( ContactsContract.Data.MIMETYPE,
493
			CommonDataKinds.Email.CONTENT_ITEM_TYPE );
494
		values.put( CommonDataKinds.Email.TYPE,
495
			convertTypeToBackendType( CommonDataKinds.Email.class,
496
				data.getType() ) );
497
		values.put( CommonDataKinds.Email.DATA, email );
498
		if( data.isPreferred() )
499
			values.put( CommonDataKinds.Email.IS_PRIMARY, 1 );
500
501
		_activity.getContentResolver().insert(
502
			ContactsContract.Data.CONTENT_URI, values );
503
	}
504
505
	@Override
506
	public void addContactAddresses( Long id, String address,
507
		ContactData.TypeDetail data ) throws ContactCreationException
508
	{
509
		ContentValues values = new ContentValues();
510
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
511
			obtainRawContact( id ) );
512
		values.put( ContactsContract.Data.MIMETYPE,
513
			CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE );
514
		values.put( CommonDataKinds.StructuredPostal.TYPE,
515
			convertTypeToBackendType( CommonDataKinds.StructuredPostal.class,
516
				data.getType() ) );
517
		values.put(
518
			CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, address );
519
520
		_activity.getContentResolver().insert(
521
			ContactsContract.Data.CONTENT_URI, values );
522
	}
523
524
	@Override
525
	public void addContactOrganisation( Long id, String organisation,
526
		ContactData.ExtraDetail data ) throws ContactCreationException
527
	{
528
		ContentValues values = new ContentValues();
529
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
530
			obtainRawContact( id ) );
531
		values.put( ContactsContract.Data.MIMETYPE,
532
			CommonDataKinds.Organization.CONTENT_ITEM_TYPE );
533
		values.put( CommonDataKinds.Organization.TYPE,
534
			CommonDataKinds.Organization.TYPE_WORK );
535
		values.put(
536
			CommonDataKinds.Organization.COMPANY, organisation );
537
		if( data.getExtra() != null )
538
			values.put( CommonDataKinds.Organization.TITLE, data.getExtra() );
539
540
		_activity.getContentResolver().insert(
541
			ContactsContract.Data.CONTENT_URI, values );
542
	}
65 by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters
543
544
	@Override
545
	public void addContactNote( Long id, String note )
546
		throws ContactCreationException
547
	{
548
		ContentValues values = new ContentValues();
549
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
550
			obtainRawContact( id ) );
551
		values.put( ContactsContract.Data.MIMETYPE,
552
			CommonDataKinds.Note.CONTENT_ITEM_TYPE );
553
		values.put(
554
			CommonDataKinds.Note.NOTE, note );
555
556
		_activity.getContentResolver().insert(
557
			ContactsContract.Data.CONTENT_URI, values );
558
	}
559
95 by Tim Marston
added suopport for birthdays
560
	@Override
561
	public void addContactBirthday( Long id, String birthday )
562
		throws ContactCreationException
563
	{
564
		ContentValues values = new ContentValues();
565
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
566
			obtainRawContact( id ) );
567
		values.put( ContactsContract.Data.MIMETYPE,
568
			CommonDataKinds.Event.CONTENT_ITEM_TYPE );
569
		values.put(
570
			CommonDataKinds.Event.TYPE, CommonDataKinds.Event.TYPE_BIRTHDAY );
571
		values.put(
572
			CommonDataKinds.Event.START_DATE, birthday );
573
		_activity.getContentResolver().insert(
574
			ContactsContract.Data.CONTENT_URI, values );
575
	}
62 by edam
added preliminary (buggy) ContactsContract backend
576
}