Android项目:手机安全卫士(9)—— 手机号码归属地查询

Android项目:手机安全卫士(9)—— 电话号码归属地查询

1 综述

手机防盗功能已经开发完了,接下来开发一个高级工具功能,就是手机归属地查询,严格来讲,是查询手机号码的归属地。不过,由于用的号码数据库不是最新的,好多新号码段都没有,所以不能查,如果有必要,可以换成最新的数据库,某宝上有,你懂的。数据库文件保存在项目的 assets 文件夹中。

关于项目相关文章,请访问:

项目源码地址(实时更新):https://github.com/xwdoor/MobileSafe

2 创建 Activity

每个功能需求都会在应用中提供进入接口,我们的项目的进入接口是:主界面->高级工具->电话归属地查询。所以需要创建两个 Activity,一个是高级工具界面:ToolsActivity,另一个是电话归属地查询界面:AddressQueryActivity。两个 Activity 的界面很简单,这里就不放代码了,给出效果图就行了,具体实现可以下载项目源码。

高级工具界面:ToolsActivity 效果图:

高级工具界面:ToolsActivity 效果图

归属地查询界面:AddressQueryActivity 效果图:

归属地查询界面:AddressQueryActivity 效果图

3 拷贝数据库

由于 SQLiteDatabase 直接收 /data/data 目录下的数据库文件,所以我们要将项目中 assets 目录的数据库文件 address.db 文件复制到 data 目录下,代码如下:


    /**
     * 拷贝数据库
     * @param dbName 数据库文件名
     */
    private void copyDb(String dbName) {
        AssetManager assets = getAssets();
        File filesDir = getFilesDir();//获取项目路径(/data/data/net.xwdoor.mobilesafe/files)
        File desFile = new File(filesDir, dbName);

        if(desFile.exists()){
            showLog("","数据库已存在");
            return;
        }
        InputStream in = null;
        FileOutputStream out = null;
        try {
            //另一种获取数据库文件方式
            //in=context.getClass().getClassLoader().getResourceAsStream("assets/"+names[i]);
            in = assets.open(dbName);// 打开assets目录的文件
            out = new FileOutputStream(desFile);
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
                out.flush();
            }
        } catch (IOException e) {
            showLog("copyDb error",e.getMessage());
        } finally {
            try {
                in.close();
                out.close();
            } catch (IOException e) {
                showLog("copyDb io error",e.getMessage());
            }
        }
    }

拷贝数据库的操作我们放到闪屏界面去完成,这也是闪屏界面的最大作用之一了。

4 号码归属地查询

先说一下我们的查询策略:

  • 若是手机号,则根据手机号前 7 位,查到对应的区域
  • 若号码长度长于 8 位,优先考虑 4 位区号,则去掉前面的零,然后根据区号查询对应的区域
  • 若根据 4 位区号没有查询结果,则作为 3 位区号进行查询,同样去掉前面的零
  • 若号码长度为 3位 或 4 位,则同一显示为报警号码
  • 若以上都不是,则显示未知号码

根据以上的查询策略,可以写出我们的查询代码了:


    /**
     * 电话归属地查询
     *
     * @param context
     * @param number 电话号码
     */
    public static String getAddress(Context context, String number) {
        String address = "未知号码";
        String path = new File(context.getFilesDir(), DB_NAME).getAbsolutePath();
        SQLiteDatabase database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);

        // 判断是否是手机号码
        // 1[3-8]+9数字
        // 正则表达式
        // ^1[3-8]\d{9}$
        if (number.matches("^1[3-8]\\d{9}$")) {// 匹配是否是手机号码
            Cursor cursor = database.rawQuery("select location from data2 where id=(select outkey from data1 where id=?)",
                    new String[]{number.substring(0, 7)});

            if (cursor.moveToFirst()) {
                address = cursor.getString(0);
            }

            cursor.close();
        }else {
            switch (number.length()){
                case 3:
                    address = "报警电话";
                    break;
                case 4:
                    address = "模拟器";
                    break;
                case 5:
                    address = "客服电话";
                    break;
                case 7:
                case 8:
                    // 8888 8888
                    address = "本地电话";
                    break;
                default:
                    // 010 8888 888
                    // 0910 8888 8888
                    if (number.startsWith("0") && number.length() >= 10
                            && number.length() <= 12) {
                        // 有可能是长途电话
                        // 区号是4位的情况
                        Cursor cursor = database.rawQuery(
                                "select location from data2 where area=?",
                                new String[] { number.substring(1, 4) });
                        if (cursor.moveToFirst()) {// 查到4位区号
                            address = cursor.getString(0);
                        }

                        cursor.close();

                        // 区号是3位的情况
                        if ("未知号码".equals(address)) {// 4位区号没有查到,开始查3位
                            cursor = database.rawQuery(
                                    "select location from data2 where area=?",
                                    new String[] { number.substring(1, 3) });
                            if (cursor.moveToFirst()) {// 查到3位区号
                                address = cursor.getString(0);
                            }

                            cursor.close();
                        }
                    }
                    break;
            }
        }
        return address;
    }

匹配手机号的时候用到了正则表达式,能简单的使用就可以了,^1[3-8]\d{9}$ 的意思是:以数字 1 开始,第二位是 3 到 8 之间的数字(包含 3 和 8),然后是 9 位数字。SQLiteDatabase 对象有两个方法,分别是 rawQuery() 和 query(),他们的区别是,前者是根据自定义 SQL 语句进行查询,后者提供参数,自动构建 SQL 语句。

查询结果如下:

号码归属地查询结果

5 总结

原来,如果有现成的数据库文件,直接使用 SQLiteDatabase.openDatabase() 方法就能够操作,前提是 SQLite 数据库。

关于项目相关文章,请访问:

项目源码地址(实时更新):https://github.com/xwdoor/MobileSafe

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值