欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

大作业(二)

程序员文章站 2022-06-10 16:56:50
3.2使用http访问网络 在android上发送http请求的方式一般有两个,httpurlconnection和httpclient,在这里我们使用httpurlconnec...

3.2使用http访问网络

android上发送http请求的方式一般有两个,httpurlconnection和httpclient,在这里我们使用httpurlconnection。

首先需要获取到httpurlconnection的实例,一般只需new出一个url对象,并传入目标的网络地址,然后调用一下openconnection()方法即可,如下所示:

url url = new url(“https://www.baidu.com”);

httpurlconnection connection =(httpurlconnection) url.openconnection();

得到了httpurlconnection的实例之后,我们可以设置一下http请求所使用的方法。常用的方法主要有两个,get和post。get表示希望从服务器那里获取数据,而post则表示希望提交数据给服务器。接下来就可以进行设置连接超时、读取超时的毫秒数;之后再调用getinputstream()方法就可以获取到服务器返回的输入流了,剩下的任务就是对输入流进行读取;最后将连接关闭掉。

下面我们就在com.wyd.search.common包中新建httputils.java类,代码如下所示:

public final class httputils {
    private static final string log_tag = "httputils connect tag";

    public static string openurl(string url, string method, bundle params,
        string enc) {
        string response = null;

        if (method.equals("get")) {
            url = url + "?" + encodeurl(params);
        }

        try {
            log.d(log_tag, "url:" + url);

            httpurlconnection conn = (httpurlconnection) new url(url).openconnection();
            conn.setrequestproperty("user-agent",
                system.getproperties().getproperty("http.agent"));
            conn.setreadtimeout(10000); //设置超时时间

            if (method.equals("post")) {
                conn.setrequestmethod("post");
                conn.setdooutput(true);
                conn.getoutputstream().write(encodeurl(params).getbytes("utf-8"));
            }

            response = read(conn.getinputstream(), enc);
        } catch (exception e) {
            log.e(log_tag, e.getmessage());
            throw new runtimeexception(e.getmessage(), e);
        }

        return response;
    }

    private static string read(inputstream in, string enc)
        throws ioexception {
        stringbuilder sb = new stringbuilder();
        inputstreamreader isr = null;
        bufferedreader r = null;

        if (enc != null) {
            //按指定的编码读入流
            r = new bufferedreader(new inputstreamreader(in, enc), 1000);
        } else {
            //按默认的编码读入
            r = new bufferedreader(new inputstreamreader(in), 1000);
        }

        for (string line = r.readline(); line != null; line = r.readline()) {
            sb.append(line);
        }

        in.close();

        return sb.tostring();
    }

    public static string encodeurl(bundle parameters) {
        if (parameters == null) {
            return "";
        }

        stringbuilder sb = new stringbuilder();
        boolean first = true;

        for (string key : parameters.keyset()) {
            if (first) {
                first = false;
            } else {
                sb.append("&");
            }

            sb.append(key + "=" + parameters.getstring(key));
        }

        return sb.tostring();
    }
}

3.3查询活动的搜索条件

我们在查询的时候,会有一些限制条件,比如说查询的ip是否合法、手机号码位数是否够......因此要进行一些限制。

我们在com.wyd.search.common包中新建activityutils类,代码如下:

public final class activityutils {
    public static void showdialog(context context, string button, string title,
        string message) {
        new alertdialog.builder(context).settitle(title).setmessage(message)
                                        .setneutralbutton(button, null).create()
                                        .show();
    }

    //校验str是否为空或为""
    public static boolean validatenull(string str) {
        if ((str == null) || str.equals("")) {
            return false;
        } else {
            return true;
        }
    }

    //校验str中是否全部是数字,用到了正则表达式
    public static boolean validatenumber(string str) {
        pattern pattern = pattern.compile("[0-9]");
        matcher matcher = pattern.matcher(str);

        return matcher.matches();
    }

    //校验ip是否合法
    public static boolean validateip(string str) {
        pattern pattern = pattern.compile("[0-9],.");
        matcher matcher = pattern.matcher(str);

        return matcher.matches();
    }
}

4 查询工具创建

在第二阶段,我们进行具体实体类的,首先我们需要申请相应的接口数据,这个我们可以轻松在聚合数据网站上得到,然后把具体的功能一个个实现,我们在第一步新建的包中新建相应的查询实体类。具体实现如下:

4.1快递单号查询

在com.wyd.search.ems包中新建ems.java类,代码如下:

public class ems implements serializable {
private static final long serialversionuid = 1l;
// 变量声明
private string message; //消息体
private string time; //时间
private string context; //状态
private string status; //返回值状态:0,查询失败;1:查询成功
private string company; //快递公司名称
private string order; //单号

接下来新建快递查询的监听类emslistener,代码如下:

public class emssearch extends activity {
    private spinner emscompanies;
    private edittext emsorder;
    private resources res;
    private string[] emscodes;
    private int pos = 0;
    private string selectedcom;
    private search search;@override public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        this.requestwindowfeature(window.feature_no_title);
        setcontentview(r.layout.ems);
        res = this.getresources();
        emscodes = res.getstringarray(r.array.ems_code);
        emsorder = (edittext) this.findviewbyid(r.id.ems_order);
        emscompanies = (spinner) this.findviewbyid(r.id.ems_com);
        arrayadapter < charsequence > adapter = arrayadapter.createfromresource(this, r.array.ems_company, android.r.layout.simple_spinner_item);
        adapter.setdropdownviewresource(android.r.layout.simple_spinner_dropdown_item);
        emscompanies.setadapter(adapter);
        emscompanies.setonitemselectedlistener(selectedlistener);
        search = new search();
    }
    private adapterview.onitemselectedlistener selectedlistener = new adapterview.onitemselectedlistener() {
        public void onitemselected(adapterview < ?>parent, view v, int position, long id) {
            // 用户选择了,记录下用户选择的公司所对应的代码
            pos = position;
            selectedcom = (string) parent.getitematposition(position);
        }
        public void onnothingselected(adapterview < ?>parent) {
            // todo auto-generated method stub
        }
    };
    public string getcode() {
        return emscodes[pos - 1]; //因为城市spinner中多了一个请选择
    }
    //检验是否选择了一个快递公司
    public boolean validateselect() {
        if (pos < 1 || pos > emscodes.length) {
            return false;
        } else {
            return true;
        }
    }
    public void onclick(view v) {
        if (v.getid() == r.id.ems_search) {
            string order = this.emsorder.gettext().tostring().trim();
            if (this.validateselect()) {
                if (activityutils.validatenull(order)) {
                    //校验成功
                    string companycode = this.getcode();
                    bundle bundle = new bundle();
                    bundle.putstring("company", selectedcom);
                    bundle.putstring("order", order);
                    this.getintent().putextras(bundle); //记录下公司和单号
                    emslistener listener = new emslistener(this);
                    search.asyncrequest(companycode, order, listener);
                } else {
                    activityutils.showdialog(this, res.getstring(r.string.ok), res.getstring(r.string.tip), res.getstring(r.string.ems_order_error));
                }
            } else {
                activityutils.showdialog(this, res.getstring(r.string.ok), res.getstring(r.string.tip), res.getstring(r.string.ems_noselect));
            }
        }
    }
}

最后就是查询后返回相应的数据,新建searchresult.java,代码如下:

public class searchresult extends activity {

    private textview emscompany,
    emsorder,
    emstime,
    emscontext;
    private resources res;
    public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        this.requestwindowfeature(window.feature_no_title);
        setcontentview(r.layout.ems_info);
        this.emscompany = (textview) this.findviewbyid(r.id.ems_company);
        this.emsorder = (textview) this.findviewbyid(r.id.ems_order);
        this.emstime = (textview) this.findviewbyid(r.id.ems_time);
        this.emscontext = (textview) this.findviewbyid(r.id.ems_context);
        res = this.getresources();
        this.showresult();
    }
    private void showresult() {
        bundle bundle = this.getintent().getextras();
        ems ems = (ems) bundle.getserializable("ems");
        if (ems != null) {
            if (ems.getstatus().equals("1")) {
                this.emscompany.settext(ems.getcompany());
                this.emsorder.settext(ems.getorder());
                this.emstime.settext(ems.gettime());
                this.emscontext.settext(ems.getcontext());
            } else {
                activityutils.showdialog(this, res.getstring(r.string.ok), res.getstring(r.string.tip), ems.getmessage());
            }
        } else {
            activityutils.showdialog(this, res.getstring(r.string.ok), res.getstring(r.string.tip), res.getstring(r.string.ems_fail));
        }
    }
}

