Android - 来自带有国家代码的号码的联系方式

Posted

技术标签:

【中文标题】Android - 来自带有国家代码的号码的联系方式【英文标题】:Android - Contact from number with Country Code 【发布时间】:2013-04-17 22:18:36 【问题描述】:

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

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,但选择代码几乎相同,所以我不确定为什么它不适用于第二个。

有什么想法吗?

【问题讨论】:

【参考方案1】:

我将此代码用于相同的要求,它返回一个名称 通过从相同的代码返回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;

【讨论】:

这看起来更像我所追求的 - 我的 atm 前面没有代码,但我会检查一下,看看这是否适合我,谢谢 它似乎不适用于印度或俄罗斯号码。例如:联系号码 89997654321 和来自 +79997654321 的来电【参考方案2】:

上个月我遇到了同样的问题,我设法使用谷歌的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;

希望它能解决你的问题。

【讨论】:

【参考方案3】:

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

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

这个登陆页面有很多sn-ps的代码,所以我觉得这里没有必要写任何代码;你应该能够从那里理解它们。

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

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

此库与您相关的功能:

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

isNumberMatch - 获取两个数字是否可以匹配的置信度 一样。

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

【讨论】:

【参考方案4】:

试试这个:Google's library for dealing with phone numbers

【讨论】:

谢谢,这可以帮助我将数字转换为不同的格式,但对于类似不起作用的问题没有帮助。如果有办法让它工作,那将是一个更简单的解决方案,因为我不知道用户保存联系人的确切格式..【参考方案5】:

也许您可以对所有国家/地区代码使用静态变量(数组或其他东西),并使用 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
    

【讨论】:

【参考方案6】:

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

    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);
                
            
        
    

希望对你有帮助...

【讨论】:

【参考方案7】:

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

//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位,希望对您有帮助!!!

【讨论】:

【参考方案8】:

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

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

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);
...

【讨论】:

获取子串不太可靠,因为不同的国家有不同的代码。 我想解决方案之一会奏效。也许您必须在 if 子句中添加第三个或以检查国家/地区代码是否包含 3 个字符(取决于您要提供的国家/地区代码)。

以上是关于Android - 来自带有国家代码的号码的联系方式的主要内容,如果未能解决你的问题,请参考以下文章

Android - 电话号码格式化和删除国家/地区代码

WhatsApp 如何知道我的联系人的国家代码? [关闭]

Xamarin Android,使用带有选择和选择参数的 CursorLoader 获取联系人手机号码

在联系人选取器中获取不正确的联系人号码 - Android

从 android 中的联系人加载器获取电话号码:投影崩溃

sqlite android提取带有电话号码的联系人