/** * Loads data from the content provider, organizes it into {@link RawContactInfo} objects and * returns a sorted list of {@link RawContactInfo}'s. */ private List<RawContactInfo> loadData() { HashMap<Long, RawContactInfo> rawContactInfos = new HashMap<Long, RawContactInfo>(); Uri dataUri = Uri.withAppendedPath(mAggregateUri, Data.CONTENT_DIRECTORY); Cursor cursor = getContext().getContentResolver().query(dataUri, SplitQuery.COLUMNS, null, null, null); try { while (cursor.moveToNext()) { long rawContactId = cursor.getLong(SplitQuery.RAW_CONTACT_ID); RawContactInfo info = rawContactInfos.get(rawContactId); if (info == null) { info = new RawContactInfo(rawContactId); rawContactInfos.put(rawContactId, info); info.accountType = cursor.getString(SplitQuery.ACCOUNT_TYPE); info.dataSet = cursor.getString(SplitQuery.DATA_SET); } String mimetype = cursor.getString(SplitQuery.MIMETYPE); if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) { loadStructuredName(cursor, info); } else if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { loadPhoneNumber(cursor, info); } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) { loadEmail(cursor, info); } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) { loadNickname(cursor, info); } } } finally { cursor.close(); } List<RawContactInfo> list = new ArrayList<RawContactInfo>(rawContactInfos.values()); Collections.sort(list); return list; }
public List<Suggestion> getSuggestions() { ArrayList<Suggestion> list = Lists.newArrayList(); if (mDataCursor != null) { Suggestion suggestion = null; long currentContactId = -1; mDataCursor.moveToPosition(-1); while (mDataCursor.moveToNext()) { long contactId = mDataCursor.getLong(DataQuery.CONTACT_ID); if (contactId != currentContactId) { suggestion = new Suggestion(); suggestion.contactId = contactId; suggestion.name = mDataCursor.getString(DataQuery.DISPLAY_NAME); suggestion.lookupKey = mDataCursor.getString(DataQuery.LOOKUP_KEY); suggestion.rawContacts = Lists.newArrayList(); list.add(suggestion); currentContactId = contactId; } long rawContactId = mDataCursor.getLong(DataQuery.RAW_CONTACT_ID); if (!containsRawContact(suggestion, rawContactId)) { RawContact rawContact = new RawContact(); rawContact.rawContactId = rawContactId; rawContact.accountName = mDataCursor.getString(DataQuery.ACCOUNT_NAME); rawContact.accountType = mDataCursor.getString(DataQuery.ACCOUNT_TYPE); rawContact.dataSet = mDataCursor.getString(DataQuery.DATA_SET); suggestion.rawContacts.add(rawContact); } String mimetype = mDataCursor.getString(DataQuery.MIMETYPE); if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.phoneNumber == null)) { suggestion.phoneNumber = data; } } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.emailAddress == null)) { suggestion.emailAddress = data; } } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) { String data = mDataCursor.getString(DataQuery.DATA1); if (!TextUtils.isEmpty(data)) { suggestion.nickname = data; } } else if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) { long dataId = mDataCursor.getLong(DataQuery.ID); long photoId = mDataCursor.getLong(DataQuery.PHOTO_ID); if (dataId == photoId && !mDataCursor.isNull(DataQuery.PHOTO)) { suggestion.photo = mDataCursor.getBlob(DataQuery.PHOTO); } } } } return list; }
/** Create an action from common {@link Data} elements. */ public DataAction(Context context, String mimeType, DataKind kind, long dataId, Cursor cursor) { mContext = context; mKind = kind; mMimeType = mimeType; // Inflate strings from cursor mAlternate = Constants.MIME_SMS_ADDRESS.equals(mimeType); if (mAlternate && mKind.actionAltHeader != null) { mHeader = mKind.actionAltHeader.inflateUsing(context, cursor); } else if (mKind.actionHeader != null) { mHeader = mKind.actionHeader.inflateUsing(context, cursor); } if (getAsInt(cursor, Data.IS_SUPER_PRIMARY) != 0) { mIsPrimary = true; } if (mKind.actionBody != null) { mBody = mKind.actionBody.inflateUsing(context, cursor); } mDataUri = ContentUris.withAppendedId(TData.CONTENT_URI, dataId); // Handle well-known MIME-types with special care if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) { final String number = getAsString(cursor, Phone.NUMBER); if (!TextUtils.isEmpty(number)) { final Uri callUri = Uri.fromParts(Constants.SCHEME_TEL, number, null); mIntent = new Intent(TIntent.ACTION_CALL_PRIVILEGED, callUri); } } else if (Constants.MIME_SMS_ADDRESS.equals(mimeType)) { final String number = getAsString(cursor, Phone.NUMBER); if (!TextUtils.isEmpty(number)) { final Uri smsUri = Uri.fromParts(Constants.SCHEME_SMSTO, number, null); mIntent = new Intent(TIntent.getACTION_SENDTO(mContext), smsUri); } } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) { final String address = getAsString(cursor, Email.DATA); if (!TextUtils.isEmpty(address)) { final Uri mailUri = Uri.fromParts(Constants.SCHEME_MAILTO, address, null); mIntent = new Intent(TIntent.getACTION_SENDTO(mContext), mailUri); } } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) { final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(getAsString(cursor, Data.MIMETYPE)); if (isEmail || isProtocolValid(cursor)) { final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : getAsInt(cursor, Im.PROTOCOL); if (isEmail) { // Use Google Talk string when using Email, and clear data // Uri so we don't try saving Email as primary. mHeader = context.getText(R.string.chat_gtalk); mDataUri = null; } String host = getAsString(cursor, Im.CUSTOM_PROTOCOL); String data = getAsString(cursor, isEmail ? Email.DATA : Im.DATA); if (protocol != Im.PROTOCOL_CUSTOM) { // Try bringing in a well-known host for specific protocols host = ContactsUtils.lookupProviderNameFromId(protocol); } if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) { final String authority = host.toLowerCase(); final Uri imUri = new Uri.Builder() .scheme(Constants.SCHEME_IMTO) .authority(authority) .appendPath(data) .build(); mIntent = new Intent(TIntent.getACTION_SENDTO(mContext), imUri); } } } if (mIntent == null) { // Otherwise fall back to default VIEW action mIntent = new Intent(TIntent.ACTION_VIEW, mDataUri); } // Always launch as new task, since we're like a launcher mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); }
/** Handle the result from the {@link #TOKEN_DATA} query. */ private void handleData(Cursor cursor) { if (cursor == null) return; if (!isMimeExcluded(Contacts.CONTENT_ITEM_TYPE)) { // Add the profile shortcut action final Action action = new ProfileAction(mContext, mLookupUri); mActions.collect(Contacts.CONTENT_ITEM_TYPE, action); } final DataStatus status = new DataStatus(); final Sources sources = Sources.getInstance(mContext); final ImageView photoView = (ImageView) mHeader.findViewById(R.id.photo); Bitmap photoBitmap = null; while (cursor.moveToNext()) { final long dataId = cursor.getLong(DataQuery._ID); final String accountType = cursor.getString(DataQuery.ACCOUNT_TYPE); final String mimeType = cursor.getString(DataQuery.MIMETYPE); // Handle any social status updates from this row status.possibleUpdate(cursor); // Skip this data item if MIME-type excluded if (isMimeExcluded(mimeType)) continue; // Handle photos included as data row if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) { final int colPhoto = cursor.getColumnIndex(Photo.PHOTO); final byte[] photoBlob = cursor.getBlob(colPhoto); if (photoBlob != null) { photoBitmap = BitmapFactory.decodeByteArray(photoBlob, 0, photoBlob.length); } continue; } final DataKind kind = sources.getKindOrFallback( accountType, mimeType, mContext, ContactsSource.LEVEL_MIMETYPES); if (kind != null) { // Build an action for this data entry, find a mapping to a UI // element, build its summary from the cursor, and collect it // along with all others of this MIME-type. final Action action = new DataAction(mContext, mimeType, kind, dataId, cursor); considerAdd(action, mimeType); } // If phone number, also insert as text message action if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && kind != null) { final Action action = new DataAction(mContext, Constants.MIME_SMS_ADDRESS, kind, dataId, cursor); considerAdd(action, Constants.MIME_SMS_ADDRESS); } // Handle Email rows with presence data as Im entry final boolean hasPresence = !cursor.isNull(DataQuery.PRESENCE); if (hasPresence && Email.CONTENT_ITEM_TYPE.equals(mimeType)) { final DataKind imKind = sources.getKindOrFallback( accountType, Im.CONTENT_ITEM_TYPE, mContext, ContactsSource.LEVEL_MIMETYPES); if (imKind != null) { final Action action = new DataAction(mContext, Im.CONTENT_ITEM_TYPE, imKind, dataId, cursor); considerAdd(action, Im.CONTENT_ITEM_TYPE); } } } if (cursor.moveToLast()) { // Read contact information from last data row final String name = cursor.getString(DataQuery.DISPLAY_NAME); final int presence = cursor.getInt(DataQuery.CONTACT_PRESENCE); final Drawable statusIcon = getPresenceIcon(presence); setHeaderText(R.id.name, name); setHeaderImage(R.id.presence, statusIcon); } if (photoView != null) { // Place photo when discovered in data, otherwise hide photoView.setVisibility(photoBitmap != null ? View.VISIBLE : View.GONE); photoView.setImageBitmap(photoBitmap); } mHasValidSocial = status.isValid(); if (mHasValidSocial && mMode != QuickContact.MODE_SMALL) { // Update status when valid was found setHeaderText(R.id.status, status.getStatus()); setHeaderText(R.id.timestamp, status.getTimestampLabel(mContext)); } // Turn our list of actions into UI elements, starting with common types final Set<String> containedTypes = mActions.keySet(); for (String mimeType : ORDERED_MIMETYPES) { if (containedTypes.contains(mimeType)) { final int index = mTrack.getChildCount() - 1; mTrack.addView(inflateAction(mimeType), index); containedTypes.remove(mimeType); } } // Then continue with remaining MIME-types in alphabetical order final String[] remainingTypes = containedTypes.toArray(new String[containedTypes.size()]); Arrays.sort(remainingTypes); for (String mimeType : remainingTypes) { final int index = mTrack.getChildCount() - 1; mTrack.addView(inflateAction(mimeType), index); } }