Android: Manage contacts with lookup key - android

I'm currently writing a application that allows to save drafts (using android version >= 2.0). Each draft is connected to a contact via the ContactsContract.Contacts.LOOKUP_KEY.
My problem is that if I change the name of my contact the lookup key changes also. Is that the way this works?
So for what do I need a lookup key? I thought that the lookup key does never change and now it changes anyway. I'm confused about that behavior ...
Can someone explain to me how to link permanently to a contact? Should I use IDs instead of the lookup key?
Thanks in advance.

It is my understanding that the lookup key is a structured / hierarchical key. Hence strictly speaking it can change, but still be used to find your contact back, by using the appropriate method:
Uri lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
Uri res = ContactsContract.Contacts.lookupContact(getContentResolver(), lookupUri);

Edited:
Why don't you find contact id or lookup key via using raw contact id? this is bug in 2.1.
Lookup key was based on the contact name for unsynced contacts.
http://comments.gmane.org/gmane.comp.handhelds.android.devel/130677
==================================================================
I didn't try yet. But I found some information about this.
http://developer.android.com/resources/articles/contacts.html
....
If performance is a concern for your application, you might want to store both the lookup and the long ID of a contact and construct a lookup URI out of both IDs, as shown here:
Uri lookupUri = getLookupUri(contactId, lookupKey)
When both IDs are present in the URI, the system will try to use the long ID first. That is a very quick query. If the contact is not found, or if the one that is found has the wrong lookup key, the content provider will parse the lookup key and track down the constituent raw contacts. If your app bulk-processes contacts, you should maintain both IDs. If your app works with a single contact per user action, you probably don't need to bother with storing the long ID.

Related

Should I rely on SOURCE_ID when reading Android Contacts?

I am creating an android contacts app, so I regularly read user's contacts and store them in my app. To do this, I need to rely on some kind of ID so that I know which contact I should update (or add/delete) in my app and Contacts Provider supplies several of them:
CONTACT_ID is the aggregate contact id,
each aggregate contact consists of one or more Raw Contacts, each with its own RAW_CONTACT_ID,
and most important, each Raw Contact has a SOURCE_ID, which is supposed to be the server id, i.e. the id this contact has in this account's server.
I 've chosen to rely on SOURCE_ID, since this sounds like the most stable one. E.g. when user removes and re-adds the same account in their device, I wouldn't want this account's contacts to get different IDs, because I wouldn't be able to match them in my app.
However, only Gmail sync adapter seems to keep the promise documented below. Exchange sync adapters unfortunately do not, SOURCE_ID changes, and it's definitely not any server id, since it has a small number like 23:4.
Question: Any ideas how to overcome this problem? Am I using the right ID for the intended use? Does exchange adapter stores the "permanent server id" in some other field?
Documentation: The SOURCE_ID must be unique for each account type and should be stable across syncs:
Unique: Each raw contact for an account must have its own source id. If you don't enforce this, you'll cause problems in the contacts
application. Notice that two raw contacts for the same account type
may have the same source id. For example, the raw contact "Thomas
Higginson" for the account emily.dickinson#gmail.com is allowed to
have the same source id as the raw contact "Thomas Higginson" for the
account emilyd#gmail.com.
Stable: Source ids are a permanent part of the online service's data for the raw contact. For example, if the user clears Contacts Storage
from the Apps settings and re-syncs, the restored raw contacts should
have the same source ids as before. If you don't enforce this,
shortcuts will stop working.
LOOKUP_KEY is what you're looking for.
LOOKUP_KEY
An opaque value that contains hints on how to find the
contact if its row id changed as a result of a sync or aggregation.
You should use a pair of <CONTACT_ID, LOOKUP_KEY> to keep track of contacts.
In normal use, use the CONTACT_ID value, but if your code gets a hint that the CONTACT_ID has changed (either missing, or unexpected contact name), you can use the LOOKUP_KEY to find the new contact-id.
Or you can use Contacts.getLookupUri() to get a URI you can always use to quickly find a contact no matter what its CONTACT_ID or LOOKUP_KEY actual values are.
First thing, it's not a good idea to store the Id in your application and hoping that the Id won't change over time and be consistent. You are right about 'SOURCE_ID' column that it's more consistent compared to the other two (CONTACT_ID is the most brittle while 'RAW_CONTACT_ID' persists at least until user logs out of an account and logs in again).
We had a syncable account with contacts and we used to keep the unique id in one of the general purpose columns in the 'raw_contacts' table (SYNC1 - SYNC10). So although Google suggests that account providers use the database columns in a certain manner but it's upto the provider totally.
General rule to follow is, never use those id's for long term persistence and if you do so, expect them to change. Also since you are making a contact App, you obviously need some kind of reference key. In such case, don't go by the rule that all account providers will put their key in the same column. It's brittle but that's the way it is.
Edit - You should use ContactsColumns.LOOKUP_KEY (previous answer also cited the same). As per the Google Documentation -
LOOKUP_KEY
Added in API level 5 String LOOKUP_KEY An opaque value that contains
hints on how to find the contact if its row id changed as a result of
a sync or aggregation.
Constant Value: "lookup"
https://developer.android.com/reference/android/provider/ContactsContract.ContactsColumns.html#LOOKUP_KEY
You can fetch the lookup key if you have the contact Id using API's provided. Look here - https://developer.android.com/reference/android/provider/ContactsContract.Contacts.html

