public void bindView(Context context, View view, Cursor c) {
      final RecentCallsListItemViews views = (RecentCallsListItemViews) view.getTag();

      String number = c.getString(NUMBER_COLUMN_INDEX);
      String formattedNumber = null;
      String callerName = c.getString(CALLER_NAME_COLUMN_INDEX);
      int callerNumberType = c.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
      String callerNumberLabel = c.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);

      // Store away the number so we can call it directly if you click on the call icon
      views.callView.setTag(number);

      // Lookup contacts with this number
      ContactInfo info = mContactInfo.get(number);
      if (info == null) {
        // Mark it as empty and queue up a request to find the name
        // The db request should happen on a non-UI thread
        info = ContactInfo.EMPTY;
        mContactInfo.put(number, info);
        enqueueRequest(number, c.getPosition(), callerName, callerNumberType, callerNumberLabel);
      } else if (info != ContactInfo.EMPTY) { // Has been queried
        // Check if any data is different from the data cached in the
        // calls db. If so, queue the request so that we can update
        // the calls db.
        if (!TextUtils.equals(info.name, callerName)
            || info.type != callerNumberType
            || !TextUtils.equals(info.label, callerNumberLabel)) {
          // Something is amiss, so sync up.
          enqueueRequest(number, c.getPosition(), callerName, callerNumberType, callerNumberLabel);
        }

        // Format and cache phone number for found contact
        if (info.formattedNumber == null) {
          info.formattedNumber = formatPhoneNumber(info.number);
        }
        formattedNumber = info.formattedNumber;
      }

      String name = info.name;
      int ntype = info.type;
      String label = info.label;
      // If there's no name cached in our hashmap, but there's one in the
      // calls db, use the one in the calls db. Otherwise the name in our
      // hashmap is more recent, so it has precedence.
      if (TextUtils.isEmpty(name) && !TextUtils.isEmpty(callerName)) {
        name = callerName;
        ntype = callerNumberType;
        label = callerNumberLabel;

        // Format the cached call_log phone number
        formattedNumber = formatPhoneNumber(number);
      }
      // Set the text lines and call icon.
      // Assumes the call back feature is on most of the
      // time. For private and unknown numbers: hide it.
      views.callView.setVisibility(View.VISIBLE);

      if (!TextUtils.isEmpty(name)) {
        views.line1View.setText(name);
        views.labelView.setVisibility(View.VISIBLE);

        // "type" and "label" are currently unused for SIP addresses.
        CharSequence numberLabel = null;
        if (!PhoneNumberUtils.isUriNumber(number)) {
          numberLabel = Phone.getDisplayLabel(context, ntype, label, mLabelArray);
        }
        views.numberView.setVisibility(View.VISIBLE);
        views.numberView.setText(formattedNumber);
        if (!TextUtils.isEmpty(numberLabel)) {
          views.labelView.setText(numberLabel);
          views.labelView.setVisibility(View.VISIBLE);

          // Zero out the numberView's left margin (see below)
          ViewGroup.MarginLayoutParams numberLP =
              (ViewGroup.MarginLayoutParams) views.numberView.getLayoutParams();
          numberLP.leftMargin = 0;
          views.numberView.setLayoutParams(numberLP);
        } else {
          // There's nothing to display in views.labelView, so hide it.
          // We can't set it to View.GONE, since it's the anchor for
          // numberView in the RelativeLayout, so make it INVISIBLE.
          //   Also, we need to manually *subtract* some left margin from
          // numberView to compensate for the right margin built in to
          // labelView (otherwise the number will be indented by a very
          // slight amount).
          //   TODO: a cleaner fix would be to contain both the label and
          // number inside a LinearLayout, and then set labelView *and*
          // its padding to GONE when there's no label to display.
          views.labelView.setText(null);
          views.labelView.setVisibility(View.INVISIBLE);

          ViewGroup.MarginLayoutParams labelLP =
              (ViewGroup.MarginLayoutParams) views.labelView.getLayoutParams();
          ViewGroup.MarginLayoutParams numberLP =
              (ViewGroup.MarginLayoutParams) views.numberView.getLayoutParams();
          // Equivalent to setting android:layout_marginLeft in XML
          numberLP.leftMargin = -labelLP.rightMargin;
          views.numberView.setLayoutParams(numberLP);
        }
      } else {
        if (number.equals(CallerInfo.UNKNOWN_NUMBER)) {
          number = getString(R.string.unknown);
          views.callView.setVisibility(View.INVISIBLE);
        } else if (number.equals(CallerInfo.PRIVATE_NUMBER)) {
          number = getString(R.string.private_num);
          views.callView.setVisibility(View.INVISIBLE);
        } else if (number.equals(CallerInfo.PAYPHONE_NUMBER)) {
          number = getString(R.string.payphone);
        } else if (PhoneNumberUtils.extractNetworkPortion(number).equals(mVoiceMailNumber)) {
          number = getString(R.string.voicemail);
        } else {
          // Just a raw number, and no cache, so format it nicely
          number = formatPhoneNumber(number);
        }

        views.line1View.setText(number);
        views.numberView.setVisibility(View.GONE);
        views.labelView.setVisibility(View.GONE);
      }

      long date = c.getLong(DATE_COLUMN_INDEX);

      // Set the date/time field by mixing relative and absolute times.
      int flags = DateUtils.FORMAT_ABBREV_RELATIVE;

      views.dateView.setText(
          DateUtils.getRelativeTimeSpanString(
              date, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, flags));

      if (views.iconView != null) {
        int type = c.getInt(CALL_TYPE_COLUMN_INDEX);
        // Set the icon
        switch (type) {
          case Calls.INCOMING_TYPE:
            views.iconView.setImageDrawable(mDrawableIncoming);
            break;

          case Calls.OUTGOING_TYPE:
            views.iconView.setImageDrawable(mDrawableOutgoing);
            break;

          case Calls.MISSED_TYPE:
            views.iconView.setImageDrawable(mDrawableMissed);
            break;
        }
      }

      // Listen for the first draw
      if (mPreDrawListener == null) {
        mFirst = true;
        mPreDrawListener = this;
        view.getViewTreeObserver().addOnPreDrawListener(this);
      }
    }
