/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
7
 * to as "this program"). For more information, see
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.
346
	 * @param id the aggregate contact id
347
	 * @return the raw contact id
348
	 * @throws ContactCreationException
349
	 */
350
	Long obtainRawContact( Long id ) throws ContactCreationException
351
	{
352
		// attempt to lookup cached value
353
		Long raw_id = _aggregate_to_raw_ids.get( id );
354
		if( raw_id != null ) return raw_id;
355
356
		// find a corresponding raw contact that has no account name/type
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
357
		Cursor cur = _activity.getContentResolver().query(
62 by edam
added preliminary (buggy) ContactsContract backend
358
			ContactsContract.RawContacts.CONTENT_URI,
359
			new String[] {
360
				ContactsContract.RawContacts._ID,
63 by edam
fixed selection of raw contacts in ContactsContract backend
361
				ContactsContract.RawContacts.ACCOUNT_NAME,
62 by edam
added preliminary (buggy) ContactsContract backend
362
			},
63 by edam
fixed selection of raw contacts in ContactsContract backend
363
			ContactsContract.RawContacts.DELETED + " = 0 AND " +
364
				ContactsContract.RawContacts.CONTACT_ID + " = ? AND " +
62 by edam
added preliminary (buggy) ContactsContract backend
365
				"IFNULL( " + ContactsContract.RawContacts.ACCOUNT_NAME +
366
					", '' ) = '' AND " +
367
				"IFNULL( " + ContactsContract.RawContacts.ACCOUNT_TYPE +
368
					", '' ) = ''",
63 by edam
fixed selection of raw contacts in ContactsContract backend
369
			new String[] {
370
				String.valueOf( id ),
371
			}, null );
62 by edam
added preliminary (buggy) ContactsContract backend
372
		if( cur.moveToNext() )
373
			raw_id = cur.getLong(
374
				cur.getColumnIndex( ContactsContract.RawContacts._ID ) );
83 by edam
stop using managedQuery(), which isn't cleaning up my queries
375
		cur.close();
62 by edam
added preliminary (buggy) ContactsContract backend
376
377
		// if one wasn't found, we'll need to create one
378
		if( raw_id == null ) {
379
			ContentValues values = new ContentValues();
380
			Uri contact_uri = _activity.getContentResolver().insert(
381
				ContactsContract.RawContacts.CONTENT_URI, values);
382
			raw_id = ContentUris.parseId( contact_uri );
383
			if( raw_id == 0 ) throw new ContactCreationException();
384
		}
385
386
		// save value in our cache
387
		_aggregate_to_raw_ids.put( id, raw_id );
388
		return raw_id;
389
	}
390
391
	private int convertTypeToBackendType( Class< ? > cls, int type )
392
		throws ContactCreationException
393
	{
394
		if( cls == CommonDataKinds.Phone.class )
395
		{
396
			switch( type )
397
			{
398
			case ContactData.TYPE_HOME:
399
				return CommonDataKinds.Phone.TYPE_HOME;
400
			case ContactData.TYPE_WORK:
401
				return CommonDataKinds.Phone.TYPE_WORK;
402
			case ContactData.TYPE_MOBILE:
403
				return CommonDataKinds.Phone.TYPE_MOBILE;
404
			case ContactData.TYPE_FAX_HOME:
405
				return CommonDataKinds.Phone.TYPE_FAX_HOME;
406
			case ContactData.TYPE_FAX_WORK:
407
				return CommonDataKinds.Phone.TYPE_FAX_WORK;
408
			case ContactData.TYPE_PAGER:
409
				return CommonDataKinds.Phone.TYPE_PAGER;
410
			}
411
		}
412
		else if( cls == CommonDataKinds.Email.class )
413
		{
414
			switch( type )
415
			{
416
			case ContactData.TYPE_HOME:
417
				return CommonDataKinds.Email.TYPE_HOME;
418
			case ContactData.TYPE_WORK:
419
				return CommonDataKinds.Email.TYPE_WORK;
420
			}
421
		}
422
		else if( cls == CommonDataKinds.StructuredPostal.class )
423
		{
424
			switch( type )
425
			{
426
			case ContactData.TYPE_HOME:
427
				return CommonDataKinds.StructuredPostal.TYPE_HOME;
428
			case ContactData.TYPE_WORK:
429
				return CommonDataKinds.StructuredPostal.TYPE_WORK;
430
			}
431
		}
432
433
		// still here?
434
		throw new ContactCreationException();
435
	}