Android Contacts: Is it possible to reference a given contact entry using a URN?

Let me try and clarify my intentions.
I'm developing an app that accesses to the Android contacts provider. I have already implemented a mechanism for pulling contacts from the contacts provider and storing the results in an SQLite table. Currently, when I query for the results of a contact's _ID, I can retrieve all the data for that contact, phone numbers, email addresses, etc.
However, in order to specify which of those my app should use on future occasions, I have to store the resulting contact data (e.g. CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.TYPE etc) in the SQL table.
This presents a problem if the data in the Android contacts provider has changed. One solution I have considered is to re-query the _ID and store the data that has changed. However, implementing such a solution requires gathering all data for that contact, making it difficult to determine the correct contact data to use.
My question is thus:
Is there a unique record key used in the Android Provider's contact data, in the same way as there is in the Provider's contact entry itself? A phone number or email address equivalent of Contact._ID?
Failing that, does the Android contacts provider store the last modified date and time? I'm hoping that if I can't reference the contact data in the provider, I can at least run a check to see if anything has changed since the contact was selected for use in the app, allowing my app to alert the user that the data has changed.
Yoi may use ContentObserver with the help of a service to monitor for contacts change or update.
for example-
extend contentObserver-
public class Contact_change extends ContentObserver
register contentobserver-
Contact_change changeObserver = new Contact_change();
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true,chageobserver);
By using this you can monitor for contact changes and update your database.
So while looking to see what was possible, I've come across some interesting findings by doing a localised record dump to my tablet.
I incorrectly referred to the phone _ID when asking my question. It's there, but it references individual records in any given contact. This might be useful, it might be exactly what I hoped, but it might also be a dead end.
So far, I've retrieved a contact using the Android Contacts Provider, which returns the contact's data including the fields that follow
ContactsContract.Contacts._ID
ContactsContract.Contacts.DISPLAY_NAME
After assigning the _ID to a String and using it in a query, I initially searched for the _ID in the ContactsContract.Data._ID field, which did not work as intended.
That's when I realised I was doing it wrong. I needed to apply the search to ContactsContract.Data.CONTACT_ID, which then retrieved all related data records for my selected contact.
Having corrected the error and re-ran my query, I found a series of records for the CONTACT_ID, each of which had its' own unique _ID (with the exception of photos and binary data, which all had a null reference to _ID instead.
Now the question is: Does this data reference change even if a phone number, email address or IM entry is modified, as opposed to deleted and re-created? I'll probably find out through further testing, but I wanted to ask if anyone had already tried this first.
Ultimately, I am hoping my internal SQL table can store only the CONTACT_ID and the _ID for each entry, relying on callbacks to the Android Provider to pull the relevant values. That way, I can be sure the data displayed in my app is up to date between the app and the stored contact data on the device.
Combined with the change notifier code provided here, I should be able to alert the user to any changes that may require action on their part.
Update:
More investigation reveals that the UID associated with a given contact entry is preserved through entry edits.
The UID is lost obviously on deletion, and in my brief testing, I have not found UID's being recycled. This solves a referential integrity issue for me at least, as that UID won't suddenly reference another record out of nowhere.
The upshot for anyone else wanting to reference individual entries in the Contacts Provider is that it's possible, and you can store only the _ID and still retrieve individual entries in the provider.

How do I robustly compare phone numbers in Android?

