12

从传入的短信中检索手机号码时,它会附加国家代码。
现在,由于数据库中的匹配联系人可能不包括国家代码来获取我正在使用的联系人姓名:

public static String getContactName(String number, Context context) {

    try {

        Uri personUri = Uri.withAppendedPath(
            ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number.trim()));
        String selection = PhoneLookup.NUMBER + " LIKE %" + number.trim() + "%";
        Cursor cur = context.getContentResolver().query(personUri,
            new String[] {
            PhoneLookup.DISPLAY_NAME
        },
            selection, null, null);
        if (cur.moveToFirst()) {
            String str = cur.getString(cur.getColumnIndex(PhoneLookup.DISPLAY_NAME));
            cur.close();
            return str;
        }
    } catch (Exception e) {
        //e.printStackTrace();
        return number;
    }
    return number;
}

如果我传入完全匹配或部分匹配,这将非常有效。但是,如果我想获取联系人 ID,我正在使用此代码:

public static Contact getContact(String number, ContentResolver contentResolver) {

    Contact contact = new Contact(-1, number);
    try {
        Uri personUri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(number));
        String selection = ContactsContract.CommonDataKinds.Phone.NUMBER + " LIKE '%" + number + "%'";
        Cursor cur = contentResolver.query(personUri,
            new String[] {
            ContactsContract.CommonDataKinds.Phone.CONTACT_ID, PhoneLookup.DISPLAY_NAME
        },
            selection, null, null);
        if (cur.moveToFirst()) {
            contact = new Contact(Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID))),
                cur.getString(cur.getColumnIndex(PhoneLookup.DISPLAY_NAME)));
        }
        cur.close();
    } catch (Exception e) {}
    return contact;
}

如果数字完全匹配,则此方法非常有效,但如果不是,则不返回任何内容。我需要这种方法来查找联系人的 ID,其中其号码保存为“01111111111”,传入号码为“+441111111111”。尽管他们正在查看不同的 URI,但选择代码几乎相同,所以我不确定为什么它不适用于第二个。

有任何想法吗?

4

8 回答 8

10

我将此代码用于相同的要求,它通过从相同代码返回 contactId 来返回名称。使用它,您的问题将得到解决。