436
437
	@Override
438
	public void addContactPhone( Long id, String number,
439
		ContactData.PreferredDetail data ) throws ContactCreationException
440
	{
441
		ContentValues values = new ContentValues();
442
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
443
			obtainRawContact( id ) );
444
		values.put( ContactsContract.Data.MIMETYPE,
445
			CommonDataKinds.Phone.CONTENT_ITEM_TYPE );
446
		values.put( CommonDataKinds.Phone.TYPE,
447
			convertTypeToBackendType( CommonDataKinds.Phone.class,
448
				data.getType() ) );
449
		values.put( CommonDataKinds.Phone.NUMBER, number );
450
		if( data.isPreferred() )
451
			values.put( CommonDataKinds.Phone.IS_PRIMARY, 1 );
452
453
		_activity.getContentResolver().insert(
454
			ContactsContract.Data.CONTENT_URI, values );
455
	}
456
457
	@Override
458
	public void addContactEmail( Long id, String email,
459
		ContactData.PreferredDetail data ) throws ContactCreationException
460
	{
461
		ContentValues values = new ContentValues();
462
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
463
			obtainRawContact( id ) );
464
		values.put( ContactsContract.Data.MIMETYPE,
465
			CommonDataKinds.Email.CONTENT_ITEM_TYPE );
466
		values.put( CommonDataKinds.Email.TYPE,
467
			convertTypeToBackendType( CommonDataKinds.Email.class,
468
				data.getType() ) );
469
		values.put( CommonDataKinds.Email.DATA, email );
470
		if( data.isPreferred() )
471
			values.put( CommonDataKinds.Email.IS_PRIMARY, 1 );
472
473
		_activity.getContentResolver().insert(
474
			ContactsContract.Data.CONTENT_URI, values );
475
	}
476
477
	@Override
478
	public void addContactAddresses( Long id, String address,
479
		ContactData.TypeDetail data ) throws ContactCreationException
480
	{
481
		ContentValues values = new ContentValues();
482
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
483
			obtainRawContact( id ) );
484
		values.put( ContactsContract.Data.MIMETYPE,
485
			CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE );
486
		values.put( CommonDataKinds.StructuredPostal.TYPE,
487
			convertTypeToBackendType( CommonDataKinds.StructuredPostal.class,
488
				data.getType() ) );
489
		values.put(
490
			CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, address );
491
492
		_activity.getContentResolver().insert(
493
			ContactsContract.Data.CONTENT_URI, values );
494
	}
495
496
	@Override
497
	public void addContactOrganisation( Long id, String organisation,
498
		ContactData.ExtraDetail data ) throws ContactCreationException
499
	{
500
		ContentValues values = new ContentValues();
501
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
502
			obtainRawContact( id ) );
503
		values.put( ContactsContract.Data.MIMETYPE,
504
			CommonDataKinds.Organization.CONTENT_ITEM_TYPE );
505
		values.put( CommonDataKinds.Organization.TYPE,
506
			CommonDataKinds.Organization.TYPE_WORK );
507
		values.put(
508
			CommonDataKinds.Organization.COMPANY, organisation );
509
		if( data.getExtra() != null )
510
			values.put( CommonDataKinds.Organization.TITLE, data.getExtra() );
511
512
		_activity.getContentResolver().insert(
513
			ContactsContract.Data.CONTENT_URI, values );
514
	}
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
515
516
	@Override
517
	public void addContactNote( Long id, String note )
518
		throws ContactCreationException
519
	{
520
		ContentValues values = new ContentValues();
521
		values.put( ContactsContract.Data.RAW_CONTACT_ID,
522
			obtainRawContact( id ) );
523
		values.put( ContactsContract.Data.MIMETYPE,
524
			CommonDataKinds.Note.CONTENT_ITEM_TYPE );
525
		values.put(
526
			CommonDataKinds.Note.NOTE, note );
527
528
		_activity.getContentResolver().insert(
529
			ContactsContract.Data.CONTENT_URI, values );
530
	}
531
62 by edam
added preliminary (buggy) ContactsContract backend
532
}