In an Android app I am developing, I have a database which maps:
<Contact ID, Contact Lookup Key> --> <My Custom Data Associated with Contact>
When an incoming SMS message comes in, I want to be able to look up My Custom Data Associated with Contact associated with the contact who sent the SMS message. I want to do the lookup in as few steps as possible.
The only data I can get out of the SMS message is the Phone Number, so the problem is basically one of mapping the Phone Number to My Custom Data Associated with Contact in as few steps as possible.
Now, I am aware that I can look up a contact from a phone number up using ContactsContract.PhoneLookup as described e.g. here. However, this does not get me to my desired result because both the Contact ID and Contact Lookup Key are subject to change. So if either the ID or the Lookup Key has changed for any contact I have persisted to my database, I have to basically load my whole database and refresh the ID/Lookup Key for each row before I can test whether they represent the same contact as the one returned by ContactsContract.PhoneLookup. This is a pretty brutal solution which I would prefer to avoid.
What I would like to do is keep a table mapping phone numbers to my custom data (in an N:1 relationship).
<Phone Number> --> <My Custom Data Associated with Contact>
This way, in theory at least, I can index the phone number column and just look up the data in one step. However, phone numbers come in many formats. My solution will only work if I can create a canonical representation of a given phone number. My plan was to use PhoneNumberUtils.getStrippedReversed to produce an efficiently indexable canonical phone number, but this fails on a trivial case, for example:
PhoneNumberUtils.getStrippedReversed("+1(306)6656320") --> 02365566031
PhoneNumberUtils.getStrippedReversed("(306)6656320") --> 0236556603
They aren't the same number!
So with that by way of long-winded explanation, my question is: Can anyone think of a way of converting a phone number to a canonical phone number so that I can perform an indexed database lookup on the number, or any other solution to the problem I described above?
You can use below method along with getStrippedReversed
public static String toCallerIDMinMatch (String phoneNumber)
*Returns the rightmost MIN_MATCH (5) characters in the network portion in reversed order This can be used to do a database lookup against the column that stores getStrippedReversed() Returns null if phoneNumber == null*
Then your comparison will give you the desired result

CONTACT_ID - Keeping it in sync

I am interested in your opinions on the best way to keep a robust reference to a contact starting android 2.0. I have read a lot regarding this issue but i don't know which technique is advisable and if there's any new ones. Below are the 3 options i found so far:
1- Don't use your own db. Extend the contacts.contract to write your data
2 - Use ContentObserver to keep track of any changes made to the contacts. This technique would however require your application to be running
3- Store all RAW contact IDs related to a CONTACT_ID in your db and infer the content of the aggregate contact from all its constituent RAW contacts
In my case i need to keep a separate db and i was wondering if there's any other new technique of keeping the CONTACT_ID current after aggregations and dis-aggregations...
Please advise
I am playing with the new Contacts API at the moment, writing an app which is also a source of contact data. I can't recommend #3 at all. To get all of "my" contact data I simply store them with a magic value in the RawContacts.SYNC1 field and query the contacts content provider for that when my app starts up.
Re. your question, don't use CONTACT_IDs, as they are volatile. Use the lookup API, i.e. if you have a raw contact ID, use RawContacts.getContactLookupUri() to get to the Contact. Likewise if some API gives you a contact ID, use Contacts.getLookupUri() to get a persistent identifier you can use later on.

Android: Manage contacts with lookup key

Following up on this question:
Android: Manage contacts with lookup key
(see below)
I have the same problem. However, it shows with Android 2.1 Update 1, But is OK with Android 2.2.
It seems that the lookup key changes with contact's name change with Android 2.1, but does not change with Android 2.2.
Did anybody else experience this? Any suggested workaround for Android 2.1?
Thanks
Original question by chromate
Hi everybody,
I'm currently writing a application that allows to save drafts (using android version >= 2.0). Each draft is connected to a contact via the ContactsContract.Contacts.LOOKUP_KEY. My problem is that if I change the name of my contact the lookup key changes also. Is that the way this works?
So for what do I need a lookup key? I thought that the lookup key does never change and now it changes anyway. I'm confused about that behavior ...
Can someone explain to me how to link permanently to a contact? Should I use IDs instead of the lookup key?
Thanks in advance.
You can use contact ids instead of that. Look up key is not stable. So do not us look up key. And the benefit of contact id is it won't very. So use contact id. good luck
why don't you find contact id or lookup key via using raw contact id?
this is bug in 2.1.
Lookup key was based on the contact name for unsynced contacts.
http://comments.gmane.org/gmane.comp.handhelds.android.devel/130677
even a lookup key is changed, it will still point to same contact.
from: https://developer.android.com/guide/topics/providers/contacts-provider
The ContactsContract.Contacts table also has the column LOOKUP_KEY that is a "permanent" link to the contact row. Because the Contacts Provider maintains contacts automatically, it may change a contact row's _ID value in response to an aggregation or sync. Even If this happens, the content URI CONTENT_LOOKUP_URI combined with contact's LOOKUP_KEY will still point to the contact row, so you can use LOOKUP_KEY to maintain links to "favorite" contacts, and so forth. This column has its own format that is unrelated to the format of the _ID column.

Categories

Resources