Exemple #2
0
  /**
   * getCallerInfo given a Cursor.
   *
   * @param context the context used to retrieve string constants
   * @param contactRef the URI to attach to this CallerInfo object
   * @param cursor the first object in the cursor is used to build the CallerInfo object.
   * @return the CallerInfo which contains the caller id for the given number. The returned
   *     CallerInfo is null if no number is supplied.
   */
  public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) {
    CallerInfo info = new CallerInfo();
    info.photoResource = 0;
    info.phoneLabel = null;
    info.numberType = 0;
    info.numberLabel = null;
    info.cachedPhoto = null;
    info.isCachedPhotoCurrent = false;
    info.contactExists = false;

    if (VDBG) Rlog.v(TAG, "getCallerInfo() based on cursor...");

    if (cursor != null) {
      if (cursor.moveToFirst()) {
        // TODO: photo_id is always available but not taken
        // care of here. Maybe we should store it in the
        // CallerInfo object as well.

        int columnIndex;

        // Look for the name
        columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
        if (columnIndex != -1) {
          info.name = cursor.getString(columnIndex);
        }

        // Look for the number
        columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER);
        if (columnIndex != -1) {
          info.phoneNumber = cursor.getString(columnIndex);
        }

        // Look for the normalized number
        columnIndex = cursor.getColumnIndex(PhoneLookup.NORMALIZED_NUMBER);
        if (columnIndex != -1) {
          info.normalizedNumber = cursor.getString(columnIndex);
        }

        // Look for the label/type combo
        columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL);
        if (columnIndex != -1) {
          int typeColumnIndex = cursor.getColumnIndex(PhoneLookup.TYPE);
          if (typeColumnIndex != -1) {
            info.numberType = cursor.getInt(typeColumnIndex);
            info.numberLabel = cursor.getString(columnIndex);
            info.phoneLabel =
                Phone.getDisplayLabel(context, info.numberType, info.numberLabel).toString();
          }
        }

        // Look for the person_id.
        columnIndex = getColumnIndexForPersonId(contactRef, cursor);
        if (columnIndex != -1) {
          final long contactId = cursor.getLong(columnIndex);
          if (contactId != 0 && !Contacts.isEnterpriseContactId(contactId)) {
            info.contactIdOrZero = contactId;
            if (VDBG) {
              Rlog.v(TAG, "==> got info.contactIdOrZero: " + info.contactIdOrZero);
            }
          }
        } else {
          // No valid columnIndex, so we can't look up person_id.
          Rlog.w(TAG, "Couldn't find contact_id column for " + contactRef);
          // Watch out: this means that anything that depends on
          // person_id will be broken (like contact photo lookups in
          // the in-call UI, for example.)
        }

        // Contact lookupKey
        columnIndex = cursor.getColumnIndex(PhoneLookup.LOOKUP_KEY);
        if (columnIndex != -1) {
          info.lookupKey = cursor.getString(columnIndex);
        }

        // Display photo URI.
        columnIndex = cursor.getColumnIndex(PhoneLookup.PHOTO_URI);
        if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
          info.contactDisplayPhotoUri = Uri.parse(cursor.getString(columnIndex));
        } else {
          info.contactDisplayPhotoUri = null;
        }

        // look for the custom ringtone, create from the string stored
        // in the database.
        columnIndex = cursor.getColumnIndex(PhoneLookup.CUSTOM_RINGTONE);
        if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
          info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex));
        } else {
          info.contactRingtoneUri = null;
        }

        // look for the send to voicemail flag, set it to true only
        // under certain circumstances.
        columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL);
        info.shouldSendToVoicemail = (columnIndex != -1) && ((cursor.getInt(columnIndex)) == 1);
        info.contactExists = true;
      }
      cursor.close();
      cursor = null;
    }

    info.needUpdate = false;
    info.name = normalize(info.name);
    info.contactRefUri = contactRef;

    return info;
  }