public static String getContactDisplayNameByNumber(String number) {
    Uri uri = Uri.withAppendedPath(
            ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
            Uri.encode(number));
    String name = "?";

    ContentResolver contentResolver = context.getContentResolver();
    Cursor contactLookup = contentResolver.query(uri, new String[] {
            BaseColumns._ID, ContactsContract.PhoneLookup.DISPLAY_NAME },
            null, null, null);

    try {
        if (contactLookup != null && contactLookup.getCount() > 0) {
            contactLookup.moveToNext();
            name = contactLookup.getString(contactLookup
                    .getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
            // String contactId =
            // contactLookup.getString(contactLookup.getColumnIndex(BaseColumns._ID));
        }
    } finally {
        if (contactLookup != null) {
            contactLookup.close();
        }
    }

    return name;
}
于 2013-05-09T13:24:59.677 回答
7

上个月我遇到了同样的问题,我设法使用谷歌的libphonenumber库解决了这个问题。

该问题仅发生在本地/国家电话号码上,因为它们可以在没有国家代码或使用“0”的情况下保存。

例如 :

印度的典型电话号码可以保存为以下格式

  a. +919665123456
  b. 919665123456
  c. 09665123456
  d. 9665123456

以上每一种都是完全有效的格式,只能在印度拨打

但是,如果电话号码不属于您的祖国,则必须使用国家代码强制保存,否则您将无法拨打电话。

ex. 

 a. +1732-757-2923    (US)
 b. +97433-456-789    (Qatar)

因此,如果相关联系人是 ,则确实会出现匹配联系人的问题local/national

这就是libphonenumber图片的来源。使用该库,我们可以提取属于该特定国家的实际国家格式的电话号码。

这是诀窍。首先将接收到的 sms 号码原样传递给 uri,以便在数据库中进行匹配。如果不匹配,则使用 libphonenumber 提取国有化电话号码,然后再次将其作为 uri 传递以进行匹配。( Uri.encode(number))

它在我的情况下有效。

我已经通过以下方式使用它。

public String getContactDisplayNameByNumber(String number) {

    if (number != null && number.length() != 0) {

        String name = lookupNumber(number);

        if (!name.contains(number))
            return name;
        else {

            TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

            String usersCountryISOCode = manager.getNetworkCountryIso();

            PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
            try {
                PhoneNumber phonenUmber = phoneUtil.parse(name,
                        usersCountryISOCode);
                if (phoneUtil.isValidNumber(phonenUmber)) {
                    temp = phoneUtil
                            .getNationalSignificantNumber(phonenUmber);


                    name = lookupNumber(temp);
                    return name;
                }

            } catch (Exception e) {

                e.printStackTrace();

            }
            return number;
        }
    } else {
        return "Invalid Number";
    }
}

private String lookupNumber(String number) {

    uri = Uri.withAppendedPath(
            ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
            Uri.encode(number));
    name = number;

    contentResolver = getContentResolver();
    contactLookup = contentResolver.query(uri, columns, null, null, null);

    try {
        if (contactLookup != null && contactLookup.getCount() > 0) {
            contactLookup.moveToNext();
            name = contactLookup.getString(contactLookup
                    .getColumnIndex(ContactsContract.Data.DISPLAY_NAME));

        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (contactLookup != null) {
            contactLookup.close();
        }
    }

    return name;
}

希望它能解决你的问题。

于 2013-05-09T12:16:38.437 回答
2

对于这类问题,谷歌本身已经为我们提供了专门针对 Android 手机的库。不要使用任何奇怪的代码,看看有经验的开发人员测试过的谷歌官方库。

使用 Google 的libphonenumber库,用于解析、格式化、存储和验证国际电话号码。

这个着陆页上有很多代码片段,所以我认为没有必要在这里编写任何代码;你应该能够从那里理解它们。

http://code.google.com/p/libphonenumber/

他们已经给出了所有资源如何解析如何匹配

该库与您相关的功能:

  • 解析/格式化/验证世界所有国家/地区的电话号码。

  • isNumberMatch - 获取两个数字是否相同的置信度。

  • findNumbers - 在文本输入中查找数字。

于 2013-05-09T13:43:44.033 回答
0

虽然我的解决方案可能看起来很脏,但这可能会奏效。

    String number = "your number";
    ContentResolver contentResolver; // content resolver
    Contact c;
    if (number != null) {
        if (number.charAt(0) == '+') {
            c = getContact(number.substring(1), contentResolver);
            if (c.firstField == -1) {
                c = getContact(number.substring(2), contentResolver);
                if (c.firstField == -1) {
                    c = getContact(number.substring(3), contentResolver);
                }
            }
        } else {
            c = getContact(number, contentResolver);
            if (c.firstField == -1) {
                c = getContact(number.substring(1), contentResolver);
                if (c.firstField == -1) {
                    c = getContact(number.substring(2), contentResolver);
                }
            }
        }
    }

希望能帮助到你...

于 2013-05-08T11:28:23.033 回答
0

我不太确定我是否正确回答了您的问题,但我是这样理解的:您的问题是电话号码可能以两种不同的方式出现。有或没有国家代码。

我认为有两个简单的解决方案。最简单的方法是更改​​收件箱中的读取输入。收件箱将始终包含可以修剪的国家/地区代码。例如

String inboxNo; //the number you've read from the inbox
int length = inboxNo.length     
if ((inboxNo.equals(whatYouAreSearching) || (String withOutCountryCode = "0"+ inboxNo.substring(3,length-1))
...

另一种解决方案可能是您检查数据库条目的第一个字符并进行转换。例如

if(!dataBaseNo.substring(0,1).contanins("+"){
dataBaseNo = "+44" + dataBaseNo.substring(1,length-1);
...
于 2013-05-07T12:41:05.930 回答
0

这种技术适用于我,解析部分数字,通过使用:

//encode the phone number and build the filter URI
Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number.substring(len-9)));

String selection = PhoneLookup.NUMBER + " LIKE %" + number.substring(len-9) + "%";

Cursor cursor = context.getContentResolver().query(contactUri, projection, selection, null, null);

完整示例:

private void getContactDetails(String number) {
    // define the columns you want the query to return
    String[] projection = new String[] {
        PhoneLookup.DISPLAY_NAME,
        PhoneLookup._ID,
        PhoneLookup.LOOKUP_KEY};
    int len = number.length();
    // encode the phone number and build the filter URI
    Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number.substring(len-9)));

    String selection = PhoneLookup.NUMBER + " LIKE %" + number.substring(len-9) + "%";

    Cursor cursor = context.getContentResolver().query(contactUri, projection, selection, null, null);

    if(cursor != null) {
        if (cursor.moveToFirst()) {
            String name = cursor.getString(cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME));
            String lookUpKey = cursor.getString(cursor.getColumnIndex(PhoneLookup.LOOKUP_KEY));
        }
        cursor.close();
    }
}

它解析并匹配数字的最后 10 位数字,希望对您有所帮助!!!

于 2014-03-11T11:09:53.670 回答
0

试试这个:谷歌处理电话号码的图书馆

于 2013-04-24T11:26:54.380 回答
0

也许您可以对所有国家/地区代码使用静态变量(数组或其他东西),并使用 2-pass 方法正确匹配代码。如果添加了国家/地区代码或其他内容,则可以通过更新来刷新此数组,或者如果您需要非常出色,请从在线标准源中提取并从您的应用程序中触发定期更新。

private static int countrycodes[]; // define the entire data here
...
{
...
for(int i=0;i<countrycodes.length;i++){
    //match using regexp or something and flag this for 2nd pass
    }
}
于 2013-05-07T20:11:52.183 回答