4.1手机号归属地查询

我们首先在com.wyd.search.telephone包中新建手机号归属地查询的实体类telephone.java,代码如下:

public class telephone implements serializable{
private static final long serialversionuid = 1l;
private string mobile; //
private string queryresult; //返回结果
private string province; //省份
private string city; //城市
private string areacode; //区号
private string postcode; //
private string corp; //
private string card; //卡类型

我们可在聚合数据网站上申请数据,然后应用网站提供的接口,通过对申请的数据得知,手机号码的查询涵盖中国移动、中国联通和中国电信,查询的结果包括省份、城市、区号和卡类型。

接下来新建快递查询的监听类telephonelistener,代码如下:

public class telephonelistener implements requestlistener {
    private telephonesearch context;
    private progressdialog progress;
    private resources res;
    public telephonelistener(telephonesearch context) {
        this.context = context;
        res = context.getresources();
        progress = progressdialog.show(context, res.getstring(r.string.tel_searching), res.getstring(r.string.getting));
        progress.show();
    }@override public void oncomplete(final string result) {
        this.context.runonuithread(new runnable() {@override public void run() {
                intent intent = new intent();
                bundle bundle = new bundle();
                bundle.putserializable("telephone", parsejson(result));
                intent.putextras(bundle);
                intent.setclass(context, searchresult.class);
                progress.dismiss();
                context.startactivity(intent);
            }
        });
    }
    public void onexception(exception e) {
        this.context.runonuithread(new runnable() {
            public void run() {
                if (progress != null) {
                    progress.dismiss();
                }
                activityutils.showdialog(context, res.getstring(r.string.ok), res.getstring(r.string.tip), res.getstring(r.string.get_nothing));
            }
        });
    }
    public telephone parsejson(string jsonstr) {
        telephone tel = null;
        jsonstr = jsonstr.substring(14, jsonstr.length() - 2);
        try {
            tel = new telephone();
            jsonobject jsonobj = new jsonobject(jsonstr);
            tel.setmobile(jsonobj.getstring("mobile"));
            tel.setqueryresult(jsonobj.getstring("queryresult"));
            tel.setprovince(jsonobj.getstring("province"));
            tel.setcity(jsonobj.getstring("city"));
            tel.setareacode(jsonobj.getstring("areacode"));
            tel.setpostcode(jsonobj.getstring("postcode"));
            tel.setcorp(jsonobj.getstring("corp"));
            tel.setcard(jsonobj.getstring("card"));
        } catch(jsonexception e) {
            log.e(log_tag, e.getmessage());
        }
        return tel;
    }
    private static final string log_tag = "telephonelistener";
}

我们从聚合数据网站上获得的数据可以使用xml和json两种方法解析,这里我们解析成json格式数据,因为相对于xml,json的主要优势在于它的体积更小,在网络上传输的时候可以更省流量。

然而,解析json数据的方法也有很多,我们使用jsonobject,首先将http请求的地址加上,然后在得到了服务器返回的数据后调用parsejsonwithjsonobject()方法来解析数据。每个jsonobject对象中包含mobile、province、areacode和card等这些数据,接下来只需要调用getstring()方法将这些数据取出,并打印出来即可。

最后就是更新ui的问题,要将解析出来的数据显示出来,代码如下:

public class searchresult extends activity {
    private textview mobile,
    province,
    city,
    areacode,
    postcode,
    card;
    public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        this.requestwindowfeature(window.feature_no_title);
        setcontentview(r.layout.telephone_info);
        mobile = (textview) this.findviewbyid(r.id.telephone_mobile);
        province = (textview) this.findviewbyid(r.id.telephone_province);
        city = (textview) this.findviewbyid(r.id.telephone_city);
        areacode = (textview) this.findviewbyid(r.id.telephone_areacode);
        postcode = (textview) this.findviewbyid(r.id.telephone_postcode);
        card = (textview) this.findviewbyid(r.id.telephone_card);
        this.showresult();
    }

