Stable contact identity & CONTENT_LOOKUP_URI

by jarkman » Tue, 03 Nov 2009 01:09:27 GMT


Sponsored Links
 In the course of moving to the 2.0 cotnact APIs, I've stumbled across
CONTENT_LOOKUP_URI :

 http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html #CONTENT_LOOKUP_URI

"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 "

Currently, we store contact IDs to identify particular contacts. If I
read this right, contact IDs will no longer be stable in the world of
2.0, and we will need to store a lookup URI (or at least a LOOKUP_KEY
and a row ID) in order to identify a contact in a stable way.

That would be a substantial change in our code. So, before I rush off
to do it, I'd love to find out if a contact row ID change is going to
be a routine thing (say, on every sync), or if it will be a very rare
thing (say, when two contacts are manually combined into one, or some
even rarer exception).

Any clues ?

Thanks,

Richard

--



Stable contact identity & CONTENT_LOOKUP_URI

by Dmitri Plotnikov » Tue, 03 Nov 2009 04:44:34 GMT


 Hi Richard,

You are exactly right.  If you want a robust persistent reference to a
contact, you now need to use the lookup URI.  Android itself uses lookup
URIs for shortcuts, Quick Contact etc.  The main reason contact ID is
volatile is that Android 2.0 has contact aggregation, both automatic and
manual.  Let's say your app stored a long ID of a contact.  Then the user
goes and manually joins the contact with some other contact. Now we have one
contact where we used to have two - the stored long contact ID points
nowhere.  However, the lookup key is more resilient.  It's a string
concatenating identities of raw contacts.  Using that string, we can still
track down a contact as it is joined with others or separated from them.

There are two options available to you: you can store just the lookup key,
which is a string id of a contact, or you can use both the lookup and the
long id of a contact.  The latter will give you better performance, but
functionally the long id is not required.  I would take this approach: if
you need to bulk-process contacts, maintain both ids.  If your app works
with a single contact per user action - you don't need to bother with the
long id.

I hope this helps,
- Dmitri




>


Sponsored Links


Stable contact identity & CONTENT_LOOKUP_URI

by jarkman » Tue, 03 Nov 2009 19:33:47 GMT


 mitri - thanks - that's very helpful. I have a couple more questions,
if that's OK:

In the short term, if we do not use the lookup URI, and go on storing
record IDs, we will clearly lose track of a contact when aggregation
or dis-aggregation of a contact takes place. Are there any other
circumstances where we will lose track ? For example, might an ID
change as a result of a sync which does not aggregate or disaggregate
a contact ?

When we use the lookup uri and a contact is disaggregated, will the
lookup URI we are holding still refer to one of the two resulting
contacts, or will it no longer refer to either of them ?

Incidentally, I wonder if it might be worth mentioning this change a
bit more prominently in the 2.0 release notes. If I hadn't happened
across the lookup key in the docs, I would not have realised that 2.0
broke all our contact references. I imagine other developers may not
be so lucky.

Thanks,

Richard

On Nov 2, 5:32pm, Dmitri Plotnikov <dplotni...@google.com> wrote:
> >



Stable contact identity & CONTENT_LOOKUP_URI

by jarkman » Tue, 03 Nov 2009 22:41:00 GMT


 h - one more question:

Am I right in thinking that the lookup URI is not itself a unique,
stable identifier ? That is, the lookup URI for one contact may be
different at different times.

Right now, we store some contact row IDs in a table, along with per-
contact settings of our own. We use a WHERE clause on the contact ID
to pull out the settings for a particular contact.

If we store lookup URIs in the table, and want to find some current
contact in that table, we cannot do it by comparing lookup URIs
directly, because the lookup URI for the target contact may have
changed since we wrote the table. If we want to compare two lookup
URIs to see if they refer to the same person, we need to look them
both up in the contacts table and see if they have the same record ID
right now. Is that right ?

Thanks,

Richard


On Nov 2, 5:32pm, Dmitri Plotnikov <dplotni...@google.com> wrote:
> >



Stable contact identity & CONTENT_LOOKUP_URI

by jarkman » Wed, 04 Nov 2009 20:46:00 GMT


 mitri - thanks - that's perfect.

So, we have two choices -

(1) For each incoming contact URI, loop over our table of stored
lookup keys, looking each one up with
ContactsContract.Contacts.lookupContact(resolver, lookupUri) and
comparing with the incoming contact.

I think that will be reliable, and makes the best use of your cunning
lookup mechanisms, but could be a performance problem.


