diff options
author | 2015-02-09 12:22:47 -0800 | |
---|---|---|
committer | 2015-02-11 16:29:14 -0800 | |
commit | 4084fa5caeee09ef7993957c5e922dab14c57f3f (patch) | |
tree | b904b243d8ab05d6dc3e83411713d0b2a55c0014 /java/src/com/android/inputmethod/latin/ContactsManager.java | |
parent | 5254c01d4cc024527479d4dc5fab2ed2516c395c (diff) | |
download | latinime-4084fa5caeee09ef7993957c5e922dab14c57f3f.tar.gz latinime-4084fa5caeee09ef7993957c5e922dab14c57f3f.tar.xz latinime-4084fa5caeee09ef7993957c5e922dab14c57f3f.zip |
Refactor content provider code from ContactsDict
Break contacts binary dictionary into two parts
- one that talks to contacts content provider and maintains
local state. Includes a manager class and a content observer
- other one that just manages the dict code.
Change-Id: Ie8f89ac9ce174c803ff3168ee0bee5cbe7721d5b
Diffstat (limited to 'java/src/com/android/inputmethod/latin/ContactsManager.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/ContactsManager.java | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/java/src/com/android/inputmethod/latin/ContactsManager.java b/java/src/com/android/inputmethod/latin/ContactsManager.java new file mode 100644 index 000000000..dc5abd955 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ContactsManager.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteException; +import android.net.Uri; +import android.provider.ContactsContract.Contacts; +import android.util.Log; + +import com.android.inputmethod.latin.common.Constants; + +import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Manages all interactions with Contacts DB. + * + * The manager provides an API for listening to meaning full updates by keeping a + * measure of the current state of the content provider. + */ +// TODO:Add test +public class ContactsManager { + private static final String TAG = ContactsManager.class.getSimpleName(); + private static final boolean DEBUG = false; + + /** + * Interface to implement for classes interested in getting notified for updates + * to Contacts content provider. + */ + public static interface ContactsChangedListener { + public void onContactsChange(); + } + + /** + * The number of contacts observed in the most recent instance of + * contacts content provider. + */ + private AtomicInteger mContactCountAtLastRebuild = new AtomicInteger(0); + + /** + * The hash code of list of valid contacts names in the most recent dictionary + * rebuild. + */ + private AtomicInteger mHashCodeAtLastRebuild = new AtomicInteger(0); + + private final Context mContext; + private final ContactsContentObserver mObserver; + + public ContactsManager(final Context context) { + mContext = context; + mObserver = new ContactsContentObserver(this /* ContactsManager */, context); + } + + // TODO: This was synchronized in previous version. Why? + public void registerForUpdates(final ContactsChangedListener listener) { + mObserver.registerObserver(listener); + } + + public int getContactCountAtLastRebuild() { + return mContactCountAtLastRebuild.get(); + } + + public int getHashCodeAtLastRebuild() { + return mHashCodeAtLastRebuild.get(); + } + + /** + * Returns all the valid names in the Contacts DB. Callers should also + * call {@link #updateLocalState(ArrayList)} after they are done with result + * so that the manager can cache local state for determining updates. + */ + public ArrayList<String> getValidNames(final Uri uri) { + final ArrayList<String> names = new ArrayList<>(); + // Check all contacts since it's not possible to find out which names have changed. + // This is needed because it's possible to receive extraneous onChange events even when no + // name has changed. + final Cursor cursor = mContext.getContentResolver().query(uri, + ContactsDictionaryConstants.PROJECTION, null, null, null); + if (cursor != null) { + try { + if (cursor.moveToFirst()) { + while (!cursor.isAfterLast()) { + final String name = cursor.getString( + ContactsDictionaryConstants.NAME_INDEX); + if (isValidName(name)) { + names.add(name); + } + cursor.moveToNext(); + } + } + } finally { + cursor.close(); + } + } + return names; + } + + /** + * Returns the number of contacts in contacts content provider. + */ + public int getContactCount() { + // TODO: consider switching to a rawQuery("select count(*)...") on the database if + // performance is a bottleneck. + Cursor cursor = null; + try { + cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, + ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null); + if (null == cursor) { + return 0; + } + return cursor.getCount(); + } catch (final SQLiteException e) { + Log.e(TAG, "SQLiteException in the remote Contacts process.", e); + } finally { + if (null != cursor) { + cursor.close(); + } + } + return 0; + } + + private static boolean isValidName(final String name) { + if (name != null && -1 == name.indexOf(Constants.CODE_COMMERCIAL_AT)) { + return true; + } + return false; + } + + /** + * Updates the local state of the manager. This should be called when the callers + * are done with all the updates of the content provider successfully. + */ + public void updateLocalState(final ArrayList<String> names) { + mContactCountAtLastRebuild.set(getContactCount()); + mHashCodeAtLastRebuild.set(names.hashCode()); + } + + /** + * Performs any necessary cleanup. + */ + public void close() { + mObserver.unregister(); + } +} |