在Contacts中,contacts2.db数据库位于/data/data/com.android.providers.contacts/databases里,contacts2.db中有很多张表,下面主要看下几张重要的表
创建contacts2.db的地方在packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsDatabaseHelper.java中,
里面定义了contact2.db数据里表名和视图名
public interface Tables { public static final String CONTACTS = "contacts"; public static final String DELETED_CONTACTS = "deleted_contacts"; public static final String RAW_CONTACTS = "raw_contacts"; public static final String STREAM_ITEMS = "stream_items"; public static final String STREAM_ITEM_PHOTOS = "stream_item_photos"; public static final String PHOTO_FILES = "photo_files"; public static final String PACKAGES = "packages"; public static final String MIMETYPES = "mimetypes"; public static final String PHONE_LOOKUP = "phone_lookup"; public static final String NAME_LOOKUP = "name_lookup"; public static final String AGGREGATION_EXCEPTIONS = "agg_exceptions"; public static final String SETTINGS = "settings"; public static final String DATA = "data"; public static final String GROUPS = "groups"; public static final String PRESENCE = "presence"; public static final String AGGREGATED_PRESENCE = "agg_presence"; public static final String NICKNAME_LOOKUP = "nickname_lookup"; public static final String CALLS = "calls"; public static final String STATUS_UPDATES = "status_updates"; public static final String PROPERTIES = "properties"; public static final String ACCOUNTS = "accounts"; public static final String VISIBLE_CONTACTS = "visible_contacts"; public static final String DIRECTORIES = "directories"; public static final String DEFAULT_DIRECTORY = "default_directory"; public static final String SEARCH_INDEX = "search_index"; public static final String VOICEMAIL_STATUS = "voicemail_status"; public static final String PRE_AUTHORIZED_URIS = "pre_authorized_uris";视图表的定义
public interface Views { public static final String DATA = "view_data"; public static final String RAW_CONTACTS = "view_raw_contacts"; public static final String CONTACTS = "view_contacts"; public static final String ENTITIES = "view_entities"; public static final String RAW_ENTITIES = "view_raw_entities"; public static final String GROUPS = "view_groups"; public static final String DATA_USAGE_STAT = "view_data_usage_stat"; public static final String STREAM_ITEMS = "view_stream_items"; }
@Override public void onCreate(SQLiteDatabase db) { Log.i(TAG, "Bootstrapping database version: " + DATABASE_VERSION); mSyncState.createDatabase(db); // Create the properties table first so the create time is available as soon as possible. // The create time is needed by BOOT_COMPLETE to send broadcasts. db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" + PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " + PropertiesColumns.PROPERTY_VALUE + " TEXT " + ");"); setProperty(db, DbProperties.DATABASE_TIME_CREATED, String.valueOf( System.currentTimeMillis())); db.execSQL("CREATE TABLE " + Tables.ACCOUNTS + " (" + AccountsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + AccountsColumns.ACCOUNT_NAME + " TEXT, " + AccountsColumns.ACCOUNT_TYPE + " TEXT, " + AccountsColumns.DATA_SET + " TEXT" + ");"); // One row per group of contacts corresponding to the same person db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," + Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," + Contacts.PHOTO_FILE_ID + " INTEGER REFERENCES photo_files(_id)," + Contacts.CUSTOM_RINGTONE + " TEXT," + Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," + Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," + Contacts.LAST_TIME_CONTACTED + " INTEGER," + Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," + Contacts.PINNED + " INTEGER NOT NULL DEFAULT " + PinnedPositions.UNPINNED + "," + Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," + Contacts.LOOKUP_KEY + " TEXT," + ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)," + Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " INTEGER" + ");"); ContactsTableUtil.createIndexes(db); // deleted_contacts table DeletedContactsTableUtil.create(db); // Raw_contacts table db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" + RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + RawContactsColumns.ACCOUNT_ID + " INTEGER REFERENCES " + Tables.ACCOUNTS + "(" + AccountsColumns._ID + ")," + RawContacts.SOURCE_ID + " TEXT," + RawContacts.BACKUP_ID + " TEXT," + RawContacts.RAW_CONTACT_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," + RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," + RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 0," + RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," + RawContacts.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," + RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " + RawContacts.AGGREGATION_MODE_DEFAULT + "," + RawContactsColumns.AGGREGATION_NEEDED + " INTEGER NOT NULL DEFAULT 1," + RawContacts.CUSTOM_RINGTONE + " TEXT," + RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," + RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," + RawContacts.LAST_TIME_CONTACTED + " INTEGER," + RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," + RawContacts.PINNED + " INTEGER NOT NULL DEFAULT " + PinnedPositions.UNPINNED + "," + RawContacts.DISPLAY_NAME_PRIMARY + " TEXT," + RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT," + RawContacts.DISPLAY_NAME_SOURCE + " INTEGER NOT NULL DEFAULT " + DisplayNameSources.UNDEFINED + "," + RawContacts.PHONETIC_NAME + " TEXT," + // TODO: PHONETIC_NAME_STYLE should be INTEGER. There is a // mismatch between how the column is created here (TEXT) and // how it is created in upgradeToVersion205 (INTEGER). RawContacts.PHONETIC_NAME_STYLE + " TEXT," + RawContacts.SORT_KEY_PRIMARY + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," + RawContactsColumns.PHONEBOOK_LABEL_PRIMARY + " TEXT," + RawContactsColumns.PHONEBOOK_BUCKET_PRIMARY + " INTEGER," + RawContacts.SORT_KEY_ALTERNATIVE + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," + RawContactsColumns.PHONEBOOK_LABEL_ALTERNATIVE + " TEXT," + RawContactsColumns.PHONEBOOK_BUCKET_ALTERNATIVE + " INTEGER," + RawContactsColumns.NAME_VERIFIED_OBSOLETE + " INTEGER NOT NULL DEFAULT 0," + RawContacts.SYNC1 + " TEXT, " + RawContacts.SYNC2 + " TEXT, " + RawContacts.SYNC3 + " TEXT, " + RawContacts.SYNC4 + " TEXT " + ");"); db.execSQL("CREATE INDEX raw_contacts_contact_id_index ON " + Tables.RAW_CONTACTS + " (" + RawContacts.CONTACT_ID + ");"); db.execSQL("CREATE INDEX raw_contacts_source_id_account_id_index ON " + Tables.RAW_CONTACTS + " (" + RawContacts.SOURCE_ID + ", " + RawContactsColumns.ACCOUNT_ID + ");"); db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS raw_contacts_backup_id_account_id_index ON " + Tables.RAW_CONTACTS + " (" + RawContacts.BACKUP_ID + ", " + RawContactsColumns.ACCOUNT_ID + ");"); db.execSQL("CREATE TABLE " + Tables.STREAM_ITEMS + " (" + StreamItems._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + StreamItems.RAW_CONTACT_ID + " INTEGER NOT NULL, " + StreamItems.RES_PACKAGE + " TEXT, " + StreamItems.RES_ICON + " TEXT, " + StreamItems.RES_LABEL + " TEXT, " + StreamItems.TEXT + " TEXT, " + StreamItems.TIMESTAMP + " INTEGER NOT NULL, " + StreamItems.COMMENTS + " TEXT, " + StreamItems.SYNC1 + " TEXT, " + StreamItems.SYNC2 + " TEXT, " + StreamItems.SYNC3 + " TEXT, " + StreamItems.SYNC4 + " TEXT, " + "FOREIGN KEY(" + StreamItems.RAW_CONTACT_ID + ") REFERENCES " + Tables.RAW_CONTACTS + "(" + RawContacts._ID + "));"); db.execSQL("CREATE TABLE " + Tables.STREAM_ITEM_PHOTOS + " (" + StreamItemPhotos._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + StreamItemPhotos.STREAM_ITEM_ID + " INTEGER NOT NULL, " + StreamItemPhotos.SORT_INDEX + " INTEGER, " + StreamItemPhotos.PHOTO_FILE_ID + " INTEGER NOT NULL, " + StreamItemPhotos.SYNC1 + " TEXT, " + StreamItemPhotos.SYNC2 + " TEXT, " + StreamItemPhotos.SYNC3 + " TEXT, " + StreamItemPhotos.SYNC4 + " TEXT, " + "FOREIGN KEY(" + StreamItemPhotos.STREAM_ITEM_ID + ") REFERENCES " + Tables.STREAM_ITEMS + "(" + StreamItems._ID + "));"); db.execSQL("CREATE TABLE " + Tables.PHOTO_FILES + " (" + PhotoFiles._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + PhotoFiles.HEIGHT + " INTEGER NOT NULL, " + PhotoFiles.WIDTH + " INTEGER NOT NULL, " + PhotoFiles.FILESIZE + " INTEGER NOT NULL);"); // TODO readd the index and investigate a controlled use of it // db.execSQL("CREATE INDEX raw_contacts_agg_index ON " + Tables.RAW_CONTACTS + " (" + // RawContactsColumns.AGGREGATION_NEEDED + // ");"); // Package name mapping table db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" + PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + PackagesColumns.PACKAGE + " TEXT NOT NULL" + ");"); // Mimetype mapping table db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" + MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + MimetypesColumns.MIMETYPE + " TEXT NOT NULL" + ");"); // Mimetype table requires an index on mime type db.execSQL("CREATE UNIQUE INDEX mime_type ON " + Tables.MIMETYPES + " (" + MimetypesColumns.MIMETYPE + ");"); // Public generic data table db.execSQL("CREATE TABLE " + Tables.DATA + " (" + Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," + DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," + Data.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," + Data.HASH_ID + " TEXT," + Data.IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," + Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," + Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," + Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," + Data.DATA1 + " TEXT," + Data.DATA2 + " TEXT," + Data.DATA3 + " TEXT," + Data.DATA4 + " TEXT," + Data.DATA5 + " TEXT," + Data.DATA6 + " TEXT," + Data.DATA7 + " TEXT," + Data.DATA8 + " TEXT," + Data.DATA9 + " TEXT," + Data.DATA10 + " TEXT," + Data.DATA11 + " TEXT," + Data.DATA12 + " TEXT," + Data.DATA13 + " TEXT," + Data.DATA14 + " TEXT," + Data.DATA15 + " TEXT," + Data.SYNC1 + " TEXT, " + Data.SYNC2 + " TEXT, " + Data.SYNC3 + " TEXT, " + Data.SYNC4 + " TEXT, " + Data.CARRIER_PRESENCE + " INTEGER NOT NULL DEFAULT 0 " + ");"); db.execSQL("CREATE INDEX data_raw_contact_id ON " + Tables.DATA + " (" + Data.RAW_CONTACT_ID + ");"); /** * For email lookup and similar queries. */ db.execSQL("CREATE INDEX data_mimetype_data1_index ON " + Tables.DATA + " (" + DataColumns.MIMETYPE_ID + "," + Data.DATA1 + ");"); /** * For contact backup restore queries. */ db.execSQL("CREATE INDEX IF NOT EXISTS data_hash_id_index ON " + Tables.DATA + " (" + Data.HASH_ID + ");"); // Private phone numbers table used for lookup db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" + PhoneLookupColumns.DATA_ID + " INTEGER REFERENCES data(_id) NOT NULL," + PhoneLookupColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," + PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," + PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" + ");"); db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" + PhoneLookupColumns.NORMALIZED_NUMBER + "," + PhoneLookupColumns.RAW_CONTACT_ID + "," + PhoneLookupColumns.DATA_ID + ");"); db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" + PhoneLookupColumns.MIN_MATCH + "," + PhoneLookupColumns.RAW_CONTACT_ID + "," + PhoneLookupColumns.DATA_ID + ");"); db.execSQL("CREATE INDEX phone_lookup_data_id_min_match_index ON " + Tables.PHONE_LOOKUP + " (" + PhoneLookupColumns.DATA_ID + ", " + PhoneLookupColumns.MIN_MATCH + ");"); // Private name/nickname table used for lookup. db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" + NameLookupColumns.DATA_ID + " INTEGER REFERENCES data(_id) NOT NULL," + NameLookupColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," + NameLookupColumns.NORMALIZED_NAME + " TEXT NOT NULL," + NameLookupColumns.NAME_TYPE + " INTEGER NOT NULL," + "PRIMARY KEY (" + NameLookupColumns.DATA_ID + ", " + NameLookupColumns.NORMALIZED_NAME + ", " + NameLookupColumns.NAME_TYPE + ")" + ");"); db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" + NameLookupColumns.RAW_CONTACT_ID + ");"); db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" + NicknameLookupColumns.NAME + " TEXT," + NicknameLookupColumns.CLUSTER + " TEXT" + ");"); db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" + NicknameLookupColumns.NAME + ", " + NicknameLookupColumns.CLUSTER + ");"); // Groups table. db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" + Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," + GroupsColumns.ACCOUNT_ID + " INTEGER REFERENCES " + Tables.ACCOUNTS + "(" + AccountsColumns._ID + ")," + Groups.SOURCE_ID + " TEXT," + Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," + Groups.DIRTY + " INTEGER NOT NULL DEFAULT 0," + Groups.TITLE + " TEXT," + Groups.TITLE_RES + " INTEGER," + Groups.NOTES + " TEXT," + Groups.SYSTEM_ID + " TEXT," + Groups.DELETED + " INTEGER NOT NULL DEFAULT 0," + Groups.GROUP_VISIBLE + " INTEGER NOT NULL DEFAULT 0," + Groups.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1," + Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0," + Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0," + Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," + Groups.SYNC1 + " TEXT, " + Groups.SYNC2 + " TEXT, " + Groups.SYNC3 + " TEXT, " + Groups.SYNC4 + " TEXT " + ");"); db.execSQL("CREATE INDEX groups_source_id_account_id_index ON " + Tables.GROUPS + " (" + Groups.SOURCE_ID + ", " + GroupsColumns.ACCOUNT_ID + ");"); db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" + AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + AggregationExceptions.TYPE + " INTEGER NOT NULL, " + AggregationExceptions.RAW_CONTACT_ID1 + " INTEGER REFERENCES raw_contacts(_id), " + AggregationExceptions.RAW_CONTACT_ID2 + " INTEGER REFERENCES raw_contacts(_id)" + ");"); db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " + Tables.AGGREGATION_EXCEPTIONS + " (" + AggregationExceptions.RAW_CONTACT_ID1 + ", " + AggregationExceptions.RAW_CONTACT_ID2 + ");"); db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " + Tables.AGGREGATION_EXCEPTIONS + " (" + AggregationExceptions.RAW_CONTACT_ID2 + ", " + AggregationExceptions.RAW_CONTACT_ID1 + ");"); db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.SETTINGS + " (" + Settings.ACCOUNT_NAME + " STRING NOT NULL," + Settings.ACCOUNT_TYPE + " STRING NOT NULL," + Settings.DATA_SET + " STRING," + Settings.UNGROUPED_VISIBLE + " INTEGER NOT NULL DEFAULT 0," + Settings.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1" + ");"); db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" + Contacts._ID + " INTEGER PRIMARY KEY" + ");"); db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" + Contacts._ID + " INTEGER PRIMARY KEY" + ");"); // The table for recent calls is here so we can do table joins on people, phones, and // calls all in one place. // NOTE: When adding a new column to Tables.CALLS, make sure to also add it to // CallLogProvider.CALL_LOG_SYNC_PROJECTION, if it is a column that should be copied to // the call log of secondary users. db.execSQL("CREATE TABLE " + Tables.CALLS + " (" + Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + Calls.NUMBER + " TEXT," + Calls.NUMBER_PRESENTATION + " INTEGER NOT NULL DEFAULT " + Calls.PRESENTATION_ALLOWED + "," + Calls.DATE + " INTEGER," + Calls.DURATION + " INTEGER," + Calls.DATA_USAGE + " INTEGER," + Calls.TYPE + " INTEGER," + Calls.FEATURES + " INTEGER NOT NULL DEFAULT 0," + Calls.PHONE_ACCOUNT_COMPONENT_NAME + " TEXT," + Calls.PHONE_ACCOUNT_ID + " TEXT," + Calls.PHONE_ACCOUNT_ADDRESS + " TEXT," + Calls.PHONE_ACCOUNT_HIDDEN + " INTEGER NOT NULL DEFAULT 0," + Calls.SUB_ID + " INTEGER DEFAULT -1," + Calls.NEW + " INTEGER," + Calls.CACHED_NAME + " TEXT," + Calls.CACHED_NUMBER_TYPE + " INTEGER," + Calls.CACHED_NUMBER_LABEL + " TEXT," + Calls.COUNTRY_ISO + " TEXT," + Calls.VOICEMAIL_URI + " TEXT," + Calls.IS_READ + " INTEGER," + Calls.GEOCODED_LOCATION + " TEXT," + Calls.CACHED_LOOKUP_URI + " TEXT," + Calls.CACHED_MATCHED_NUMBER + " TEXT," + Calls.CACHED_NORMALIZED_NUMBER + " TEXT," + Calls.CACHED_PHOTO_ID + " INTEGER NOT NULL DEFAULT 0," + Calls.CACHED_PHOTO_URI + " TEXT," + Calls.CACHED_FORMATTED_NUMBER + " TEXT," + Voicemails._DATA + " TEXT," + Voicemails.HAS_CONTENT + " INTEGER," + Voicemails.MIME_TYPE + " TEXT," + Voicemails.SOURCE_DATA + " TEXT," + Voicemails.SOURCE_PACKAGE + " TEXT," + Voicemails.TRANSCRIPTION + " TEXT," + Voicemails.STATE + " INTEGER," + Voicemails.DIRTY + " INTEGER NOT NULL DEFAULT 0," + Voicemails.DELETED + " INTEGER NOT NULL DEFAULT 0" + ");"); // Voicemail source status table. db.execSQL("CREATE TABLE " + Tables.VOICEMAIL_STATUS + " (" + VoicemailContract.Status._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + VoicemailContract.Status.SOURCE_PACKAGE + " TEXT UNIQUE NOT NULL," + VoicemailContract.Status.PHONE_ACCOUNT_COMPONENT_NAME + " TEXT," + VoicemailContract.Status.PHONE_ACCOUNT_ID + " TEXT," + VoicemailContract.Status.SETTINGS_URI + " TEXT," + VoicemailContract.Status.VOICEMAIL_ACCESS_URI + " TEXT," + VoicemailContract.Status.CONFIGURATION_STATE + " INTEGER," + VoicemailContract.Status.DATA_CHANNEL_STATE + " INTEGER," + VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE + " INTEGER" + ");"); db.execSQL("CREATE TABLE " + Tables.STATUS_UPDATES + " (" + StatusUpdatesColumns.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," + StatusUpdates.STATUS + " TEXT," + StatusUpdates.STATUS_TIMESTAMP + " INTEGER," + StatusUpdates.STATUS_RES_PACKAGE + " TEXT, " + StatusUpdates.STATUS_LABEL + " INTEGER, " + StatusUpdates.STATUS_ICON + " INTEGER" + ");"); createDirectoriesTable(db); createSearchIndexTable(db, false /* we build stats table later */); db.execSQL("CREATE TABLE " + Tables.DATA_USAGE_STAT + "(" + DataUsageStatColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + DataUsageStatColumns.DATA_ID + " INTEGER NOT NULL, " + DataUsageStatColumns.USAGE_TYPE_INT + " INTEGER NOT NULL DEFAULT 0, " + DataUsageStatColumns.TIMES_USED + " INTEGER NOT NULL DEFAULT 0, " + DataUsageStatColumns.LAST_TIME_USED + " INTERGER NOT NULL DEFAULT 0, " + "FOREIGN KEY(" + DataUsageStatColumns.DATA_ID + ") REFERENCES " + Tables.DATA + "(" + Data._ID + ")" + ");"); db.execSQL("CREATE UNIQUE INDEX data_usage_stat_index ON " + Tables.DATA_USAGE_STAT + " (" + DataUsageStatColumns.DATA_ID + ", " + DataUsageStatColumns.USAGE_TYPE_INT + ");"); db.execSQL("CREATE TABLE " + Tables.PRE_AUTHORIZED_URIS + " ("+ PreAuthorizedUris._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + PreAuthorizedUris.URI + " STRING NOT NULL, " + PreAuthorizedUris.EXPIRATION + " INTEGER NOT NULL DEFAULT 0);"); // When adding new tables, be sure to also add size-estimates in updateSqliteStats createContactsViews(db); createGroupsView(db); createContactsTriggers(db); createContactsIndexes(db, false /* we build stats table later */); loadNicknameLookupTable(db); // Set sequence starts. initializeAutoIncrementSequences(db); // Add the legacy API support views, etc. LegacyApiSupport.createDatabase(db); if (mDatabaseOptimizationEnabled) { // This will create a sqlite_stat1 table that is used for query optimization db.execSQL("ANALYZE;"); updateSqliteStats(db); } ContentResolver.requestSync(null /* all accounts */, ContactsContract.AUTHORITY, new Bundle()); // Only send broadcasts for regular contacts db. if (dbForProfile() == 0) { final Intent dbCreatedIntent = new Intent( ContactsContract.Intents.CONTACTS_DATABASE_CREATED); dbCreatedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcast(dbCreatedIntent, android.Manifest.permission.READ_CONTACTS); } }
db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," + Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," + Contacts.PHOTO_FILE_ID + " INTEGER REFERENCES photo_files(_id)," + Contacts.CUSTOM_RINGTONE + " TEXT," + Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," + Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," + Contacts.LAST_TIME_CONTACTED + " INTEGER," + Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," + Contacts.PINNED + " INTEGER NOT NULL DEFAULT " + PinnedPositions.UNPINNED + "," + Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," + Contacts.LOOKUP_KEY + " TEXT," + ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)," + Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " INTEGER" + ");");
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"外键约束,contacts表中字段NAME_RAW_CONTACT_ID为raw_contacts表的主键,另外外键约束的类似
Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," + Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," + Contacts.PHOTO_FILE_ID + " INTEGER REFERENCES photo_files(_id)," +
为data表创建触发器,如果raw_contact表中某条数据被删除,自动删除data表中对应的数据
db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_deleted;"); db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted " + " BEFORE DELETE ON " + Tables.RAW_CONTACTS + " BEGIN " + " DELETE FROM " + Tables.DATA + " WHERE " + Data.RAW_CONTACT_ID + "=OLD." + RawContacts._ID + ";" + " DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + " WHERE " + AggregationExceptions.RAW_CONTACT_ID1 + "=OLD." + RawContacts._ID + " OR " + AggregationExceptions.RAW_CONTACT_ID2 + "=OLD." + RawContacts._ID + ";" + " DELETE FROM " + Tables.VISIBLE_CONTACTS + " WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID + " AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID + " )=1;" + " DELETE FROM " + Tables.DEFAULT_DIRECTORY + " WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID + " AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID + " )=1;" + " DELETE FROM " + Tables.CONTACTS + " WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID + " AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID + " )=1;" + " END");
String rawContactsSelect = "SELECT " + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + "," + RawContacts.CONTACT_ID + ", " + RawContacts.AGGREGATION_MODE + ", " + RawContacts.RAW_CONTACT_IS_READ_ONLY + ", " + RawContacts.DELETED + ", " + RawContacts.DISPLAY_NAME_SOURCE + ", " + RawContacts.DISPLAY_NAME_PRIMARY + ", " + RawContacts.DISPLAY_NAME_ALTERNATIVE + ", " + RawContacts.PHONETIC_NAME + ", " + RawContacts.PHONETIC_NAME_STYLE + ", " + RawContacts.SORT_KEY_PRIMARY + ", " + RawContactsColumns.PHONEBOOK_LABEL_PRIMARY + ", " + RawContactsColumns.PHONEBOOK_BUCKET_PRIMARY + ", " + RawContacts.SORT_KEY_ALTERNATIVE + ", " + RawContactsColumns.PHONEBOOK_LABEL_ALTERNATIVE + ", " + RawContactsColumns.PHONEBOOK_BUCKET_ALTERNATIVE + ", " + dbForProfile() + " AS " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + ", " + rawContactOptionColumns + ", " + syncColumns + " FROM " + Tables.RAW_CONTACTS + " JOIN " + Tables.ACCOUNTS + " ON (" + RawContactsColumns.CONCRETE_ACCOUNT_ID + "=" + AccountsColumns.CONCRETE_ID + ")"; db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS + " AS " + rawContactsSelect);
在NAME_LOOKUP表中的raw_contact_id列上创建名为name_lookup_raw_contact_id_index的索引
db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" + NameLookupColumns.RAW_CONTACT_ID + ");");
在联系人中使用数据库的时候,一般都是通过ContentProvider来操作contact2.db里的数据,在ContactsProvider2中定义了操作不同表的uri,在contentProvider中根据不同的uri来操作不同的表
static { // Contacts URI matching table final UriMatcher matcher = sUriMatcher; // DO NOT use constants such as Contacts.CONTENT_URI here. This is the only place // where one can see all supported URLs at a glance, and using constants will reduce // readability. matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", AGGREGATION_SUGGESTIONS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", AGGREGATION_SUGGESTIONS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo", CONTACTS_ID_DISPLAY_PHOTO); // Special URIs that refer to contact pictures in the corp CP2. matcher.addURI(ContactsContract.AUTHORITY, "contacts_corp/#/photo", CONTACTS_ID_PHOTO_CORP); matcher.addURI(ContactsContract.AUTHORITY, "contacts_corp/#/display_photo", CONTACTS_ID_DISPLAY_PHOTO_CORP); matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", CONTACTS_ID_STREAM_ITEMS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/photo", CONTACTS_LOOKUP_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", CONTACTS_LOOKUP_ID_DATA); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/photo", CONTACTS_LOOKUP_ID_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", CONTACTS_LOOKUP_DISPLAY_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/display_photo", CONTACTS_LOOKUP_ID_DISPLAY_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", CONTACTS_LOOKUP_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", CONTACTS_LOOKUP_ID_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", CONTACTS_LOOKUP_STREAM_ITEMS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", CONTACTS_LOOKUP_ID_STREAM_ITEMS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", CONTACTS_AS_MULTI_VCARD); matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", CONTACTS_STREQUENT_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); matcher.addURI(ContactsContract.AUTHORITY, "contacts/frequent", CONTACTS_FREQUENT); matcher.addURI(ContactsContract.AUTHORITY, "contacts/delete_usage", CONTACTS_DELETE_USAGE); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_ID_DATA); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/display_photo", RAW_CONTACTS_ID_DISPLAY_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ID_ENTITY); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items", RAW_CONTACTS_ID_STREAM_ITEMS); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items/#", RAW_CONTACTS_ID_STREAM_ITEMS_ID); matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities_corp", RAW_CONTACT_ENTITIES_CORP); matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); matcher.addURI(ContactsContract.AUTHORITY, "data_enterprise/phones", PHONES_ENTERPRISE); matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup_enterprise", EMAILS_LOOKUP_ENTERPRISE); matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup_enterprise/*", EMAILS_LOOKUP_ENTERPRISE); matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); /** "*" is in CSV form with data IDs ("123,456,789") */ matcher.addURI(ContactsContract.AUTHORITY, "data/usagefeedback/*", DATA_USAGE_FEEDBACK_ID); matcher.addURI(ContactsContract.AUTHORITY, "data/callables/", CALLABLES); matcher.addURI(ContactsContract.AUTHORITY, "data/callables/#", CALLABLES_ID); matcher.addURI(ContactsContract.AUTHORITY, "data/callables/filter", CALLABLES_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "data/callables/filter/*", CALLABLES_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "data/contactables/", CONTACTABLES); matcher.addURI(ContactsContract.AUTHORITY, "data/contactables/filter", CONTACTABLES_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "data/contactables/filter/*", CONTACTABLES_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", SYNCSTATE_ID); matcher.addURI(ContactsContract.AUTHORITY, "profile/" + SyncStateContentProviderHelper.PATH, PROFILE_SYNCSTATE); matcher.addURI(ContactsContract.AUTHORITY, "profile/" + SyncStateContentProviderHelper.PATH + "/#", PROFILE_SYNCSTATE_ID); matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup_enterprise/*", PHONE_LOOKUP_ENTERPRISE); matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", AGGREGATION_EXCEPTIONS); matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", AGGREGATION_EXCEPTION_ID); matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGESTIONS); matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGESTIONS); matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", SEARCH_SHORTCUT); matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); matcher.addURI(ContactsContract.AUTHORITY, "profile", PROFILE); matcher.addURI(ContactsContract.AUTHORITY, "profile/entities", PROFILE_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "profile/data", PROFILE_DATA); matcher.addURI(ContactsContract.AUTHORITY, "profile/data/#", PROFILE_DATA_ID); matcher.addURI(ContactsContract.AUTHORITY, "profile/photo", PROFILE_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "profile/display_photo", PROFILE_DISPLAY_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "profile/as_vcard", PROFILE_AS_VCARD); matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts", PROFILE_RAW_CONTACTS); matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#", PROFILE_RAW_CONTACTS_ID); matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/data", PROFILE_RAW_CONTACTS_ID_DATA); matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/entity", PROFILE_RAW_CONTACTS_ID_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "profile/status_updates", PROFILE_STATUS_UPDATES); matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contact_entities", PROFILE_RAW_CONTACT_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "stream_items", STREAM_ITEMS); matcher.addURI(ContactsContract.AUTHORITY, "stream_items/photo", STREAM_ITEMS_PHOTOS); matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#", STREAM_ITEMS_ID); matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo", STREAM_ITEMS_ID_PHOTOS); matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo/#", STREAM_ITEMS_ID_PHOTOS_ID); matcher.addURI(ContactsContract.AUTHORITY, "stream_items_limit", STREAM_ITEMS_LIMIT); matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", DISPLAY_PHOTO_ID); matcher.addURI(ContactsContract.AUTHORITY, "photo_dimensions", PHOTO_DIMENSIONS); matcher.addURI(ContactsContract.AUTHORITY, "deleted_contacts", DELETED_CONTACTS); matcher.addURI(ContactsContract.AUTHORITY, "deleted_contacts/#", DELETED_CONTACTS_ID); }
在Contacts中,有时候看到查询的uri明明是对应raw_contacts表,但真在在查询数据库的时候却是查询view_raw_contacts里的数据
Cursor cursor = mContentResolver.query( RawContacts.CONTENT_URI, PROJECTION_FILTERED_MEMBERS, accountClause + " AND (" + RawContacts.DISPLAY_NAME_PRIMARY + " LIKE ? OR " + RawContacts.DISPLAY_NAME_ALTERNATIVE + " LIKE ? )", args, RawContacts.DISPLAY_NAME_PRIMARY + " COLLATE LOCALIZED ASC");
RawContacts.CONTENT_URI定义如下:
/** * The content:// style URI for this table, which requests a directory of * raw contact rows matching the selection criteria. */ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts");
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return query(uri, projection, selection, selectionArgs, sortOrder, null); } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { if (VERBOSE_LOGGING) { Log.v(TAG, "query: uri=" + uri + " projection=" + Arrays.toString(projection) + " selection=[" + selection + "] args=" + Arrays.toString(selectionArgs) + " order=[" + sortOrder + "] CPID=" + Binder.getCallingPid() + " User=" + UserUtils.getCurrentUserHandle(getContext())); } waitForAccess(mReadAccessLatch); // Query the profile DB if appropriate. if (mapsToProfileDb(uri)) { switchToProfileMode(); return mProfileProvider.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); } // Otherwise proceed with a normal query against the contacts DB. switchToContactMode(); String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); final long directoryId = (directory == null ? -1 : (directory.equals("0") ? Directory.DEFAULT : (directory.equals("1") ? Directory.LOCAL_INVISIBLE : Long.MIN_VALUE))); if (directoryId > Long.MIN_VALUE) { final Cursor cursor = queryLocal(uri, projection, selection, selectionArgs, sortOrder, directoryId, cancellationSignal); return addSnippetExtrasToCursor(uri, cursor); } DirectoryInfo directoryInfo = getDirectoryAuthority(directory); if (directoryInfo == null) { Log.e(TAG, "Invalid directory ID: " + uri); return null; } Builder builder = new Uri.Builder(); builder.scheme(ContentResolver.SCHEME_CONTENT); builder.authority(directoryInfo.authority); builder.encodedPath(uri.getEncodedPath()); if (directoryInfo.accountName != null) { builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); } if (directoryInfo.accountType != null) { builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); } String limit = getLimit(uri); if (limit != null) { builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); } Uri directoryUri = builder.build(); if (projection == null) { projection = getDefaultProjection(uri); } Cursor cursor; try { cursor = getContext().getContentResolver().query( directoryUri, projection, selection, selectionArgs, sortOrder); if (cursor == null) { return null; } } catch (RuntimeException e) { Log.w(TAG, "Directory query failed: uri=" + uri, e); return null; } // Load the cursor contents into a memory cursor (backed by a cursor window) and close the // underlying cursor. try { MemoryCursor memCursor = new MemoryCursor(null, cursor.getColumnNames()); memCursor.fillFromCursor(cursor); return memCursor; } finally { cursor.close(); } }
protected Cursor queryLocal(final Uri uri, final String[] projection, String selection, String[] selectionArgs, String sortOrder, final long directoryId, final CancellationSignal cancellationSignal) { final SQLiteDatabase db = mDbHelper.get().getReadableDatabase(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); String groupBy = null; String having = null; String limit = getLimit(uri); boolean snippetDeferred = false; // The expression used in bundleLetterCountExtras() to get count. String addressBookIndexerCountExpression = null; final int match = sUriMatcher.match(uri); switch (match) { case SYNCSTATE: case PROFILE_SYNCSTATE: return mDbHelper.get().getSyncState().query(db, projection, selection, selectionArgs, sortOrder); ...... case RAW_CONTACTS: case PROFILE_RAW_CONTACTS: { setTablesAndProjectionMapForRawContacts(qb, uri); break; } ....... }
在setTablesAndProjectionMapForRawContacts 设置要查询的表和字段
private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { StringBuilder sb = new StringBuilder(); sb.append(Views.RAW_CONTACTS); qb.setTables(sb.toString()); //设置查询的表为raw_contacts的视图表 qb.setProjectionMap(sRawContactsProjectionMap); appendAccountIdFromParameter(qb, uri); }