1d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng/* 2d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Copyright (C) 2010 The Android Open Source Project 3d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 4d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 5d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * you may not use this file except in compliance with the License. 6d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * You may obtain a copy of the License at 7d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 8d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 9d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 10d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Unless required by applicable law or agreed to in writing, software 11d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 12d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * See the License for the specific language governing permissions and 14d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * limitations under the License. 15d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 16d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengpackage com.android.contacts.common.list; 17d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 18d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.content.AsyncTaskLoader; 19d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.content.Context; 20d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.content.pm.PackageManager; 21d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.database.ContentObserver; 22d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.database.Cursor; 23d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.database.MatrixCursor; 24d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.net.Uri; 25d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.os.Handler; 26d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.provider.ContactsContract.Directory; 27d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.TextUtils; 28d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.util.Log; 29d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 30d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.R; 31d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 32d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng/** 33d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * A specialized loader for the list of directories, see {@link Directory}. 34d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 35d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengpublic class DirectoryListLoader extends AsyncTaskLoader<Cursor> { 36d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 37d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private static final String TAG = "ContactEntryListAdapter"; 38d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 39d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int SEARCH_MODE_NONE = 0; 40d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int SEARCH_MODE_DEFAULT = 1; 41d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int SEARCH_MODE_CONTACT_SHORTCUT = 2; 42d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int SEARCH_MODE_DATA_SHORTCUT = 3; 43d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 44d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private static final class DirectoryQuery { 45d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final Uri URI = Directory.CONTENT_URI; 46d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final String ORDER_BY = Directory._ID; 47d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 48d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final String[] PROJECTION = { 49d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory._ID, 50d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.PACKAGE_NAME, 51d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.TYPE_RESOURCE_ID, 52d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.DISPLAY_NAME, 53d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.PHOTO_SUPPORT, 54d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng }; 55d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 56d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int ID = 0; 57d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int PACKAGE_NAME = 1; 58d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int TYPE_RESOURCE_ID = 2; 59d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int DISPLAY_NAME = 3; 60d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final int PHOTO_SUPPORT = 4; 61d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 62d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 63d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // This is a virtual column created for a MatrixCursor. 64d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public static final String DIRECTORY_TYPE = "directoryType"; 65d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 66d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private static final String[] RESULT_PROJECTION = { 67d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory._ID, 68d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng DIRECTORY_TYPE, 69d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.DISPLAY_NAME, 70d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.PHOTO_SUPPORT, 71d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng }; 72d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 73d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private final ContentObserver mObserver = new ContentObserver(new Handler()) { 74d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 75d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void onChange(boolean selfChange) { 76d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng forceLoad(); 77d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 78d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng }; 79d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 80d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDirectorySearchMode; 81d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mLocalInvisibleDirectoryEnabled; 82d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 83d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private MatrixCursor mDefaultDirectoryList; 84d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 85d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public DirectoryListLoader(Context context) { 86d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super(context); 87d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 88d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 89d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setDirectorySearchMode(int mode) { 90d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDirectorySearchMode = mode; 91d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 92d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 93d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 94d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * A flag that indicates whether the {@link Directory#LOCAL_INVISIBLE} directory should 95d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * be included in the results. 96d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 97d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setLocalInvisibleDirectoryEnabled(boolean flag) { 98d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng this.mLocalInvisibleDirectoryEnabled = flag; 99d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 100d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 101d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 102d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onStartLoading() { 103d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getContext().getContentResolver(). 104d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng registerContentObserver(Directory.CONTENT_URI, false, mObserver); 105d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng forceLoad(); 106d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 107d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 108d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 109d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onStopLoading() { 110d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getContext().getContentResolver().unregisterContentObserver(mObserver); 111d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 112d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 113d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 114d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public Cursor loadInBackground() { 115d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDirectorySearchMode == SEARCH_MODE_NONE) { 116d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return getDefaultDirectories(); 117d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 118d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 119d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MatrixCursor result = new MatrixCursor(RESULT_PROJECTION); 120d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Context context = getContext(); 121d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng PackageManager pm = context.getPackageManager(); 122d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng String selection; 123d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng switch (mDirectorySearchMode) { 124d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng case SEARCH_MODE_DEFAULT: 125d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng selection = mLocalInvisibleDirectoryEnabled ? null 126d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng : (Directory._ID + "!=" + Directory.LOCAL_INVISIBLE); 127d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng break; 128d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 129d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng case SEARCH_MODE_CONTACT_SHORTCUT: 130d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng selection = Directory.SHORTCUT_SUPPORT + "=" + Directory.SHORTCUT_SUPPORT_FULL 131d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng + (mLocalInvisibleDirectoryEnabled ? "" 132d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng : (" AND " + Directory._ID + "!=" + Directory.LOCAL_INVISIBLE)); 133d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng break; 134d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 135d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng case SEARCH_MODE_DATA_SHORTCUT: 136d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng selection = Directory.SHORTCUT_SUPPORT + " IN (" 137d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng + Directory.SHORTCUT_SUPPORT_FULL + ", " 138d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng + Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY + ")" 139d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng + (mLocalInvisibleDirectoryEnabled ? "" 140d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng : (" AND " + Directory._ID + "!=" + Directory.LOCAL_INVISIBLE)); 141d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng break; 142d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 143d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng default: 144d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng throw new RuntimeException( 145d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng "Unsupported directory search mode: " + mDirectorySearchMode); 146d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 147d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 148d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Cursor cursor = context.getContentResolver().query(DirectoryQuery.URI, 149d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng DirectoryQuery.PROJECTION, selection, null, DirectoryQuery.ORDER_BY); 150903c973e0ef995ee05acf8fa7501377afa971384Yorke Lee if (cursor == null) { 151903c973e0ef995ee05acf8fa7501377afa971384Yorke Lee return result; 152903c973e0ef995ee05acf8fa7501377afa971384Yorke Lee } 153d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng try { 154d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng while(cursor.moveToNext()) { 155d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng long directoryId = cursor.getLong(DirectoryQuery.ID); 156d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng String directoryType = null; 157d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 158d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng String packageName = cursor.getString(DirectoryQuery.PACKAGE_NAME); 159d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID); 160d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!TextUtils.isEmpty(packageName) && typeResourceId != 0) { 161d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng try { 162d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng directoryType = pm.getResourcesForApplication(packageName) 163d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng .getString(typeResourceId); 164d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } catch (Exception e) { 165d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Log.e(TAG, "Cannot obtain directory type from package: " + packageName); 166d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 167d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 168d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng String displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME); 169d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int photoSupport = cursor.getInt(DirectoryQuery.PHOTO_SUPPORT); 170d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng result.addRow(new Object[]{directoryId, directoryType, displayName, photoSupport}); 171d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 172d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } finally { 173d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng cursor.close(); 174d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 175d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 176d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return result; 177d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 178d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 179d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Cursor getDefaultDirectories() { 180d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDefaultDirectoryList == null) { 181d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDefaultDirectoryList = new MatrixCursor(RESULT_PROJECTION); 182d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDefaultDirectoryList.addRow(new Object[] { 183d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.DEFAULT, 184d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getContext().getString(R.string.contactsList), 185d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng null 186d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng }); 187d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDefaultDirectoryList.addRow(new Object[] { 188d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Directory.LOCAL_INVISIBLE, 189d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getContext().getString(R.string.local_invisible_directory), 190d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng null 191d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng }); 192d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 193d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mDefaultDirectoryList; 194d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 195d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 196d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 197d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onReset() { 198d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng stopLoading(); 199d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 200d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng} 201