Home | History | Annotate | Download | only in list
      1 /*
      2  * Copyright (C) 2010 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 package com.android.contacts.list;
     17 
     18 import com.android.contacts.R;
     19 
     20 import android.content.AsyncTaskLoader;
     21 import android.content.Context;
     22 import android.content.pm.PackageManager;
     23 import android.database.ContentObserver;
     24 import android.database.Cursor;
     25 import android.database.MatrixCursor;
     26 import android.net.Uri;
     27 import android.os.Handler;
     28 import android.provider.ContactsContract.Directory;
     29 import android.text.TextUtils;
     30 import android.util.Log;
     31 
     32 /**
     33  * A specialized loader for the list of directories, see {@link Directory}.
     34  */
     35 public class DirectoryListLoader extends AsyncTaskLoader<Cursor> {
     36 
     37     private static final String TAG = "ContactEntryListAdapter";
     38 
     39     public static final int SEARCH_MODE_NONE = 0;
     40     public static final int SEARCH_MODE_DEFAULT = 1;
     41     public static final int SEARCH_MODE_CONTACT_SHORTCUT = 2;
     42     public static final int SEARCH_MODE_DATA_SHORTCUT = 3;
     43 
     44     private static final class DirectoryQuery {
     45         public static final Uri URI = Directory.CONTENT_URI;
     46         public static final String ORDER_BY = Directory._ID;
     47 
     48         public static final String[] PROJECTION = {
     49             Directory._ID,
     50             Directory.PACKAGE_NAME,
     51             Directory.TYPE_RESOURCE_ID,
     52             Directory.DISPLAY_NAME,
     53             Directory.PHOTO_SUPPORT,
     54         };
     55 
     56         public static final int ID = 0;
     57         public static final int PACKAGE_NAME = 1;
     58         public static final int TYPE_RESOURCE_ID = 2;
     59         public static final int DISPLAY_NAME = 3;
     60         public static final int PHOTO_SUPPORT = 4;
     61     }
     62 
     63     public static final String DIRECTORY_TYPE = "directoryType";
     64 
     65     private static final String[] RESULT_PROJECTION = {
     66         Directory._ID,
     67         DIRECTORY_TYPE,
     68         Directory.DISPLAY_NAME,
     69         Directory.PHOTO_SUPPORT,
     70     };
     71 
     72     private final ContentObserver mObserver = new ContentObserver(new Handler()) {
     73         @Override
     74         public void onChange(boolean selfChange) {
     75             forceLoad();
     76         }
     77     };
     78 
     79     private int mDirectorySearchMode;
     80     private boolean mLocalInvisibleDirectoryEnabled;
     81 
     82     private MatrixCursor mDefaultDirectoryList;
     83 
     84     public DirectoryListLoader(Context context) {
     85         super(context);
     86     }
     87 
     88     public void setDirectorySearchMode(int mode) {
     89         mDirectorySearchMode = mode;
     90     }
     91 
     92     /**
     93      * A flag that indicates whether the {@link Directory#LOCAL_INVISIBLE} directory should
     94      * be included in the results.
     95      */
     96     public void setLocalInvisibleDirectoryEnabled(boolean flag) {
     97         this.mLocalInvisibleDirectoryEnabled = flag;
     98     }
     99 
    100     @Override
    101     protected void onStartLoading() {
    102         getContext().getContentResolver().
    103                 registerContentObserver(Directory.CONTENT_URI, false, mObserver);
    104         forceLoad();
    105     }
    106 
    107     @Override
    108     protected void onStopLoading() {
    109         getContext().getContentResolver().unregisterContentObserver(mObserver);
    110     }
    111 
    112     @Override
    113     public Cursor loadInBackground() {
    114         if (mDirectorySearchMode == SEARCH_MODE_NONE) {
    115             return getDefaultDirectories();
    116         }
    117 
    118         MatrixCursor result = new MatrixCursor(RESULT_PROJECTION);
    119         Context context = getContext();
    120         PackageManager pm = context.getPackageManager();
    121         String selection;
    122         switch (mDirectorySearchMode) {
    123             case SEARCH_MODE_DEFAULT:
    124                 selection = mLocalInvisibleDirectoryEnabled ? null
    125                         : (Directory._ID + "!=" + Directory.LOCAL_INVISIBLE);
    126                 break;
    127 
    128             case SEARCH_MODE_CONTACT_SHORTCUT:
    129                 selection = Directory.SHORTCUT_SUPPORT + "=" + Directory.SHORTCUT_SUPPORT_FULL
    130                         + (mLocalInvisibleDirectoryEnabled ? ""
    131                                 : (" AND " + Directory._ID + "!=" + Directory.LOCAL_INVISIBLE));
    132                 break;
    133 
    134             case SEARCH_MODE_DATA_SHORTCUT:
    135                 selection = Directory.SHORTCUT_SUPPORT + " IN ("
    136                         + Directory.SHORTCUT_SUPPORT_FULL + ", "
    137                         + Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY + ")"
    138                         + (mLocalInvisibleDirectoryEnabled ? ""
    139                                 : (" AND " + Directory._ID + "!=" + Directory.LOCAL_INVISIBLE));
    140                 break;
    141 
    142             default:
    143                 throw new RuntimeException(
    144                         "Unsupported directory search mode: " + mDirectorySearchMode);
    145         }
    146 
    147         Cursor cursor = context.getContentResolver().query(DirectoryQuery.URI,
    148                 DirectoryQuery.PROJECTION, selection, null, DirectoryQuery.ORDER_BY);
    149         try {
    150             while(cursor.moveToNext()) {
    151                 long directoryId = cursor.getLong(DirectoryQuery.ID);
    152                 String directoryType = null;
    153 
    154                 String packageName = cursor.getString(DirectoryQuery.PACKAGE_NAME);
    155                 int typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID);
    156                 if (!TextUtils.isEmpty(packageName) && typeResourceId != 0) {
    157                     try {
    158                         directoryType = pm.getResourcesForApplication(packageName)
    159                                 .getString(typeResourceId);
    160                     } catch (Exception e) {
    161                         Log.e(TAG, "Cannot obtain directory type from package: " + packageName);
    162                     }
    163                 }
    164                 String displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME);
    165                 int photoSupport = cursor.getInt(DirectoryQuery.PHOTO_SUPPORT);
    166                 result.addRow(new Object[]{directoryId, directoryType, displayName, photoSupport});
    167             }
    168         } finally {
    169             cursor.close();
    170         }
    171 
    172         return result;
    173     }
    174 
    175     private Cursor getDefaultDirectories() {
    176         if (mDefaultDirectoryList == null) {
    177             mDefaultDirectoryList = new MatrixCursor(RESULT_PROJECTION);
    178             mDefaultDirectoryList.addRow(new Object[] {
    179                     Directory.DEFAULT,
    180                     getContext().getString(R.string.contactsList),
    181                     null
    182             });
    183             mDefaultDirectoryList.addRow(new Object[] {
    184                     Directory.LOCAL_INVISIBLE,
    185                     getContext().getString(R.string.local_invisible_directory),
    186                     null
    187             });
    188         }
    189         return mDefaultDirectoryList;
    190     }
    191 
    192     @Override
    193     protected void onReset() {
    194         stopLoading();
    195     }
    196 }
    197