I want to search the contact list to get a particular contact using _ID or LOOKUP_KEY. Which one of these two is better and the reason. It will be really helpful if you give the main differences of both.
Android Doc says-
_ID - Row ID. Consider using LOOKUP_KEY instead.
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.
So when in case the contacts RowID change for any reason LOOKUP_KEY is our way to go. Check this link on how to find it as this is not there on Docs I guess.
Related
I have an app that gets the ContactsContract.Contacts.LOOKUP_KEY of a contact on the device and saves it on the app Db.
After reading this page I thought I could use the LOOKUP_KEY to uniquely identify a contact, even when a contact is edited (for example after editing the name of the contact).
Actually I saw that after editing a contact, its LOOKUP_KEY changes, so I cannot use anymore the LOOKUP_KEY I saved on my app DB.
My question is: is there a way to uniquely identify a contact on ContactsContract.Contacts from when it is created for the first time on the device until it is deleted from the device?
Thank you
A LOOKUP_KEY is not meant to be used as a key on its own, instead it should be used together with a contact's _ID to form a full lookupUri.
The lookupUri can then be used to find a contact in CONTENT_LOOKUP_URI tables.
The CONTENT_LOOKUP_URI basically first looks for the contact by _ID, if it fails to find it, or the _ID seems like the wrong contact, it uses hints from the LOOKUP_KEY part to try and track down the correct contact for you.
From CONTENT_LOOKUP_URI
A content:// style URI for this table that should be used to create
shortcuts or otherwise create long-term links to contacts. This URI
should always be followed by a "/" and the contact's LOOKUP_KEY. It
can optionally also have a "/" and last known contact ID appended
after that. This "complete" format is an important optimization and is
highly recommended.
As long as the contact's row ID remains the same, this URI is
equivalent to CONTENT_URI. If the contact's row ID changes as a result
of a sync or aggregation, this URI will look up the contact using
indirect information (sync IDs or constituent raw contacts).
Lookup key should be appended unencoded - it is stored in the encoded
form, ready for use in a URI.
From getLookupUri(long contactId, String lookupKey)
Build a CONTENT_LOOKUP_URI lookup Uri using the given _ID and
LOOKUP_KEY.
From 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.
The row id (primary key) for each contact called _ID.
So, I can write to and retrieve info from the ContactsContract, however I have a question about how it works.
It is my understanding that all contact information for Contacts are stored within ContactsContract.Contact and ContactsContract.Data (ContactsContract.CommonDataDataKinds.Phone/Email/etc are all references to ContactsContract.Data, right?). A majority of this info is stored within ContactsContract.Data.DATA1-15.
Ignoring contact groups, if I wanted to create a contact app, do I only need to worry about DATA1-DATA15 for storing actual numbers/email/address/birthday/etc? What happens if a contact has more than 14 pieces of contact data (DATA15 is a blob)?
Am I missing something vital?
Edit - I'm looking more into it, and it seems like the common MIME types may be the best way of searching. If I search the following MIMETYPES:
StructuredName.CONTENT_ITEM_TYPE
Phone.CONTENT_ITEM_TYPE
Email.CONTENT_ITEM_TYPE
Photo.CONTENT_ITEM_TYPE
Organization.CONTENT_ITEM_TYPE
Im.CONTENT_ITEM_TYPE
Nickname.CONTENT_ITEM_TYPE
Note.CONTENT_ITEM_TYPE
StructuredPostal.CONTENT_ITEM_TYPE
GroupMembership.CONTENT_ITEM_TYPE
Website.CONTENT_ITEM_TYPE
Event.CONTENT_ITEM_TYPE
Relation.CONTENT_ITEM_TYPE
SipAddress.CONTENT_ITEM_TYPE
Will that handle everything? It's probably important to note that I'm using ContactsContract.Contacts.CONTENT_FILTER_URI as my search query. My goal is to have a similar effect as the standard app, where if I search, I can display the matching field below the contact's name.
Thanks for the help.
According to Google docs, you should use LOOKUP_KEY to fetch a contact, since its ID in the ContactsContract.Contacts table can change:
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.
(source)
Is it also possible that a RawContacts's ID in the ContactsContract.RawContacts change as well?
I've got a fairly complicated query (multiple joins) on a normalized sqlite database. The query does a SELECT * to enable some automated attribute selection logic (so I can't eliminate the "*")
The problem I am having is that my result set contains multiple columns with the same attribute name. For example, one attribute common to each table in the query is "_id". When I go to call "cursor.getColumnIndex("_id")" the value returned is always the index of the last "_id" attribute in the result set column list (i.e. not the one I want). I'd love to be able to use my SQL alias prefixes like cursor.getColumnIndex("A._id") but that is not working.
QUESTIONs
It appears that cursor.getColumnIndex(AttributeName) returns the index of the last "AttributeName". Can anyone confirm this?
Also, any suggestions on how return the index of the 1st attribute with "AttributeName"? or better the Xth attribute having "AttributeName"?
You can do this:
SELECT _id as myID, * FROM myTable
This means the _id field will appear twice for each table in your results, but one of the two columns will have a unique name which should enable you to find it.
Unfortunately the documentation doesn't mention anything about what you need to do, so I am assuming it cannot be done.
However, you say
The query does a SELECT * to enable some automated attribute selection
logic (so I can't eliminate the "*")
What is this 'automated attribute selection logic' you speak of? Why do you require this?
An oder solution is:
"SELECT tableName.columnName FROM tableName"
and then do the same with:
cursor.getColumnIndex("tableName.columnName");
This is what MS-Access does. You can create a query and then see the generated SQL code (simply going to 'view' menu and selecting 'SQL view' from your query dessign window)
Here's an interesting question that I'm shocked hasn't been asked more often on the internet. Android's CursorAdapters are extremely useful once you get a ContentProvider up and running and learn how to use it, but they are limited due to their requirement on having the _id field as part of their query (an error is thrown without it). Here's why:
My specific problem is that I have two spinners: One spinner should contain unique "category" names from the database, and the other should populate with all the database entries from the selected "category" (category being the column name, here). This seems like a pretty simple setup that many programs might use, no? Trying to implement that first spinner is where I've run into problems.
Here's the query that I would like for that first spinner:
SELECT DISTINCT category FROM table;
Making this query throws an error on CursorAdapter because the _id column is required as part of the query. Adding the _id column to the projection naturally returns every row of the table, since you're now asking for distinct id's as well, and every id is distinct (by definition). Obviously I would rather see only one entry per category name.
I've already implemented a work around, which is to simply make the query above and then copy the results into an ArrayAdapter. My reason for this post is to see if there was a more elegant solution to this odd little problem and start a discussion on what I could be doing better. Alternate implementation suggestions, such as using different kinds of controls or adapters, are very welcome.
Here's the query I ended up with:
SELECT _id, category FROM table_name GROUP BY category;
I used the rawQuery() function on an SQLiteDatabase object to carry this out. The "GROUP BY" piece was the key towards getting the right results, so thanks to user Sagar for pointing me in the right direction.
Do consider user Al Sutton's answer to this question as well, as it may be a more elegant solution to this problem.
Thanks everyone!
I'd suggest having a separate table with just _id & category in it which contains one row per unique category. Your data rows can then replace their category field with the _id from the category table.
This has the added advantage you can change the category in the categories table and it will show up in all entries in that category.
SELECT DISTINCT category,_id FROM table GROUP BY category;
I think this should give you what you are looking for. The results from this will be the category, and the first _id for that category. You can ignore the second column (_id).
You can specify an _id field alias in your select statement that is just a constant value, for example:
SELECT DISTINCT 0 _id, category FROM table;
Better yet, I solved this problem by using:
SELECT DISTINCT category AS _id FROM table
Now, you have a column with the name _id which has what you want in it