(2) Move our custom data into the generic data store in the contacts
database ( as hinted at here:
http://groups.google.com/group/android-developers/browse_thread/thread/690cd4e531205b0c/364e21a52b00491c?lnk=gst&q=contacts#364e21a52b00491c
)

That should be reliable, but I am not sure what will happen to the
generic data rows over contact aggregation and disaggregation.
Presumably we may find a contact who has two instances of our custom
data (after aggregation) or none (after disaggregation, if our custom
data stayed with the other half of the results).


(3) In our own table, keep all the raw contact IDs for each aggregated
contact we are interested in. That lets us deal with the aftermath of
aggregation and disaggregation explicitly, and it lets us search
quickly by comparing IDs, but it means we need to do something
complicated to clean up our data after a disaggregation has has
happened.

Do you think that covers it ?


Richard

On Nov 3, 7:17pm, Dmitri Plotnikov <dplotni...@google.com> wrote:
> > > >



Other Threads

1. Porting 1.0 to 1.5, Street view intent (also broken in Google Maps)

Did I say in an earlier post everything checks out porting from 1.0 to
1.5? Correction. Invoking the Street View activity crashes in the
emulator. Both in ported app and Google Maps app (there by clicking on
an address bubble) Stack dump:

04-30 02:00:27.757: ERROR/AndroidRuntime(665): Uncaught handler:
thread main exiting due to uncaught exception
04-30 02:00:27.785: ERROR/AndroidRuntime(665):
android.content.ActivityNotFoundException: No Activity found to handle
Intent { action=android.intent.action.VIEW
data=google.streetview:cbll=47.625476,-122.356021&cbp=1,268.72,,0,0&mz=17 }
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.app.Instrumentation.checkStartActivityResult
(Instrumentation.java:1484)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.app.Instrumentation.execStartActivity(Instrumentation.java:
1454)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.app.Activity.startActivityForResult(Activity.java:2656)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.app.Activity.startActivity(Activity.java:2700)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.google.android.maps.StreetViewOverlay.startStreetViewActivity
(StreetViewOverlay.java:697)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.google.android.maps.StreetViewOverlay.startStreetView
(StreetViewOverlay.java:686)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.google.android.maps.StreetViewOverlay.access$1200
(StreetViewOverlay.java:55)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.google.android.maps.StreetViewOverlay$5.onClick
(StreetViewOverlay.java:201)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.View.performClick(View.java:2179)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.View.onTouchEvent(View.java:3828)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.View.dispatchTouchEvent(View.java:3368)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:831)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.android.internal.policy.impl.PhoneWindow
$DecorView.superDispatchTouchEvent(PhoneWindow.java:1707)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent
(PhoneWindow.java:1197)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.app.Activity.dispatchTouchEvent(Activity.java:1993)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.android.internal.policy.impl.PhoneWindow
$DecorView.dispatchTouchEvent(PhoneWindow.java:1691)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.view.ViewRoot.handleMessage(ViewRoot.java:1525)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.os.Handler.dispatchMessage(Handler.java:99)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.os.Looper.loop(Looper.java:123)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
android.app.ActivityThread.main(ActivityThread.java:3948)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
java.lang.reflect.Method.invokeNative(Native Method)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
java.lang.reflect.Method.invoke(Method.java:521)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run
(ZygoteInit.java:782)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
04-30 02:00:27.785: ERROR/AndroidRuntime(665):     at
dalvik.system.NativeStart.main(Native Method)

I could not find anything on a corresponding "switch" to turn Street
View on (or what 1.5 needs to make this happen). The documentation in
developer.android.com leads to a 404. Swinging by
http://code.google.com/android/add-ons/google-apis/ does not contain
information on Street View (that I could find).
Hmm, anybody seeing the same issues? Resolution?



--~--~---------~--~----~------------~-------~--~----~

2. How how can we keep Overlay Surface unchanged when switch from Portrait to Landscape mode

In current android implementation,all the Surface will rotate 90degree
when switch to landscape.

We have requirement to keep the video unchanged (no rotation) and it
seems the only way is to ignore the orientation in
LayerBuffer::OverlaySource::onVisibilityResolved().

Please let me know if you have comments.
--~--~---------~--~----~------------~-------~--~----~

3. Android Design Awards (Suggestion)

4. QWERTY USB keyboard - keystrokes problem

5. retrieve all the images in phone and sdcard

6. How's preloaded-classes file generated?

7. Accessing Market from Cupcake on Dev phone