Home | History | Annotate | Download | only in latin
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.inputmethod.latin;
     18 
     19 import android.content.ContentResolver;
     20 import android.content.Context;
     21 import android.database.ContentObserver;
     22 import android.database.Cursor;
     23 import android.os.AsyncTask;
     24 import android.os.SystemClock;
     25 import android.provider.ContactsContract.Contacts;
     26 
     27 public class ContactsDictionary extends ExpandableDictionary {
     28 
     29     private static final String[] PROJECTION = {
     30         Contacts._ID,
     31         Contacts.DISPLAY_NAME,
     32     };
     33 
     34     private static final int INDEX_NAME = 1;
     35 
     36     private ContentObserver mObserver;
     37 
     38     private long mLastLoadedContacts;
     39 
     40     public ContactsDictionary(Context context) {
     41         super(context);
     42         // Perform a managed query. The Activity will handle closing and requerying the cursor
     43         // when needed.
     44         ContentResolver cres = context.getContentResolver();
     45 
     46         cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) {
     47             @Override
     48             public void onChange(boolean self) {
     49                 setRequiresReload(true);
     50             }
     51         });
     52         loadDictionary();
     53     }
     54 
     55     public synchronized void close() {
     56         if (mObserver != null) {
     57             getContext().getContentResolver().unregisterContentObserver(mObserver);
     58             mObserver = null;
     59         }
     60         super.close();
     61     }
     62 
     63     @Override
     64     public void startDictionaryLoadingTaskLocked() {
     65         long now = SystemClock.uptimeMillis();
     66         if (mLastLoadedContacts == 0
     67                 || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) {
     68             super.startDictionaryLoadingTaskLocked();
     69         }
     70     }
     71 
     72     @Override
     73     public void loadDictionaryAsync() {
     74         Cursor cursor = getContext().getContentResolver()
     75                 .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
     76         if (cursor != null) {
     77             addWords(cursor);
     78         }
     79         mLastLoadedContacts = SystemClock.uptimeMillis();
     80     }
     81 
     82     private void addWords(Cursor cursor) {
     83         clearDictionary();
     84 
     85         final int maxWordLength = getMaxWordLength();
     86         if (cursor.moveToFirst()) {
     87             while (!cursor.isAfterLast()) {
     88                 String name = cursor.getString(INDEX_NAME);
     89 
     90                 if (name != null) {
     91                     int len = name.length();
     92 
     93                     // TODO: Better tokenization for non-Latin writing systems
     94                     for (int i = 0; i < len; i++) {
     95                         if (Character.isLetter(name.charAt(i))) {
     96                             int j;
     97                             for (j = i + 1; j < len; j++) {
     98                                 char c = name.charAt(j);
     99 
    100                                 if (!(c == '-' || c == '\'' ||
    101                                       Character.isLetter(c))) {
    102                                     break;
    103                                 }
    104                             }
    105 
    106                             String word = name.substring(i, j);
    107                             i = j - 1;
    108 
    109                             // Safeguard against adding really long words. Stack
    110                             // may overflow due to recursion
    111                             // Also don't add single letter words, possibly confuses
    112                             // capitalization of i.
    113                             final int wordLen = word.length();
    114                             if (wordLen < maxWordLength && wordLen > 1) {
    115                                 super.addWord(word, 128);
    116                             }
    117                         }
    118                     }
    119                 }
    120 
    121                 cursor.moveToNext();
    122             }
    123         }
    124         cursor.close();
    125     }
    126 
    127 }
    128