/* * Copyright (C) 2010 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.contacts.list; import com.android.contacts.R; import android.content.AsyncTaskLoader; import android.content.Context; import android.content.pm.PackageManager; import android.database.ContentObserver; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.Handler; import android.provider.ContactsContract.Directory; import android.text.TextUtils; import android.util.Log; /** * A specialized loader for the list of directories, see {@link Directory}. */ public class DirectoryListLoader extends AsyncTaskLoader<Cursor> { private static final String TAG = "ContactEntryListAdapter"; public static final int SEARCH_MODE_NONE = 0; public static final int SEARCH_MODE_DEFAULT = 1; public static final int SEARCH_MODE_CONTACT_SHORTCUT = 2; public static final int SEARCH_MODE_DATA_SHORTCUT = 3; private static final class DirectoryQuery { public static final Uri URI = Directory.CONTENT_URI; public static final String ORDER_BY = Directory._ID; public static final String[] PROJECTION = { Directory._ID, Directory.PACKAGE_NAME, Directory.TYPE_RESOURCE_ID, Directory.DISPLAY_NAME, Directory.PHOTO_SUPPORT, }; public static final int ID = 0; public static final int PACKAGE_NAME = 1; public static final int TYPE_RESOURCE_ID = 2; public static final int DISPLAY_NAME = 3; public static final int PHOTO_SUPPORT = 4; } public static final String DIRECTORY_TYPE = "directoryType"; private static final String[] RESULT_PROJECTION = { Directory._ID, DIRECTORY_TYPE, Directory.DISPLAY_NAME, Directory.PHOTO_SUPPORT, }; private final ContentObserver mObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { forceLoad(); } }; private int mDirectorySearchMode; private boolean mLocalInvisibleDirectoryEnabled; private MatrixCursor mDefaultDirectoryList; public DirectoryListLoader(Context context) { super(context); } public void setDirectorySearchMode(int mode) { mDirectorySearchMode = mode; } /** * A flag that indicates whether the {@link Directory#LOCAL_INVISIBLE} directory should * be included in the results. */ public void setLocalInvisibleDirectoryEnabled(boolean flag) { this.mLocalInvisibleDirectoryEnabled = flag; } @Override protected void onStartLoading() { getContext().getContentResolver(). registerContentObserver(Directory.CONTENT_URI, false, mObserver); forceLoad(); } @Override protected void onStopLoading() { getContext().getContentResolver().unregisterContentObserver(mObserver); } @Override public Cursor loadInBackground() { if (mDirectorySearchMode == SEARCH_MODE_NONE) { return getDefaultDirectories(); } MatrixCursor result = new MatrixCursor(RESULT_PROJECTION); Context context = getContext(); PackageManager pm = context.getPackageManager(); String selection; switch (mDirectorySearchMode) { case SEARCH_MODE_DEFAULT: selection = mLocalInvisibleDirectoryEnabled ? null : (Directory._ID + "!=" + Directory.LOCAL_INVISIBLE); break; case SEARCH_MODE_CONTACT_SHORTCUT: selection = Directory.SHORTCUT_SUPPORT + "=" + Directory.SHORTCUT_SUPPORT_FULL + (mLocalInvisibleDirectoryEnabled ? "" : (" AND " + Directory._ID + "!=" + Directory.LOCAL_INVISIBLE)); break; case SEARCH_MODE_DATA_SHORTCUT: selection = Directory.SHORTCUT_SUPPORT + " IN (" + Directory.SHORTCUT_SUPPORT_FULL + ", " + Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY + ")" + (mLocalInvisibleDirectoryEnabled ? "" : (" AND " + Directory._ID + "!=" + Directory.LOCAL_INVISIBLE)); break; default: throw new RuntimeException( "Unsupported directory search mode: " + mDirectorySearchMode); } Cursor cursor = context.getContentResolver().query(DirectoryQuery.URI, DirectoryQuery.PROJECTION, selection, null, DirectoryQuery.ORDER_BY); try { while(cursor.moveToNext()) { long directoryId = cursor.getLong(DirectoryQuery.ID); String directoryType = null; String packageName = cursor.getString(DirectoryQuery.PACKAGE_NAME); int typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID); if (!TextUtils.isEmpty(packageName) && typeResourceId != 0) { try { directoryType = pm.getResourcesForApplication(packageName) .getString(typeResourceId); } catch (Exception e) { Log.e(TAG, "Cannot obtain directory type from package: " + packageName); } } String displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME); int photoSupport = cursor.getInt(DirectoryQuery.PHOTO_SUPPORT); result.addRow(new Object[]{directoryId, directoryType, displayName, photoSupport}); } } finally { cursor.close(); } return result; } private Cursor getDefaultDirectories() { if (mDefaultDirectoryList == null) { mDefaultDirectoryList = new MatrixCursor(RESULT_PROJECTION); mDefaultDirectoryList.addRow(new Object[] { Directory.DEFAULT, getContext().getString(R.string.contactsList), null }); mDefaultDirectoryList.addRow(new Object[] { Directory.LOCAL_INVISIBLE, getContext().getString(R.string.local_invisible_directory), null }); } return mDefaultDirectoryList; } @Override protected void onReset() { stopLoading(); } }