效果图

手机号 redis 位图 手机号 位置_正则表达式

手机号 redis 位图 手机号 位置_手机号 redis 位图_02

技术点

  • 数据库的查询操作
  • 正则表达式
  • 监听输入框的输入事件

思路

查询号码归属地的方法有两种:
1.网络查询,通过网上的一些接口,可以查询到JSON数据等

2.本地查询,APK中,自带一个数据库,放置号段对应的地点信息

考虑到用户的使用场景,决定采用本地查询的方式来实现这个功能。

  • 本功能采用的是 小米提供的数据库。
  • 内部有两张表:
  • data1: id:手机号码的前七位 outkey:外键
  • data2: id:对应表1中的外键 location:位置 area:区号

查询手机号码的思路

首先查询出对应的外键:
select outkey from data1 where id = “号码的前七位”

之后根据外键查询位置
select location from data2 where id = “外键的值”

即:
执行SQL语句:
select location from data2 where id = (select outkey from data1 where id = “号码的前七位” )
注意:当一个SQL语句中嵌套另一个SQL语句的时候,要用括号括起来。

查询固定电话的思路:

判断号码是否以0开头,且长度大于10
如果是,则截取号码的第2-3位,进行数据库查询;
如果没有,则截取号码的2-4位进行数据库查询;
如果还没有,那就直接返回号码

select location from data2 where area=”截取的那部分数字”

同时,还要通过正则表达式对数据进行“格式化”
1) 以^开头
2)[xyz] 确定该位置的数据一定为x/y/z中的一个
3)[x-z]表示该位置的值为x-z
4)\d 表示0-9数字
5){n} 显示多少次
6)以$ 结尾

则,手机号的正则表达式:
^1[3458]\d{9}$

复制数据到手机中

数据库放在raw文件夹内,在Splash页面运行的时候,复制到手机内存中。具体操作:

private void copyDatabaseToMobile()
    {
        //1.把raw文件转换成字节流
        InputStream is = SplashActivity.this.getResources().openRawResource(R.raw.address);
        //2.复制数据到内存中
        File file = new File(QueryNumberUtils.DATABASE_PATH);
        try
        {
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buffer = new  byte[1024];
            int length = -1;
            while((length = is.read(buffer)) != -1)
            {
                fos.write(buffer,0,length);
            }
            fos.close();
            is.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

让”结果文本”随着输入框内容的改变而改变:

addTextChangedListener() 方法,参数为 TextWacher的示例,由于TextWatcher是接口,所以以匿名内部类的形式创建,并重写其中的三个方法beforeTextChanged、onTextChanged、afterTextChanged

其中,主要重写onTextChanged,让它在回调的之后执行查询地址操作。

最终实现代码:

mEtNumber.addTextChangedListener(new TextWatcher()
{

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    //文字内容发生变化时进行的操作
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if(s != null && s.length() >= 3)
        {           mTvResult.setText(QueryNumberUtils.getLocationByNumber(s.toString()));
        }
        if(s.length() <= 2)
        {
            mTvResult.setText("");
        }
     }

        @Override
        public void afterTextChanged(Editable s) {}
});

查询功能的代码:

public static String getLocationByNumber(String number)
    {
        String location = null;
        //判断格式是否为手机号码
        String regular = "^1[34568]\\d{9}$";
        if(number.matches(regular))
        {
            //是手机号码
            location = queryPhoneNumber(number);
        }
        else
        {
            location = queryOtherNumber(number);
        }
        return location;
    }

    //查询手机号码归属地的操作
    private static String queryPhoneNumber(String number)
    {
        SQLiteDatabase sdb = SQLiteDatabase.openDatabase(DATABASE_PATH,null,SQLiteDatabase.OPEN_READONLY);
        String location = null;
        Cursor cursor = sdb.rawQuery("select location from data2 where id = (select outkey from data1 where id = ?)",new String[]{number.substring(0,7)});
        while(cursor.moveToNext())
        {
            location = cursor.getString(0);
        }
        if(location == null)
        {
            location = number;
        }
        cursor.close();
        return location;
    }

    //查询其他号码归属地的操作
    private static String queryOtherNumber(String number)
    {
        SQLiteDatabase sdb = SQLiteDatabase.openDatabase(DATABASE_PATH,null,SQLiteDatabase.OPEN_READONLY);
        String location = null;
        switch(number.length())
        {
            case 3:
                //类似110 119 120之类的特殊电话
                location = "特殊电话";
                break;
            case 4:
                location = "模拟器电话";
                break;
            case 5:
                //10010 10086之类的客服电话
                location = "客服电话";
                break;
            default:
                if(number.length() > 10 && number.startsWith("0"))
                {
                    //此时为固定电话号码
                    //查询固定电话号码:
                    location = queryTelNumber(number);
                }
                break;
        }
        if(location == null)
        {
            location = number;
        }
        return location;
    }

    //查询固定电话的号码归属地
    private static String queryTelNumber(String number)
    {
        SQLiteDatabase sdb = SQLiteDatabase.openDatabase(DATABASE_PATH,null,SQLiteDatabase.OPEN_READONLY);
        String location = null;
        Cursor cursor = null;
        cursor = sdb.rawQuery("select location from data2 where area= ?",new String[]{number.substring(1,3)});
        while(cursor.moveToNext())
        {
            location = cursor.getString(0);
        }
        cursor = sdb.rawQuery("select location from data2 where area= ?",new String[]{number.substring(1,4)});
        while(cursor.moveToNext())
        {
            location = cursor.getString(0);
        }
        if(cursor != null) {
            cursor.close();
            return location.substring(0, location.length() - 2);
        }
        cursor.close();
        return number;
    }