效果图:
技术点:
- 数据库的查询操作
- 正则表达式
- 监听输入框的输入事件
思路:
查询号码归属地的方法有两种:
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;
}