    public void showresult() {
        intent intent = this.getintent();
        bundle bundle = intent.getextras();
        telephone tel = (telephone) bundle.getserializable("telephone");
        if (tel != null) {
            mobile.settext(tel.getmobile());
            province.settext(tel.getprovince());
            city.settext(tel.getcity());
            areacode.settext(tel.getareacode());
            postcode.settext(tel.getpostcode());
            card.settext(tel.getcard());
        }
    }
}

4.3天气的查询

我们首先在com.wyd.search.weather包中新建手机号归属地查询的实体类weather.java,代码如下:

public class weather implements serializable {
private static final long serialversionuid = 13835783478884l;
private string day; //星期
private string date; //日期
private string low; //最低温度
private string high; //最高温度
private string code; //天气状况码
private string text; //天气状况码,对应的天气类型

接着我偶们继续新建search类,代码如下:

public class search {
    //这里使用的是雅虎天气查询url
    private static final string http_url = "https://weather.yahooapis.com/forecastrss";
    private static final string method = "get";
    private static final string log_tag = "com.search.weather.search";

    public string request(string woeid) {
        if (woeid != null) {
            bundle params = new bundle();
            params.putstring("w", woeid); //城市对应的id
            params.putstring("u", "c"); //华氏温度是f,摄氏温度是c。这里采用摄氏度
            return httputils.openurl(http_url, method, params, null);
        } else {
            return null;
        }
    }
    //异步封装
    public void asyncrequest(final string city, final requestlistener listener) {
        //子线程中更新ui
        new thread(new runnable() {@override public void run() {
                try {
                    string response = request(city);
                    listener.oncomplete(response);
                } catch(exception e) {
                    log.e(log_tag, e.getmessage());
                    listener.onexception(e);
                }
            }
        }).start();
    }
}

下面创建weatherlistener.java,代码如下:

public class weatherlistener implements requestlistener {
    private weathersearch context;
    private progressdialog progress;
    private resources res;
    public weatherlistener(weathersearch context) {
        this.context = context;
        res = this.context.getresources();
        this.progress = progressdialog.show(context, res.getstring(r.string.wea_searching), res.getstring(r.string.getting));
        this.progress.show();
    }
    public void oncomplete(final string result) {
        context.runonuithread(new runnable() {
            public void run() {
                try {
                    inputstream is = null;
                    is = new bytearrayinputstream(result.getbytes("utf-8"));
                    list < weather > results = weatherpullparser.getdata(is);
                    if (results.size() >= 2) {
                        weather today = results.get(0);
                        weather tomorrow = results.get(1);
                        intent intent = new intent();
                        bundle bundle = new bundle();
                        bundle.putserializable("today", today);
                        bundle.putserializable("tomorrow", tomorrow);
                        intent.putextras(bundle);
                        intent.setclass(context, searchresult.class);
                        if (progress != null) {
                            progress.dismiss();
                        }
                        context.startactivity(intent);
                    } else {
                        if (progress != null) {
                            progress.dismiss();
                        }
                        activityutils.showdialog(context, res.getstring(r.string.ok), res.getstring(r.string.tip), res.getstring(r.string.xml_error));
                    }

                } catch(unsupportedencodingexception e) {
                    log.e(log_tag, e.getmessage());
                    activityutils.showdialog(context, res.getstring(r.string.ok), res.getstring(r.string.tip), res.getstring(r.string.xml_error));
                }
            }
        });
    }
    public void onexception(final exception e) {
        context.runonuithread(new runnable() {@override public void run() {
                if (progress != null) {
                    progress.dismiss();
                }
                activityutils.showdialog(context, res.getstring(r.string.ok), res.getstring(r.string.tip), res.getstring(r.string.get_nothing));
            }
        });
    }
    private static final string log_tag = "weatherlistener";
}

然后我们就要对服务器返回的数据进行解析了,由于这里我们用的是雅虎天气提供的数据,所以这里我们运用pull的解析方式。

新建weatherpullparser.java,代码如下:

public class weatherpullparser {
    public static list < weather > getdata(inputstream reader) {
        list < weather > result = null;
        xmlpullparser parser = xml.newpullparser();
        weather wea = null;
        string tagname = null;
        try {
            parser.setinput(reader, "utf-8");
            int eventcode = parser.geteventtype(); //返回事件码类型
            while (eventcode != xmlpullparser.end_document) {
                switch (eventcode) {
                case xmlpullparser.start_document:
                    //初始化
                    result = new arraylist < weather > ();
                    break;
                case xmlpullparser.start_tag:
                    //一个元素的开始
                    tagname = parser.getname(); //获取当前标签的名称
                    if (tagname.equalsignorecase("forecast")) {
                        wea = new weather();
                        wea.setday(parser.getattributevalue(null, "day"));
                        wea.setdate(parser.getattributevalue(null, "date"));
                        wea.setlow(parser.getattributevalue(null, "low"));
                        wea.sethigh(parser.getattributevalue(null, "high"));
                        wea.settext(parser.getattributevalue(null, "text"));
                        wea.setcode(parser.getattributevalue(null, "code"));
                        result.add(wea);
                    }
                    break;
                }
                eventcode = parser.next(); //解析下一个元素
            }
        } catch(exception e) {
            log.e("weatherpullparser", e.getmessage());
        }
        return result;
    }
}

最后就是就是就将解析出阿里的数据显示出来,在这个包下新建searchresult.java,代码如下:

public class searchresult extends activity {
    private textview today,
    tomorrow,
    low1,
    low2,
    high1,
    high2;
    private resources res;
    public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        this.requestwindowfeature(window.feature_no_title);
        setcontentview(r.layout.weather_info);
        today = (textview) this.findviewbyid(r.id.wea_today);
        tomorrow = (textview) this.findviewbyid(r.id.wea_tomorrow);
        low1 = (textview) this.findviewbyid(r.id.wea_low);
        low2 = (textview) this.findviewbyid(r.id.wea_low2);
        high1 = (textview) this.findviewbyid(r.id.wea_high);
        high2 = (textview) this.findviewbyid(r.id.wea_high2);
        res = this.getresources();
        this.showresult();
    }

    private void showresult() {
        intent intent = this.getintent();
        bundle bundle = intent.getextras();
        weather w_today = (weather) bundle.getserializable("today");
        weather w_tomorrow = (weather) bundle.getserializable("tomorrow");
        string unit = res.getstring(r.string.wea_unit);
        if (w_today != null) {
            string today_codition = this.getcondition(w_today.getcode()); //获取code对应的天气
            today.settext(today_codition);
            low1.settext(w_today.getlow() + unit);
            high1.settext(w_today.gethigh() + unit);
        }
        if (w_tomorrow != null) {
            string tommorrow_condition = this.getcondition(w_tomorrow.getcode());
            tomorrow.settext(tommorrow_condition);
            low2.settext(w_tomorrow.getlow() + unit);
            high2.settext(w_tomorrow.gethigh() + unit);
        }
    }
    //根据代码获取对应的天气信息。在weather的string-array中匹配
    private string getcondition(string code) {

        string[] weathers = res.getstringarray(r.array.weather);
        int temp = integer.parseint(code);
        if (temp < 48 && temp >= 0) {
            return weathers[temp];
        }
        return res.getstring(r.string.wea_undefine);
    }
}