电话归属查询android_android studio查询电话归属地 - CSDN
  • 最近老是被什么基金原油的电话骚扰,但是手机没显示归属地,搞得我有时以为是快递电话之类的就接了..然后各种烦..所以打算做一个来去电显示归属地的小软件,碰到某些城市的陌生号码就直接挂掉,既然要做就顺便写篇...

    前言

    最近老是被什么基金原油的电话骚扰,但是手机没显示归属地,搞得我有时以为是快递电话之类的就接了..然后各种烦..所以打算做一个来去电显示归属地的小软件,碰到某些城市的陌生号码就直接挂掉,既然要做就顺便写篇博客把,显示来去电归属地这个功能商业app用得不多,但是权当学习了。

    实现原理

    网上找一个有号码段的归属地数据库,然后开启个服务监听系统去电广播和来电,然后获取来去电号码,跟数据库的号码字段进行比对,然后显示在手机界面上。

    实现步骤

    下面一步步来完成这个功能:
    主界面布局:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/btn_show_address"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="显示来去电归属地"
            android:textSize="19sp" />
    
        <Button
            android:id="@+id/btn_noshow_address"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="不显示来去电归属地"
            android:textSize="19sp" />
    </LinearLayout>
    这个布局是自己为了自己设置是否显示归属地的。
    在main下面新建一个assets文件夹,并把网上找到的数据库拷贝到该文件夹下面
    接下来分析数据库表:
    我下的数据库里面有两个表,表结构如下:
    data1:

    data2:

    其中data1的id就是电话号码,前七位就可以确定归属地了,然后根据id对应的outkey去匹配data2的id就可以得到归属地信息了。知道了两个表之间的联系之后就可以开始我们的查询工作了。
    新建一个CallAddressDao类,这个类是用来访问数据库的
    public class CallAddressDao {
        //数据库路径
        private static final String PATH = "data/data/com.sjr.calladdress/files/address.db";
        /**
         * 从数据库中获取手机归属地
         * @param number
         * @return 手机归属地
         */
        public static String getCallAddress(String number){
            String callAddress = "未知号码";
            //获取数据库对象
            SQLiteDatabase database = SQLiteDatabase.openDatabase(PATH, null,
                    SQLiteDatabase.OPEN_READONLY);
            //正则表达式匹配
            if (number.matches("^1[3-8]\\d{9}$")) {//匹配器11位手机号
                Cursor cursor = database.rawQuery("select location from data2 where id=(select outkey from data1 where id=?)",
                        new String[]{number.substring(0, 7)});//截取前七个
                if (cursor.moveToNext())
                    callAddress = cursor.getString(0);
                cursor.close();
            }else if (number.matches("^\\d+$")){//匹配数字
                switch (number.length()){
                    case 3:
                        callAddress = "报警电话";//三位数就是报警电话
                        break;
                    case 4:
                        callAddress = "模拟器";
                        break;
                    case 5:
                        callAddress = "客服电话";
                        break;
                    case 7:
                    case 8:
                        callAddress = "本地电话";
                        break;
                    default:
                        if (number.startsWith("0")&&number.length()>10){//有可能是长途电话
                            //有些区号是4位,有些区号是3位(包括0)
    //                        先查询4位区号
                            Cursor cursor = database.rawQuery("select location from data2 where area =?",
                                    new String[]{number.substring(1,4)});
                            if (cursor.moveToNext())
                                callAddress = cursor.getString(0);
                            else {
                                cursor.close();
                                //查询3位区号
                                cursor = database.rawQuery("select location from data2 where area =?",
                                        new String[]{number.substring(1,3)});
                                if (cursor.moveToNext())
                                    callAddress = cursor.getString(0);
                                cursor.close();
                            }
                        }
                        break;
                }
            }
            database.close();//关闭数据库
            return callAddress;
        }
    }
    下面是打开一个数据库:
     //获取数据库对象
            SQLiteDatabase database = SQLiteDatabase.openDatabase(PATH, null,
                    SQLiteDatabase.OPEN_READONLY);
    PATH是数据库路径,第二个是一个可选的选项,直接传null,第三个然后我们只是要读,并不修改数据库,所以设置为只读
    这里我设定的数据库路径是:
    data/data/com.sjr.calladdress/files/address.db
    这不能是assets文件夹下面的,只能是data/data/包名/ 目录下,不然是访问不到的,但是这时这个路径下是没有数据库的,所以我就在第一次进入主界面的时候先把数据库拷到这个目录下
        /**
         * 把assets目录下的数据库拷贝到data/data目录下
         *
         * @param dbName
         */
        private void copyDB(String dbName) {
    //                File filesDir = getFilesDir();///data/data/com.sjr.calladdress/files
    //        Log.d("print","路径:"+filesDir.getAbsolutePath());
            File desFile = new File(getFilesDir(), dbName);//要拷贝的目标地址
            if (desFile.exists()) {//如果已经存在,就不进行拷贝工作直接返回
                Log.d("print", "数据库" + dbName + "已经存在");
                return;
            }
            //否则就进行数据库拷贝
            FileOutputStream out = null;
            InputStream in = null;
    
            try {
                in = getAssets().open(dbName);//读写assets文件夹下的数据库
                out = new FileOutputStream(desFile);//写入data目录
    
                int len = 0;
                byte[] buffer = new byte[1024];
    
                while ((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null)
                        out.close();
                    if (in != null)
                        in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
    
        }
    上面的代码就把数据库从assets文件夹下面拷贝到data目录下了
    然后通过数据库查询语句跟正则表达式对手机号进行匹配。
    这时我们开启一个服务去监听来电广播和去电状态,我先把整个服务类拷下来然后详细分析:
       <pre name="code" class="java">/**
     * Created by 宋家任 on 2016/3/1 15:22.
     * 监听来去电服务
     */
    public class CallAddressService extends Service {
    
    
        private TelephonyManager mTM;//电话管理者
        private WindowManager mWM;//桌面窗口管理者
        private MPhoneStateListener mListener;
        private View mView;//桌面展示归属地的view
        private OutCallReceiver mReceiver;//监听去电广播
    
        private SharedPreferences mPref;//记录归属地的位置
    
        private int startX;
        private int startY;
        private WindowManager.LayoutParams params;
        private int windowWidth;
        private int windowHeight;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            mPref = getSharedPreferences("config", MODE_PRIVATE);
            mTM = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
            mListener = new MPhoneStateListener();
            mTM.listen(mListener, PhoneStateListener.LISTEN_CALL_STATE);
            mReceiver = new OutCallReceiver();
    
            //动态注册去电广播
            IntentFilter filter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
            registerReceiver(mReceiver, filter);
        }
    
        /**
         * 监听来电通话状态
         * 需要权限
         *  <uses-permission android:name="android.permission.READ_PHONE_STATE" />
         */
        class MPhoneStateListener extends PhoneStateListener {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                switch (state) {
                    case TelephonyManager.CALL_STATE_RINGING:// 电话铃响
                        String address = CallAddressDao.getCallAddress(incomingNumber);//把来电号码跟数据库号码进行比对
                        showView(address);
                        break;
    
                    case TelephonyManager.CALL_STATE_IDLE:// 电话闲置状态
                        if (mWM != null && mView != null) {
                            mWM.removeView(mView);// 从window中移除view
                            mView = null;
                        }
                        break;
                }
            }
        }
    
        /**
         * 去电广播
         * 监听去电广播需要下面的权限
         * <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
         */
        class OutCallReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                String number = getResultData();//获取去电号码
                String address = CallAddressDao.getCallAddress(number);//将去电号码跟数据库的进行比对
                showView(address);
            }
        }
    
        /**
         *
         * 弹自定义的界面
         * 使用电话窗口需要下面的权限
         *<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
         * @param address
         */
        private void showView(String address) {
            //获得一个窗口管理者实例
            mWM = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
    
            windowWidth = mWM.getDefaultDisplay().getWidth();//获取屏幕宽度
            windowHeight = mWM.getDefaultDisplay().getHeight();//获取屏幕高度
    
            //布局参数
            params = new WindowManager.LayoutParams();
            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
            params.width = WindowManager.LayoutParams.WRAP_CONTENT;
            params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
            params.format = PixelFormat.TRANSLUCENT;
            params.type = WindowManager.LayoutParams.TYPE_PHONE;//电话窗口。用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
            params.gravity = Gravity.LEFT + Gravity.TOP;// 将重心位置设置为左上方,
            // 也就是(0,0)从左上方开始,而不是默认的重心位置
    
            params.setTitle("Toast");
    
            //先获取上次显示的位置
            int lastX = mPref.getInt("lastX", 0);
            int lastY = mPref.getInt("lastY", 0);
    
            //设置悬浮窗的位置,基于左上方的偏移量
            params.x = lastX;
            params.y = lastY;
    
    
            //要展示的view
            mView = View.inflate(this, R.layout.view_address, null);
    
            //给view设置背景
            mView.setBackgroundResource(R.drawable.call_locate_blue);// 根据存储的样式更新背景
    
            //设置文字
            TextView tvText = (TextView) mView.findViewById(R.id.tv_number);
            tvText.setText(address);
    
            mWM.addView(mView, params);// 将view添加在屏幕上(Window)
    
            //给这个归属地view设置监听,移动的时候记录坐标
            mView.setOnTouchListener(new View.OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN://按下
                            // 初始化起点坐标
                            startX = (int) event.getRawX();
                            startY = (int) event.getRawY();
                            break;
                        case MotionEvent.ACTION_MOVE://移动
                            int endX = (int) event.getRawX();
                            int endY = (int) event.getRawY();
    
                            // 计算移动偏移量
                            int dx = endX - startX;
                            int dy = endY - startY;
    
                            // 更新浮窗位置
                            params.x += dx;
                            params.y += dy;
    
                            // 防止坐标偏离屏幕
                            if (params.x < 0) {
                                params.x = 0;
                            }
                            if (params.y < 0) {
                                params.y = 0;
                            }
    
    
                            // 防止坐标偏离屏幕
                            if (params.x > windowWidth - mView.getWidth()) {
                                params.x = windowWidth - mView.getWidth();
                            }
    
                            if (params.y > windowHeight - mView.getHeight()) {
                                params.y = windowHeight - mView.getHeight();
                            }
    
    
                            mWM.updateViewLayout(mView, params);//更新布局
    
                            // 重新初始化起点坐标
                            startX = (int) event.getRawX();
                            startY = (int) event.getRawY();
                            break;
                        case MotionEvent.ACTION_UP://抬起
                            // 记录坐标点
                            SharedPreferences.Editor edit = mPref.edit();
                            edit.putInt("lastX", params.x);
                            edit.putInt("lastY", params.y);
                            edit.commit();
                            break;
    
                        default:
                            break;
                    }
                    return true;//返回true消费这个手势事件
                }
            });
        }
    
    
        /**
         * 服务销毁的时候会回调这个方法
         */
        @Override
        public void onDestroy() {
            mTM.listen(mListener, PhoneStateListener.LISTEN_NONE);//停止来电监听
            unregisterReceiver(mReceiver);//注销监听去电广播
        }
    }

    
    先解决监听去电广播的问题,写一个广播接收者,去接收去电广播,注意监听去电广播是要权限的,权限如下
      /**
         * 去电广播
         * 监听去电广播需要下面的权限
         * <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
         */
        class OutCallReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                String number = getResultData();//获取去电号码
                String address = CallAddressDao.getCallAddress(number);//将去电号码跟数据库的进行比对
                showView(address);
            }
        }

    让后因为是要动态监听去电广播,所以就只能动态注册,所以在服务开启的时候就注册这个广播:
       //动态注册去电广播
            IntentFilter filter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
            registerReceiver(mReceiver, filter);
    在服务关闭的时候就取消注册:
     /**
         * 服务销毁的时候会回调这个方法
         */
        @Override
        public void onDestroy() {
            mTM.listen(mListener, PhoneStateListener.LISTEN_NONE);//停止来电监听
            unregisterReceiver(mReceiver);//注销监听去电广播
        }
    上面就完成了一个动态监听去电广播了,然后就是监听电话状态了
     /**
         * 监听来电通话状态
         * 需要权限
         *  <uses-permission android:name="android.permission.READ_PHONE_STATE" />
         */
        class MPhoneStateListener extends PhoneStateListener {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                switch (state) {
                    case TelephonyManager.CALL_STATE_RINGING:// 电话铃响
                        String address = CallAddressDao.getCallAddress(incomingNumber);//把来电号码跟数据库号码进行比对
                        showView(address);
                        break;
    
                    case TelephonyManager.CALL_STATE_IDLE:// 电话闲置状态
                        if (mWM != null && mView != null) {
                            mWM.removeView(mView);// 从window中移除view
                            mView = null;
                        }
                        break;
                }
            }
        }

    写一个类去继承PhoneStateListener,然后监听通话状态,注意也是需要权限的,然后同监听去电广播类似,在服务初始化的时候监听,在服务销毁的时候注销监听。

    然后写一个方法在通话窗口展示归属地当然使用电话窗口也是需要权限的,权限如下

      /**
         *
         * 弹自定义的界面
         * 使用电话窗口需要下面的权限
         *<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
         * @param address
         */
        private void showView(String address) {
            //获得一个窗口管理者实例
            mWM = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
    
            windowWidth = mWM.getDefaultDisplay().getWidth();//获取屏幕宽度
            windowHeight = mWM.getDefaultDisplay().getHeight();//获取屏幕高度
    
            //布局参数
            params = new WindowManager.LayoutParams();
            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
            params.width = WindowManager.LayoutParams.WRAP_CONTENT;
            params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
            params.format = PixelFormat.TRANSLUCENT;
            params.type = WindowManager.LayoutParams.TYPE_PHONE;//电话窗口。用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
            params.gravity = Gravity.LEFT + Gravity.TOP;// 将重心位置设置为左上方,
            // 也就是(0,0)从左上方开始,而不是默认的重心位置
    
            params.setTitle("Toast");
    
            //先获取上次显示的位置
            int lastX = mPref.getInt("lastX", 0);
            int lastY = mPref.getInt("lastY", 0);
    
           //设置悬浮窗的位置,基于左上方的偏移量
            params.x = lastX;
            params.y = lastY;
            //要展示的view
            mView = View.inflate(this, R.layout.view_address, null);
    
            //给view设置背景
            mView.setBackgroundResource(R.drawable.call_locate_blue);// 根据存储的样式更新背景
    
            //设置文字
            TextView tvText = (TextView) mView.findViewById(R.id.tv_number);
            tvText.setText(address);
    
            mWM.addView(mView, params);// 将view添加在屏幕上(Window)
    
            //给这个归属地view设置监听,移动的时候记录坐标
            mView.setOnTouchListener(new View.OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN://按下
                            // 初始化起点坐标
                            startX = (int) event.getRawX();
                            startY = (int) event.getRawY();
                            break;
                        case MotionEvent.ACTION_MOVE://移动
                            int endX = (int) event.getRawX();
                            int endY = (int) event.getRawY();
    
                            // 计算移动偏移量
                            int dx = endX - startX;
                            int dy = endY - startY;
    
                            // 更新浮窗位置
                            params.x += dx;
                            params.y += dy;
    
                            // 防止坐标偏离屏幕
                            if (params.x < 0) {
                                params.x = 0;
                            }
                            if (params.y < 0) {
                                params.y = 0;
                            }
    
    
                            // 防止坐标偏离屏幕
                            if (params.x > windowWidth - mView.getWidth()) {
                                params.x = windowWidth - mView.getWidth();
                            }
    
                            if (params.y > windowHeight - mView.getHeight()) {
                                params.y = windowHeight - mView.getHeight();
                            }
    
    
                            mWM.updateViewLayout(mView, params);//更新布局
    
                            // 重新初始化起点坐标
                            startX = (int) event.getRawX();
                            startY = (int) event.getRawY();
                            break;
                        case MotionEvent.ACTION_UP://抬起
                            // 记录坐标点
                            SharedPreferences.Editor edit = mPref.edit();
                            edit.putInt("lastX", params.x);
                            edit.putInt("lastY", params.y);
                            edit.commit();
                            break;
    
                        default:
                            break;
                    }
                    return true;//返回true消费这个手势事件
                }
            });
        }

    上面的方法就是在通话界面显示自定义的view,为了便于理解我加了很多注释,然后在这里还是解释下好了,获得一个桌面管理者,然后设置归属地view的相关参数,然后把归属地view添加到桌面,然后给view设置一个监听,让view可以移动,上面用到了SharedPreferences,这是为了移动完归属地view后记录下位置然后下次初始就让这个view显示在那个位置,view布局如下:


    <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/call_locate_blue"
        android:gravity="center_vertical"
        android:orientation="horizontal" >
    
        <ImageView
            android:id="@+id/iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@android:drawable/ic_menu_call" />
    
        <TextView
            android:id="@+id/tv_number"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="未知号码"
            android:textSize="18sp"
            android:textColor="#fff" />
    
    </LinearLayout></span>
    背景是从网上找的一张.9图然后图标是Android系统的一个电话图标,效果如下




    然后完成这个服务类以后只要在MainActivity里开启服务就好了,MainActivity代码如下:

    <span style="font-size:14px;">/**
     * Created by 宋家任 on 2016/5/6 13:55.
     * 主界面
     */
    public class MainActivity extends Activity implements View.OnClickListener {
        private Button btnShow;//显示归属地
        private Button btnNoShow;//不显示归属地
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            copyDB("address.db");// 拷贝归属地查询数据库
            initDatas();
        }
    
        /**
         * 把assets目录下的数据库拷贝到data/data目录下
         *
         * @param dbName
         */
        private void copyDB(String dbName) {
    //                File filesDir = getFilesDir();///data/data/com.sjr.calladdress/files
    //        Log.d("print","路径:"+filesDir.getAbsolutePath());
            File desFile = new File(getFilesDir(), dbName);//要拷贝的目标地址
            if (desFile.exists()) {//如果已经存在,就不进行拷贝工作直接返回
                Log.d("print", "数据库" + dbName + "已经存在");
                return;
            }
            //否则就进行数据库拷贝
            FileOutputStream out = null;
            InputStream in = null;
    
            try {
                in = getAssets().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);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null)
                        out.close();
                    if (in != null)
                        in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
    
        }
    
        private void initDatas() {
            btnNoShow = (Button) findViewById(R.id.btn_show_address);
            btnShow = (Button) findViewById(R.id.btn_noshow_address);
    
            btnShow.setOnClickListener(this);
            btnNoShow.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_show_address:
                    startService(new Intent(this, CallAddressService.class));//开启显示归属地服务
                    break;
                case R.id.btn_noshow_address:
                    stopService(new Intent(this, CallAddressService.class));//关闭显示归属地服务
                    break;
            }
        }
    }</span>


    效果

    到这里整个归属地的设置就已经完成了,下面是实际运行结果



    源码地址为http://download.csdn.net/detail/lxzmmd/9512104













    展开全文
  • android 2015最新手机和电话归属查询数据库,可以查询手机的归属地,也可以查询座机的归属地,并可以查询出是移动,电信,联通的号码
  • 数据库拷贝,归属查询工具类
    来电归宿地查询有两种查询方式:
    1、网络平台查询;
    2、数据库查询;

    这是使用数据库查询的方式,实现步骤如下:
    1、 在Eclispase的android工程中把要发布的数据库放在assets目录下面;
    2、在展示应用的引导页面(也就是展示广告或者公司logo的页面)把数据库拷贝到”data/data/应用名称/files/数据库名称”路径下,在实现数据库拷贝的代码中有判断数据库是否存在的逻辑(当用户第一次安装应用时数据库就拷贝了,当用户又一次打开应用时无需再拷贝,这样可以节省应用的性能)。拷贝数据库的工具类如下:
    <textarea readonly="readonly" name="code" class="java"> 
    package gif.phone.zzy.com.comphonesafe.com.mobliesafe.activity.databaseutils;
    
    import android.content.Context;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import gif.phone.zzy.com.comphonesafe.R;
    import gif.phone.zzy.com.comphonesafe.com.mobliesafe.activity.util.ToastUtils;
    
    /**
     * 拷贝assets文件夹下的数据库到  data/data/应用包名/files文件夹
     */
    public class DatabaseUtils {
        public static void copyDataBase(Context context,String dataBaseName){
            File desFile=new File(context.getFilesDir(),dataBaseName);
    
            //判断数据库是否存在,如果存在就不在往desFile中拷贝数据库
            if (desFile.exists()){
                return;
            }
    
            FileOutputStream fos=null;
            InputStream inputStream=null;
           //context.getResources().openRawResource(R.raw.address);
            try {
                 inputStream = context.getAssets().open(dataBaseName);
                 fos=new FileOutputStream(desFile);
                byte[] bytes=new byte[1024];
                int lenth=0;
                while ((lenth=inputStream.read(bytes))!=-1){
                    fos.write(bytes,0,bytes.length);
                    fos.flush();
                }
    
            } catch (IOException e) {
                ToastUtils.showToast(context,"assets目录下的数据库不存在");
            }finally {
                if (inputStream!=null){
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
                }
                if (fos!=null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    </textarea>
    <div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.71429; font-size: 14px;"><span style="font-family: 'Helvetica Neue'; color: rgb(51, 51, 51);"> 3、实现归属地查询的工具类 </span></div> <pre name="code" class="java">  <textarea readonly="readonly" name="code" class="java> 
    package gif.phone.zzy.com.comphonesafe.com.mobliesafe.activity.databaseutils;
    
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Environment;
    
    import java.io.File;
    
    import gif.phone.zzy.com.comphonesafe.com.mobliesafe.activity.util.LogUtils;
    
    /**
     * 查询归属地工具类
     */
    public class AddressQuery  {
        private static  String dataBaseNameFilepath;
        public static String getAdress(Context context,String number){
            String address="未知号码";
            dataBaseNameFilepath= context.getFilesDir()+ File.separator+"address.db";
            //获取数据库
            SQLiteDatabase database=SQLiteDatabase.openDatabase(dataBaseNameFilepath,null,SQLiteDatabase.OPEN_READONLY);
            //开始查询
    
            //正则表达式匹配电话号码
            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!=null){
                    if (cursor.moveToNext()){
                        address=cursor.getString(0);
                    }
                }
                cursor.close();
            }else if (number.matches("^\\d+$")){//匹配数字
                switch (number.length()){
                    case 3:
                        if (number.equals("110")){
                            address="报警电话";
                        }else if (number.equals("120")){
                            address="急救电话";
                        }
                        break;
                    case 4:
                        address="android模拟器电话";
                        break;
                    case 5:
                        address="客服电话";
                        break;
                    case 7:
                    case 8:
                        address="本地电话";
                        break;
                    default:
                    if (number.startsWith("0") && number.length()>10){//判断长途或者本地座机
                        LogUtils.showLog("判断长途或者本地座机");
                        Cursor cursor = database.rawQuery("select location from data2 where area=?",
                                new String[]{number.substring(1, 4)});//截取区号的后三位   如贵阳区号0851
                        if (cursor.moveToNext()){
                            address = cursor.getString(0);
                        }else {
                            cursor.close();
                            cursor = database.rawQuery("select location from data2 where area=?",
                                    new String[]{number.substring(1, 3)});//截取区号的后两位,如北京区号010
                            if (cursor.moveToNext()){
                                address=cursor.getString(0);
                                cursor.close();
                            }
                        }
                    }
                        break;
                }
            }
    
            database.close();
            return address;
        }
    }
    </textarea>

    
    

    展开全文
  • 需要使用到WebService的服务,这里选择www.webxml.com.cn提供的服务来查询电话号码归属地,使用方法网页上有介绍,这里使用一个实例来演示如何在Android下实现电话号码归属地的查询: 0.使用webxml的soap方式:...

    需要使用到WebService的服务,这里选择www.webxml.com.cn提供的服务来查询电话号码归属地,使用方法网页上有介绍,这里使用一个实例来演示如何在Android下实现电话号码归属地的查询:

    0.使用webxml的soap方式:mobilesoap.xml在src目录下

    <?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Body> <getMobileCodeInfo xmlns="http://WebXml.com.cn/"> <mobileCode>$mobile</mobileCode> <userID></userID> </getMobileCodeInfo> </soap12:Body> </soap12:Envelope>

    1.MainActivity.java

    public class MainActivity extends Activity { private EditText mobileText; private TextView addressView; private static final String TAG = "MainActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mobileText = (EditText)this.findViewById(R.id.mobile); addressView = (TextView)this.findViewById(R.id.address); Button button = (Button)this.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String mobile = mobileText.getText().toString(); InputStream inStream = this.getClass().getClassLoader().getResourceAsStream("mobilesoap.xml"); try { addressView.setText(MobileInfoService.getMobileAddress(inStream, mobile)); } catch (Exception e) { Log.e(TAG, e.toString()); Toast.makeText(MainActivity.this, "查询失败", 1).show(); } } }); } }

    2.MobileInfoService.java

    public class MobileInfoService { /** * 获得电话号码归属地信息 * @param inStream * @param mobile * @return * @throws Exception */ public static String getMobileAddress(InputStream inStream, String mobile)throws Exception { //定义输入流 String soap = readSoapFile(inStream, mobile); byte[] data = soap.getBytes(); URL url = new URL("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("POST"); conn.setConnectTimeout(5 * 1000); //如果通过post提交数据,必须设置允许对外输出数据 conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/soap+xml; charset=utf-8"); conn.setRequestProperty("Content-Length", String.valueOf(data.length)); OutputStream outStream = conn.getOutputStream(); outStream.write(data); outStream.flush(); outStream.close(); if(conn.getResponseCode()==200) { return parseResponseXML(conn.getInputStream()); } return null; } /** * 读取Soap文件 * @param inStream * @param mobile * @return * @throws Exception */ private static String readSoapFile(InputStream inStream, String mobile) throws Exception { //读取输入流 byte[] data = StreamTool.readInputStream(inStream); String soapxml = new String(data); Map<String, String> params = new HashMap<String, String>(); params.put("mobile", mobile); return replace(soapxml, params); } /** * 替换占位符方法 * @param xml * @param params * @return * @throws Exception */ public static String replace(String xml, Map<String, String> params)throws Exception { String result = xml; if(params!=null && !params.isEmpty()) { //循环替换掉所有占位符 for(Map.Entry<String, String> entry : params.entrySet()) { //需要对$进行转义 String name = "\\$"+ entry.getKey(); //使用正则表达式替换 Pattern pattern = Pattern.compile(name); Matcher matcher = pattern.matcher(result); if(matcher.find()) { result = matcher.replaceAll(entry.getValue()); } } } return result; } /** * 解析返回的XML字符串数据 * @param inStream * @return * @throws Exception */ private static String parseResponseXML(InputStream inStream) throws Exception { XmlPullParser parser = Xml.newPullParser(); parser.setInput(inStream, "UTF-8"); //产生第一个事件 int eventType = parser.getEventType(); //只要不是文档结束事件 while(eventType!=XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_TAG: //获取解析器当前指向的元素的名称 String name = parser.getName(); if("getMobileCodeInfoResult".equals(name)) { return parser.nextText(); } break; } eventType = parser.next(); } return null; } }

    3.工具类

    /** * 上传文件 */ public class FormFile { /* 上传文件的数据 */ private byte[] data; private InputStream inStream; private File file; /* 文件名称 */ private String filname; /* 请求参数名称*/ private String parameterName; /* 内容类型 */ private String contentType = "application/octet-stream"; public FormFile(String filname, byte[] data, String parameterName, String contentType) { this.data = data; this.filname = filname; this.parameterName = parameterName; if(contentType!=null) this.contentType = contentType; } public FormFile(String filname, File file, String parameterName, String contentType) { this.filname = filname; this.parameterName = parameterName; this.file = file; try { this.inStream = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } if(contentType!=null) this.contentType = contentType; } public File getFile() { return file; } public InputStream getInStream() { return inStream; } public byte[] getData() { return data; } public String getFilname() { return filname; } public void setFilname(String filname) { this.filname = filname; } public String getParameterName() { return parameterName; } public void setParameterName(String parameterName) { this.parameterName = parameterName; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } }

    /** * 上传文件 */ public class FormFile { /* 上传文件的数据 */ private byte[] data; private InputStream inStream; private File file; /* 文件名称 */ private String filname; /* 请求参数名称*/ private String parameterName; /* 内容类型 */ private String contentType = "application/octet-stream"; public FormFile(String filname, byte[] data, String parameterName, String contentType) { this.data = data; this.filname = filname; this.parameterName = parameterName; if(contentType!=null) this.contentType = contentType; } public FormFile(String filname, File file, String parameterName, String contentType) { this.filname = filname; this.parameterName = parameterName; this.file = file; try { this.inStream = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } if(contentType!=null) this.contentType = contentType; } public File getFile() { return file; } public InputStream getInStream() { return inStream; } public byte[] getData() { return data; } public String getFilname() { return filname; } public void setFilname(String filname) { this.filname = filname; } public String getParameterName() { return parameterName; } public void setParameterName(String parameterName) { this.parameterName = parameterName; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } }

    public class StreamTool { /** * 从输入流读取数据 * @param inStream * @return * @throws Exception */ public static byte[] readInputStream(InputStream inStream) throws Exception { ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while( (len = inStream.read(buffer)) !=-1 ) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); return outSteam.toByteArray(); } }

    4.程序运行效果:


    展开全文
  • 自己开发的项目里,添加了一个简易的“手机号码归属查询”模块,纯手撸,不采用第三方框架。获取源码效果图:上的开发思路:界面实现---&gt;获取数据---&gt;解析数据---&gt;界面展示具体实现: 1. ...

    自己开发的项目里,添加了一个简易的“手机号码归属地查询”模块,纯手撸,没有采用第三方框架。

    获取源码

    效果图:

    开发思路:

    界面实现--->获取数据--->数据处理--->界面展示

    具体实现:

      1. 界面实现

    界面绘制比较简单,就不放代码了,其中为EditText做了几点处理:

    • 自定义背景

    bg_edit_selector:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/bg_edit_normal" android:state_focused="false" />
        <item android:drawable="@drawable/bg_edit_selected" android:state_focused="true" />
    </selector>

    bg_edit_normal:

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <stroke
            android:width="1dp"
            android:color="@color/normalBlue" />
        <corners android:radius="5dp" />
        <solid android:color="@android:color/transparent" />
        <padding
            android:bottom="10dp"
            android:left="12dp"
            android:right="12dp"
            android:top="10dp" />
    </shape>

    bg_edit_selected:

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="@android:color/transparent" />
        <stroke
            android:width="2dp"
            android:color="@color/lightBlue" />
        <corners android:radius="5dp" />
        <padding
            android:bottom="10dp"
            android:left="12dp"
            android:right="12dp"
            android:top="10dp" />
    </shape>
    • 添加动画效果,简单的透明度、伸缩变化

    java:

    Animation animPhone = AnimationUtils.loadAnimation(this, R.anim.edit_phone_anim);
    edtPhone.startAnimation(animPhone);

    xml:tv_phone_result_anim

    <?xml version="1.0" encoding="utf-8"?>
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="200"
        android:fromAlpha="1.0"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:toAlpha="0.3" />
    • 点击查询按钮后隐藏键盘
     private void hideKeyboard(View view) {
            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            if (im.isActive(view)) {
                im.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
            }
        }

      2. 获取数据

    • 选用百度的API,写在项目的Consts类里:
    public class Consts {
        public static final String BAIDU_PHONE_URL = "http://mobsec-dianhua.baidu.com/dianhua_api/open/location";
    }
    • 自己开辟线程,执行网络请求,读取数据:
    class PhoneThread extends Thread {
            private String url;
            private String number;
    
            private PhoneThread(String url, String number) {
                this.url = url;
                this.number = number;
            }
    
            /**
             * 子线程不能直接弹出Toast(其实就是子线程更新UI),方法:
             * 1. Looper.prepare(); Looper.loop();
             * 2. runOnUiThread(new Runnable(){});
             * 3. mHandler.senMessage();
             */
            @Override
            public void run() {
                String result = getJsonFromURL(url);
                if (TextUtils.isEmpty(result)) {
                    Looper.prepare();
                    Toast.makeText(AttributionActivity.this, R.string.attribution_return_null,
                            Toast.LENGTH_SHORT).show();
                    Looper.loop();
                } else {
                    Phone phone = parseJsonToPhone(result, number);
                    Message msg = Message.obtain();
                    msg.obj = phone;
                    mPhoneHandler.sendMessage(msg);
                }
            }
        }

      3. 数据处理

    • 自定义Phone类(getter()、setter()和toString()略):
    public class Phone {
        private String number;
        private String province;
        private String carrier;
        private String ownerCarrier;
    }
    • 解析json:使用Android自带的JSONObject,当然Gson和FastJson更方便
     private Phone parseJsonToPhone(String url, String number) {
            Phone phone = new Phone();
            try {
                JSONObject object = new JSONObject(url);
                JSONObject numberObj = object.getJSONObject("response").getJSONObject(number);
                JSONObject detailObj = numberObj.getJSONObject("detail");
                phone.setNumber(number);
                phone.setProvince(detailObj.getString("province"));
                phone.setCarrier(detailObj.getString("operator"));
                phone.setOwnerCarrier(numberObj.getString("location"));
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return phone;
        }

    • 自定义Handler,用于子线程向主线程发送数据,更新UI:
    @SuppressLint("HandlerLeak")
        class PhoneHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                Phone phone = (Phone) msg.obj;
                showInfo(phone);
            }
        }

      4. 界面展示

    • 查询按钮的点击事件:
    @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.btn_query:
                    Animation animPhone = AnimationUtils.loadAnimation(this, R.anim.edit_phone_anim);
                    edtPhone.startAnimation(animPhone);
    
                    /**
                     * 1.输入不为空则隐藏输入键盘
                     * 2.获取号码转换为Url
                     * 3.获取json
                     * 4.解析json
                     * 5.更新UI
                     */
                    String url;
                    String phoneNumber = edtPhone.getText().toString().trim();
                    if (TextUtils.isEmpty(phoneNumber)) {
                        Toast.makeText(this, getString(R.string.input_no_empty),
                                Toast.LENGTH_SHORT).show();
                    } else {
                        hideKeyboard(edtPhone);
                        url = Consts.BAIDU_PHONE_URL + "?tel=" + phoneNumber;
                        //解析“百度号码归属地API”返回的json数据需要用到电话号码
                        new PhoneThread(url, phoneNumber).start();
                    }
                    break;
                default:
                    break;
            }
        }
    • 真正更新UI的showInfo()方法:
     @SuppressLint("SetTextI18n")
        private void showInfo(Phone phone) {
            tvResult.startAnimation(AnimationUtils.loadAnimation(this, R.anim.tv_phone_result_anim));
            tvNumber.setText(phone.getNumber());
            tvProvince.setText(phone.getProvince());
            tvCarrier.setText(phone.getCarrier());
            tvOwner.setText(phone.getOwnerCarrier());
            if (phone.getCarrier() == null) {
                Toast.makeText(this, R.string.attribution_no_result, Toast.LENGTH_SHORT)
                        .show();
            } else {
                switch (phone.getCarrier()) {
                    case "移动":
                        civIcon.setImageResource(R.drawable.icon_mobile_phone);
                        break;
                    case "电信":
                        civIcon.setImageResource(R.drawable.icon_telecom_phone);
                        break;
                    case "联通":
                        civIcon.setImageResource(R.drawable.icon_unicom_phone);
                        break;
                    default:
                        break;
                }
            }
        }

    完整代码:

    Git地址

    /**
     * @author: yh
     * @date: 2018/5/23 0023
     * @function: 手机号归属地查询
     */
    public class AttributionActivity extends BaseActivity {
        private EditText edtPhone;
        private CircleImageView civIcon;
        private TextView tvResult;
        private TextView tvNumber;
        private TextView tvProvince;
        private TextView tvCarrier;
        private TextView tvOwner;
        private PhoneHandler mPhoneHandler = new PhoneHandler();
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_attribution_layout);
            initView();
        }
    
        private void initView() {
            edtPhone = findViewById(R.id.edt_phone);
            civIcon = findViewById(R.id.civ_carrier_icon);
            tvResult = findViewById(R.id.tv_result);
            tvNumber = findViewById(R.id.tv_number);
            tvProvince = findViewById(R.id.tv_province);
            tvCarrier = findViewById(R.id.tv_carrier);
            tvOwner = findViewById(R.id.tv_owner_carrier);
    
            Button btnQuery = findViewById(R.id.btn_query);
            btnQuery.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.btn_query:
                    Animation animPhone = AnimationUtils.loadAnimation(this, R.anim.edit_phone_anim);
                    edtPhone.startAnimation(animPhone);
    
                    /**
                     * 1.输入不为空则隐藏输入键盘
                     * 2.获取号码转换为Url
                     * 3.获取json
                     * 4.解析json
                     * 5.更新UI
                     */
                    String url;
                    String phoneNumber = edtPhone.getText().toString().trim();
                    if (TextUtils.isEmpty(phoneNumber)) {
                        Toast.makeText(this, getString(R.string.input_no_empty),
                                Toast.LENGTH_SHORT).show();
                    } else {
                        hideKeyboard(edtPhone);
                        url = Consts.BAIDU_PHONE_URL + "?tel=" + phoneNumber;
                        //解析“百度号码归属地API”返回的json数据需要用到电话号码
                        new PhoneThread(url, phoneNumber).start();
                    }
                    break;
                default:
                    break;
            }
        }
    
        class PhoneThread extends Thread {
            private String url;
            private String number;
    
            private PhoneThread(String url, String number) {
                this.url = url;
                this.number = number;
            }
    
            /**
             * 子线程不能直接弹出Toast(其实就是子线程更新UI),方法:
             * 1. Looper.prepare(); Looper.loop();
             * 2. runOnUiThread(new Runnable(){});
             * 3. mHandler.senMessage();
             */
            @Override
            public void run() {
                String result = getJsonFromURL(url);
                if (TextUtils.isEmpty(result)) {
                    Looper.prepare();
                    Toast.makeText(AttributionActivity.this, R.string.attribution_return_null,
                            Toast.LENGTH_SHORT).show();
                    Looper.loop();
                } else {
                    Phone phone = parseJsonToPhone(result, number);
                    Message msg = Message.obtain();
                    msg.obj = phone;
                    mPhoneHandler.sendMessage(msg);
                }
            }
        }
    
        @SuppressLint("HandlerLeak")
        class PhoneHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                Phone phone = (Phone) msg.obj;
                showInfo(phone);
            }
        }
    
    
        private String getJsonFromURL(String urlStr) {
            StringBuilder sb = new StringBuilder();
            try {
                InputStream is = new URL(urlStr).openStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            Log.d("yh", "getJsonFromURL: " + sb.toString());
            return sb.toString();
        }
    
        /**
         * 将获取的json字符串转换为Phone对象
         *
         * @param url
         * @param number
         * @return
         */
        private Phone parseJsonToPhone(String url, String number) {
            Phone phone = new Phone();
            try {
                JSONObject object = new JSONObject(url);
                JSONObject numberObj = object.getJSONObject("response").getJSONObject(number);
                JSONObject detailObj = numberObj.getJSONObject("detail");
                phone.setNumber(number);
                phone.setProvince(detailObj.getString("province"));
                phone.setCarrier(detailObj.getString("operator"));
                phone.setOwnerCarrier(numberObj.getString("location"));
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return phone;
        }
    
        /**
         * 在页面上显示Phone对象的相关信息
         *
         * @param phone
         */
        @SuppressLint("SetTextI18n")
        private void showInfo(Phone phone) {
            tvResult.startAnimation(AnimationUtils.loadAnimation(this, R.anim.tv_phone_result_anim));
            tvNumber.setText(phone.getNumber());
            tvProvince.setText(phone.getProvince());
            tvCarrier.setText(phone.getCarrier());
            tvOwner.setText(phone.getOwnerCarrier());
            if (phone.getCarrier() == null) {
                Toast.makeText(this, R.string.attribution_no_result, Toast.LENGTH_SHORT)
                        .show();
                civIcon.setImageResource(R.drawable.icon_question_phone);
            } else {
                switch (phone.getCarrier()) {
                    case "移动":
                        civIcon.setImageResource(R.drawable.icon_mobile_phone);
                        break;
                    case "电信":
                        civIcon.setImageResource(R.drawable.icon_telecom_phone);
                        break;
                    case "联通":
                        civIcon.setImageResource(R.drawable.icon_unicom_phone);
                        break;
                    default:
                        break;
                }
            }
        }
    
        private void hideKeyboard(View view) {
            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            if (im.isActive(view)) {
                im.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
            }
        }
    
        private Phone parseJsonByFastJson(String t) {
            return new Phone();
        }
    
        private Phone parseJsonByGson(String t) {
            return new Phone();
        }
    }


    展开全文
  • 安卓的基础知识学了一个多月后...除了号码归属地,苹果序列号,身份证号码查询,邮编,快递查询都可以借鉴。不过有些API申请是需要费用的。但是刚开始申请会免费赠送你几次查询。 工具: Android studio 建议使用And

    安卓的基础知识学了一个多月后一直觉得遇到了瓶颈,想写几个APP来证明一下自己,不过后面还是发现自己太年轻了,毕竟技术的路还是很长的,看到这篇博客的朋友希望能从中学到一些东西,这样这篇博客就没有白费。

    除了号码归属地,苹果序列号,身份证号码查询,邮编,快递查询都可以借鉴。不过有些API申请是需要费用的。但是刚开始申请会免费赠送你几次查询。

    工具:

    Android studio

    建议使用Android studio

    准备工作:

    去聚合数据申请一个号码归属地查询的API,网址:https://www.juhe.cn/(申请过程百度上都有)


    具体实现:

    这是个典型的客户端请求服务器数据,服务器返回json数据给客户端,然后再经由客户端对json格式的数据进行解析的例子。

    JSON返回示例:

    {
    "resultcode":"200",
    "reason":"Return Successd!",
    "result":{
        "province":"浙江",
        "city":"杭州",
        "areacode":"0571",
        "zip":"310000",
        "company":"中国移动",
        "card":"移动动感地带卡"
    }
    }
    这个json比较简单,直接用JSONobject进行解析获取数据即可。
    界面代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.administrator.num_find.MainActivity">
    
        <EditText
            android:layout_marginTop="20dp"
            android:id="@+id/editText"
            android:text="请输入号码"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/button"
            android:text="查询"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_below="@id/editText"
            />
        <LinearLayout
            android:id="@+id/line"
            android:layout_below="@id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="移动号码归属地支持号段:\n
    134 135 136 137 138 139 150 151 152 157 158 159 182 183 187 188 147\n
    联通号码归属地支持号段:\n
    130 131 132 155 156 186 145\n
    电信号码归属地支持号段:\n
    133 153 189 180\n
    移动运营商:\n
    170\n"
                />
        </LinearLayout>
    
    <RelativeLayout
        android:id="@+id/lineR"
        android:layout_below="@id/line"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp">
            <TextView
            android:id="@+id/provinceCity"
                android:layout_marginLeft="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </RelativeLayout>
            <RelativeLayout
                android:layout_below="@id/lineR"
    
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/relativeLayout"></RelativeLayout>
    
        <TextView
            android:id="@+id/zip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
    
            android:layout_alignTop="@+id/lineR"
            android:layout_toRightOf="@+id/button"
            android:layout_toEndOf="@+id/button" />
    
        <TextView
            android:id="@+id/citycode"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
    
            android:layout_alignTop="@+id/lineR"
            android:layout_toLeftOf="@+id/button"
            android:layout_toStartOf="@+id/button" />
    
        <TextView
            android:id="@+id/card"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/relativeLayout"
            android:layout_alignLeft="@+id/zip"
            android:layout_alignStart="@+id/zip" />
    
        <TextView
            android:id="@+id/company"
    
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/relativeLayout"
            android:layout_toRightOf="@+id/lineR"
            android:layout_toEndOf="@+id/lineR" />
    </RelativeLayout>
    
    本人UI不大好,界面有点丑,可以后期优化
    
    
    在点击查询按钮后向服务器发出请求,此处开了个线程。有安卓基础的你懂的,因为要将数据显示到UI上。
    接收数据后对得到的json进行解析,然后显示到界面上,这个程序就完成了。
    代码:
    package com.example.administrator.num_find;
    
    import android.app.Activity;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class MainActivity extends Activity {
        private Button button;
        private EditText editText;
        private String NumString;
    
        private String address = null;
        private String response = null;
    
        private TextView provinceCity;
        private TextView cityCode;
        private TextView zip1;
        private TextView card1;
        private  TextView company1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            button = (Button) findViewById(R.id.button);
            editText = (EditText) findViewById(R.id.editText);
            provinceCity = (TextView)findViewById(R.id.provinceCity) ;
            cityCode = (TextView)findViewById(R.id.citycode);
            zip1 = (TextView)findViewById(R.id.zip);
            card1 = (TextView)findViewById(R.id.card);
            company1= (TextView)findViewById(R.id.company);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            HttpURLConnection connection = null;
                            NumString = editText.getText().toString();
                            if (NumString == null) {
    
                                return;
                            }
                            address = "http://apis.juhe.cn/mobile/get?phone=" + NumString + "&key=你申请的api key";
                            System.out.println("NUM" + NumString);
                            System.out.println("addr" + address);
                            InputStream inputStream = null;
                            try {
                                URL url = new URL(address);
                                connection = (HttpURLConnection) url.openConnection();
                                connection.setRequestMethod("GET");
                                connection.setReadTimeout(8000);
                                connection.setConnectTimeout(8000);
                                inputStream = connection.getInputStream();
                                if (inputStream == null)
                                    System.out.println("in null");
                                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                                StringBuilder builder = new StringBuilder();
                                String line;
                                while ((line = reader.readLine()) != null) {
                                    builder.append(line);
                                }
                                if (builder!=null){
                                    response = builder.toString();
                                }
                                System.out.println(builder);
                                Json(response);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
    
                        }
                    }).start();
                }
            });
        }
        private void Json(final String response) {
    
            try {
    
                runOnUiThread(new Runnable() {
                    JSONObject jsonobject = new JSONObject(response);
                    JSONObject result = jsonobject.getJSONObject("result");
                   // System.out.println("result"+result);
                    String prvoince = result.getString("province");
                   // System.out.println("result"+prvoince);
                    String city = result.getString("city");
                    String areacode = result.getString("areacode");
                    String zip = result.getString("zip");
                    String company = result.getString("company");
                    String card = result.getString("card");
                    @Override
                    public void run() {
                        provinceCity.setText(prvoince);
                        cityCode.setText(areacode);
                        zip1.setText(zip);
                        company1.setText(company);
                        card1.setText(card);
                    }
                });
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    
    

    bug还有很多,例如没有对号码进行判断,可用正则表达式对后期进行优化。

    展开全文
  • 需要使用到WebService的服务,这里选择www.webxml.com.cn提供的服务来查询电话号码归属地,使用方法网页上有介绍,这里使用一个实例来演示如何在Android下实现电话号码归属地的查询: 0.使用webxml的soap方式:...
  • 1.首先将我们的归属地的数据库放入assets/address.db 2.然后需要将我们的数据库文件copy到 data/data/com.ittest.address/files/address.dbprivate void copyDB(String dbName) {//dbName文件名 File destFile = ...
  • 目前手机里面的号码归属查询主要是通过两种方式:1.联网查询,2.匹配本机归属地数据库。 我认为两种结合方式最好,在本地数据库中匹配不到的在进行联网查询,能大大增加匹配效果,并且不用过于增加本地数据库容量...
  • 由于本人在蓝牙项目的开发中,需要在当拨打或接听电话时弹出的通话界面中需要显示其该号码的归属地等信息,所以今天决定将这个关于如何获取手机号码归属地的使用方法总结下来,以便将来所需,利人也利己。...
  • 前一篇文章已经提供了电话号码的归属地查询功能,现在要做的,就是在打电话和来电显示的时候,显示一个电话归属地提示框,就像这样: 感觉很简单是不是,No,这个还费了一点功夫,首先是监听来电、去电...
  • 1、此规则能查询:手机号码、报警电话、模拟器、客服电话、区号是4位的长途电话,区号是3位的长途电话
  • 需要查询手机号的API:https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=18888888888导入...新建一个电话的model: package zhku.edu.searchphone.model; /** * Created by manRED on 2018/2/21. ...
  • 应用网上的电话归属地db数据进行匹配查询。 如若查不到可用此地址,包含3W+数据匹配。资源地址:https://download.csdn.net/download/lemon_husky/11942253 第一步:下载DB数据库资源放入APP得assets文件夹中,...
  • 学习目标:实现归属查询,通过OkHttp网络框架请求手机号数据,并能掌握流行的MVP设计模式以及如何使用目前主流的Json和Gson解析框架。 难度点:在gson解析时,遇到了key会动态变化的json数据,如何处理花费了很长...
  • 归属地数据源 http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx webxml网站还支持其他请求方式 如SOAP等等 界面比较简单 package com.sphere.guishudi; import java.util....
  • 题记自研的电话应用中,有两处使用了号码归属地,一处是通话记录页,一处是通话界面;那么它们是如何实现的呢?下面进行一步一步的分析。Dialer使用号码归属地 通话记录页的号码归属地 通过查询calls表中的Calls....
  • <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_par
  • android本地使用的电话归属地数据库,存放在app的数据库中方便本地查询
1 2 3 4 5 ... 20
收藏数 2,098
精华内容 839
关键字:

电话归属查询android