/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
 *
4
 * Copyright (C) 2012 Tim Marston <tim@ed.am>
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();
62 by edam
added preliminary (buggy) ContactsContract backend
284
	}
285
286
	@Override
287
	public void deleteContact( Long id )
288
	{
289
		Uri contact_uri = ContentUris.withAppendedId(
290
			ContactsContract.Contacts.CONTENT_URI, id );
291
		_activity.getContentResolver().delete( contact_uri, null, null );
292
	}
293
294
	@Override
295
	public Long addContact( String name ) throws ContactCreationException
296
	{
297
		// create raw contact
298
		ContentValues values = new ContentValues();
299
		Uri contact_uri = _activity.getContentResolver().insert(
300
			ContactsContract.RawContacts.CONTENT_URI, values);
301
		Long raw_id = ContentUris.parseId( contact_uri );
302
		if( raw_id == 0 ) throw new ContactCreationException();
303
304
		// add name data for this raw contact
305
		if( name != null ) {
306
			values.put( ContactsContract.Data.RAW_CONTACT_ID, raw_id );
307
			values.put( ContactsContract.Data.MIMETYPE,
308
				CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE );
309
			values.put( CommonDataKinds.StructuredName.DISPLAY_NAME, name );
310
			_activity.getContentResolver().insert(
311
				ContactsContract.Data.CONTENT_URI, values );
312
		}
313
314
		// find corresponding aggregate contact
315
		contact_uri = Uri.withAppendedPath(
316
			ContentUris.withAppendedId(
317
				ContactsContract.RawContacts.CONTENT_URI, raw_id ),
318
			ContactsContract.RawContacts.Entity.CONTENT_DIRECTORY );
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
319
		Cursor cur = _activity.getContentResolver().query( contact_uri,
62 by edam
added preliminary (buggy) ContactsContract backend
320
			new String[] {
321
				ContactsContract.RawContacts.CONTACT_ID,
322
			}, null, null, null );
323
		Long id = null;
324
		if( cur.moveToNext() )
325
			id = cur.getLong(
326
				cur.getColumnIndex( ContactsContract.RawContacts.CONTACT_ID ) );
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
327
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
328
		if( id == null || id == 0 )
329
		{
330
			// we didn't find an aggregate contact id, so try to clean up (by
331
			// deleting the raw contact we just created) before bailing
332
			contact_uri = ContentUris.withAppendedId(
333
				ContactsContract.RawContacts.CONTENT_URI, id );
334
			_activity.getContentResolver().delete( contact_uri, null, null );
335
336
			throw new ContactCreationException();
337
		}
338
339
		return id;
340
	}
341
342
	/**
343
	 * Obtain the raw contact id for the phone-only raw contact that is
344
	 * associated with the aggregate contact id.  One will be created if
345
	 * necessary.
93 by Tim Marston
minor style tweaks
346
	 *
62 by edam
added preliminary (buggy) ContactsContract backend
347
	 * @param id the aggregate contact id
348
	 * @return the raw contact id
349
	 * @throws ContactCreationException
350
	 */
351
	Long obtainRawContact( Long id ) throws ContactCreationException
352
	{
353
		// attempt to lookup cached value
354
		Long raw_id = _aggregate_to_raw_ids.get( id );
355
		if( raw_id != null ) return raw_id;
356
357
		// find a corresponding raw contact that has no account name/type
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
358
		Cursor cur = _activity.getContentResolver().query(
62 by edam
added preliminary (buggy) ContactsContract backend
359
			ContactsContract.RawContacts.CONTENT_URI,
360
			new String[] {
361
				ContactsContract.RawContacts._ID,
63 by edam
fixed selection of raw contacts in ContactsContract backend
362
				ContactsContract.RawContacts.ACCOUNT_NAME,
62 by edam
added preliminary (buggy) ContactsContract backend
363
			},
63 by edam
fixed selection of raw contacts in ContactsContract backend
364
			ContactsContract.RawContacts.DELETED + " = 0 AND " +
365
				ContactsContract.RawContacts.CONTACT_ID + " = ? AND " +
62 by edam
added preliminary (buggy) ContactsContract backend
366
				"IFNULL( " + ContactsContract.RawContacts.ACCOUNT_NAME +
367
					", '' ) = '' AND " +
368
				"IFNULL( " + ContactsContract.RawContacts.ACCOUNT_TYPE +
369
					", '' ) = ''",
63 by edam
fixed selection of raw contacts in ContactsContract backend
370
			new String[] {
371
				String.valueOf( id ),
372
			}, null );
62 by edam
added preliminary (buggy) ContactsContract backend
373
		if( cur.moveToNext() )
374
			raw_id = cur.getLong(
375
				cur.getColumnIndex( ContactsContract.RawContacts._ID ) );
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
376
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
377
378
		// if one wasn't found, we'll need to create one
379
		if( raw_id == null ) {
380
			ContentValues values = new ContentValues();
381
			Uri contact_uri = _activity.getContentResolver().insert(
382
				ContactsContract.RawContacts.CONTENT_URI, values);
383
			raw_id = ContentUris.parseId( contact_uri );
384
			if( raw_id == 0 ) throw new ContactCreationException();
385
		}
386
387
		// save value in our cache
388
		_aggregate_to_raw_ids.put( id, raw_id );
389
		return raw_id;
390
	}
391
392
	private int convertTypeToBackendType( Class< ? > cls, int type )
393
		throws ContactCreationException
