Android:手机号码归属地查询

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

获取源码

效果图:

开发思路:

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

具体实现:

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


猜你喜欢

转载自blog.csdn.net/weixin_39272004/article/details/80500018