394
	{
395
		if( cls == CommonDataKinds.Phone.class )
396
		{
397
			switch( type )
398
			{
399
			case ContactData.TYPE_HOME:
400
				return CommonDataKinds.Phone.TYPE_HOME;
401
			case ContactData.TYPE_WORK:
402
				return CommonDataKinds.Phone.TYPE_WORK;
403
			case ContactData.TYPE_MOBILE:
404
				return CommonDataKinds.Phone.TYPE_MOBILE;
405
			case ContactData.TYPE_FAX_HOME:
406
				return CommonDataKinds.Phone.TYPE_FAX_HOME;
407
			case ContactData.TYPE_FAX_WORK:
408
				return CommonDataKinds.Phone.TYPE_FAX_WORK;
409
			case ContactData.TYPE_PAGER:
410
				return CommonDataKinds.Phone.TYPE_PAGER;
411
			}
412
		}
413
		else if( cls == CommonDataKinds.Email.class )
414
		{
415
			switch( type )
416
			{
417
			case ContactData.TYPE_HOME:
418
				return CommonDataKinds.Email.TYPE_HOME;
419
			case ContactData.TYPE_WORK:
420
				return CommonDataKinds.Email.TYPE_WORK;
421
			}
422
		}
423
		else if( cls == CommonDataKinds.StructuredPostal.class )
424
		{
425
			switch( type )
426
			{
427
			case ContactData.TYPE_HOME:
428
				return CommonDataKinds.StructuredPostal.TYPE_HOME;
429
			case ContactData.TYPE_WORK:
430
				return CommonDataKinds.StructuredPostal.TYPE_WORK;
431
			}
432
		}
433
434
		// still here?
435
		throw new ContactCreationException();
436
	}
437
438
	@Override
439
	public void addContactPhone( Long id, String number,
440
		ContactData.PreferredDetail data ) throws ContactCreationException
441
	{
442
		ContentValues values = new ContentValues();
443
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
444
			obtainRawContact( id ) );
445
		values.put( ContactsContract.Data.MIMETYPE,
446
			CommonDataKinds.Phone.CONTENT_ITEM_TYPE );
447
		values.put( CommonDataKinds.Phone.TYPE,
448
			convertTypeToBackendType( CommonDataKinds.Phone.class,
449
				data.getType() ) );
450
		values.put( CommonDataKinds.Phone.NUMBER, number );
451
		if( data.isPreferred() )
452
			values.put( CommonDataKinds.Phone.IS_PRIMARY, 1 );
453
454
		_activity.getContentResolver().insert(
455
			ContactsContract.Data.CONTENT_URI, values );
456
	}
457
458
	@Override
459
	public void addContactEmail( Long id, String email,
460
		ContactData.PreferredDetail data ) throws ContactCreationException
461
	{
462
		ContentValues values = new ContentValues();
463
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
464
			obtainRawContact( id ) );
465
		values.put( ContactsContract.Data.MIMETYPE,
466
			CommonDataKinds.Email.CONTENT_ITEM_TYPE );
467
		values.put( CommonDataKinds.Email.TYPE,
468
			convertTypeToBackendType( CommonDataKinds.Email.class,
469
				data.getType() ) );
470
		values.put( CommonDataKinds.Email.DATA, email );
471
		if( data.isPreferred() )
472
			values.put( CommonDataKinds.Email.IS_PRIMARY, 1 );
473
474
		_activity.getContentResolver().insert(
475
			ContactsContract.Data.CONTENT_URI, values );
476
	}
477
478
	@Override
479
	public void addContactAddresses( Long id, String address,
480
		ContactData.TypeDetail data ) throws ContactCreationException
481
	{
482
		ContentValues values = new ContentValues();
483
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
484
			obtainRawContact( id ) );
485
		values.put( ContactsContract.Data.MIMETYPE,
486
			CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE );
487
		values.put( CommonDataKinds.StructuredPostal.TYPE,
488
			convertTypeToBackendType( CommonDataKinds.StructuredPostal.class,
489
				data.getType() ) );
490
		values.put(
491
			CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, address );
492
493
		_activity.getContentResolver().insert(
494
			ContactsContract.Data.CONTENT_URI, values );
495
	}
496
497
	@Override
498
	public void addContactOrganisation( Long id, String organisation,
499
		ContactData.ExtraDetail data ) throws ContactCreationException
500
	{
501
		ContentValues values = new ContentValues();
502
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
503
			obtainRawContact( id ) );
504
		values.put( ContactsContract.Data.MIMETYPE,
505
			CommonDataKinds.Organization.CONTENT_ITEM_TYPE );
506
		values.put( CommonDataKinds.Organization.TYPE,
507
			CommonDataKinds.Organization.TYPE_WORK );
508
		values.put(
509
			CommonDataKinds.Organization.COMPANY, organisation );
510
		if( data.getExtra() != null )
511
			values.put( CommonDataKinds.Organization.TITLE, data.getExtra() );
512
513
		_activity.getContentResolver().insert(
514
			ContactsContract.Data.CONTENT_URI, values );
515
	}
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
516
517
	@Override
518
	public void addContactNote( Long id, String note )
519
		throws ContactCreationException
520
	{
521
		ContentValues values = new ContentValues();
522
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
523
			obtainRawContact( id ) );
524
		values.put( ContactsContract.Data.MIMETYPE,
525
			CommonDataKinds.Note.CONTENT_ITEM_TYPE );
526
		values.put(
527
			CommonDataKinds.Note.NOTE, note );
528
529
		_activity.getContentResolver().insert(
530
			ContactsContract.Data.CONTENT_URI, values );
531
	}
532
62 by edam
added preliminary (buggy) ContactsContract backend
533
}