首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在线请求天气API,并解析其中的json数据予以显示

在线请求天气API,并解析其中的json数据予以显示

作者头像
爱因斯坦福
发布2018-09-10 16:50:35
5.7K0
发布2018-09-10 16:50:35
举报
文章被收录于专栏:KK的小酒馆KK的小酒馆

Android网络与数据存储

第二章学习


在线请求天气API,并解析其中的json数据予以显示####

概要:

请求互联网信息提供商并取得返回的数据使用到HttpURLConnection,等待数据下载成功得到的Json,把它 解析成程序可利用的数据,使用到JSONObject


使用和风天气的API作为范例,只要注册就可免费用的还凑合的天气预报平台 http://www.heweather.com/

1.HttpURLConnection类的使用#####

本来Android发送Http请求拥有两种方式,分别是HttpURLConnection和HttpClient,但在Android 6.0时,HttpClient已经彻底从SDK里消失了,虽然是个重要的类,包括如今的阿里云服务中,也依然给我们提供了基于HttpClient的API请求SDK,由于版本问题,我也难以使用。(此处花费一整天用于折腾阿里云市场里购买的天气预报API,卒。)

所以,本着追赶潮流的思想,这次的App只使用HttpURLConnection进行网络请求。

0.生成HttpURLConnection对象:

API接口: https://api.heweather.com/x3/weather?cityid=城市ID&key=你的认证key

注册好以后,替换掉“城市ID”以及“你的认证key”字段即可使用

URL url = new URL("https://api.heweather.com/x3/weather?cityid=城市ID&key=你的认证key");
//将字符串转化为URL对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

1.给HttpURLConnection对象设置请求方式: 接下来给这个connection设置一种向网络服务器请求的方式,实际开发中我们用得较多的方式是Get和Post:

connection.setRequestMethod("GET");
  • Get:请求获取Request-URI所标识的资源
  • POST:在Request-URI所标识的资源后附加新的数据
  • HEAD 请求获取由Request-URI所标识的资源的响应信息报头
  • PUT:请求服务器存储一个资源,并用Request-URI作为其标识
  • DELETE:请求服务器删除Request-URI所标识的资源
  • TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断
  • CONNECT:保留将来使用
  • OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项

说得太难懂,用GET和POST举个例子:

  • GET:在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分隔, 但数据容量通常不能超过2K,比如: “https://api.heweather.com/x3/weather?cityid=城市ID&key=你的认证key” 这种就是GET
  • POST: 这个则可以在请求的实体内容中向服务器发送数据,传输没有数量限制

2.定制HttpURLConnection并获取链接状态:

设置连接超过8000毫秒则为超时状态,同理还有读取超时

connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);

还可以获取当前连接的状态

int responseCode = connection.getResponseCode();

此时responseCode将会有非常多种数字有可能被返回,如“404”

  • 100~199 : 成功接受请求,客户端需提交下一次请求才能完成整个处理过程
  • 200: OK,客户端请求成功
  • 300~399:请求资源已移到新的地址(302,307,304)
  • 401:请求未授权,改状态代码需与WWW-Authenticate报头域一起使用
  • 403:Forbidden,服务器收到请求,但是拒绝提供服务
  • 404:Not Found,请求资源不存在,这个就不用说啦
  • 500:Internal Server Error,服务器发生不可预期的错误
  • 503:Server Unavailable,服务器当前不能处理客户端请求,一段时间后可能恢复正常

当然最好我们的返回代码是200,此时就成功了

3.获取输入流并转换为String类:

try {
    InputStream in = connection.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
    StringBuilder response = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
            response.append(line).append("\r\n");
        }
    reader.close();
        } catch (Exception e) {
         e.printStackTrace();
     } finally {
     if (connection != null) {
     connection.disconnect();
     }
}

从网络请求的返回中获取输入流,并进行IO操作,结束后记得关掉BufferedReader和HttpURLConnection实例。此时,完成了一系列的操作后,我们取得了从网络返回的数据。

咳咳,插句题外话,当然也可以将返回数据解析为比特流返回

public class ToByteUtil {
    //从流中读取数据
    public static byte[] read(InputStream in) throws Exception{
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while((len = in.read(buffer)) != -1)
        //一行行读取,只要不为-1则表示没读完
        {
            out.write(buffer,0,len);
        }
        in.close();
        return out.toByteArray();
    }
}

以上成功获得了一个String,当前的API商提供给我们的是Json文件,Json文件并不会直接被系统识别,需要解析出其中的每一项,然后利用起来;

我们可以将对数据库进行的操作封装为一系列方法,如下:

4.看看Json的格式:

{"HeWeather data service 3.0":[{"basic":{"city":"大连","cnty":"中国","id":"CN101070201","lat":"38.944000","lon":"121.576000","update":{"loc":"2015-07-15 10:43","utc":"2015-07-15 02:46:14"}},"status":"ok","aqi":{"city":{"aqi":"71","co":"1","no2":"75","o3":"101","pm10":"89","pm25":"44","qlty":"良","so2":"27"}},"alarms":[{"level":"橙色","stat":"预警中","title":"辽宁省大连市气象台发布高温橙色预警","txt":"大连市气象台2015年07月14日13时31分发布高温橙色预警信号:预计14日下午至傍晚,旅顺口区局部最高气温将达到37℃以上,请注意防范。","type":"高温"}],"now":{"cond":{"code":"100","txt":"晴"},"fl":"33","hum":"28","pcpn":"0","pres":"1005","tmp":"32","vis":"10","wind":{"deg":"350","dir":"东北风","sc":"4-5","spd":"11"}},"daily_forecast":[{"date":"2015-07-15","astro":{"sr":"04:40","ss":"19:19"},"cond":{"code_d":"100","code_n":"101","txt_d":"晴","txt_n":"多云"},"hum":"48","pcpn":"0.0","pop":"0","pres":"1005","tmp":{"max":"33","min":"24"},"vis":"10","wind":{"deg":"192","dir":"东南风","sc":"4-5","spd":"11"}},{"date":"2015-07-16","astro":{"sr":"04:40","ss":"19:18"},"cond":{"code_d":"104","code_n":"104","txt_d":"阴","txt_n":"阴"},"hum":"82","pcpn":"2.7","pop":"82","pres":"1008","tmp":{"max":"27","min":"23"},"vis":"10","wind":{"deg":"116","dir":"东南风","sc":"4-5","spd":"11"}},{"date":"2015-07-17","astro":{"sr":"04:41","ss":"19:17"},"cond":{"code_d":"101","code_n":"100","txt_d":"多云","txt_n":"晴"},"hum":"70","pcpn":"0.1","pop":"11","pres":"1006","tmp":{"max":"28","min":"22"},"vis":"10","wind":{"deg":"172","dir":"西风","sc":"4-5","spd":"11"}}],"hourly_forecast":[{"date":"2015-07-15 10:00","hum":"51","pop":"0","pres":"1006","tmp":"32","wind":{"deg":"127","dir":"东南风","sc":"微风","spd":"4"}},{"date":"2015-07-15 13:00","hum":"49","pop":"0","pres":"1005","tmp":"34","wind":{"deg":"179","dir":"南风","sc":"微风","spd":"7"}},{"date":"2015-07-15 16:00","hum":"54","pop":"0","pres":"1005","tmp":"31","wind":{"deg":"216","dir":"西南风","sc":"微风","spd":"6"}},{"date":"2015-07-15 19:00","hum":"62","pop":"0","pres":"1005","tmp":"29","wind":{"deg":"192","dir":"西南风","sc":"微风","spd":"4"}},{"date":"2015-07-15 22:00","hum":"62","pop":"0","pres":"1006","tmp":"26","wind":{"deg":"154","dir":"东南风","sc":"微风","spd":"10"}}],"suggestion":{"comf":{"brf":"较舒适","txt":"白天天气晴好,您在这种天气条件下,会感觉早晚凉爽、舒适,午后偏热。"},"cw":{"brf":"较不宜","txt":"较不宜洗车,未来一天无雨,风力较大,如果执意擦洗汽车,要做好蒙上污垢的心理准备。"},"drsg":{"brf":"炎热","txt":"天气炎热,建议着短衫、短裙、短裤、薄型T恤衫等清凉夏季服装。"},"flu":{"brf":"少发","txt":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。"},"sport":{"brf":"较适宜","txt":"天气较好,但风力较大,推荐您进行室内运动,若在户外运动请注意防风。"},"trav":{"brf":"适宜","txt":"天气较好,是个好天气哦。稍热但是风大,能缓解炎热的感觉,适宜旅游,可不要错过机会呦!"},"uv":{"brf":"强","txt":"紫外线辐射强,建议涂擦SPF20左右、PA++的防晒护肤品。避免在10点至14点暴露于日光下。"}}}]}

妈呀密密麻麻的,我有密集恐惧症啊…………为了减少长度,我压缩了json文件,看不清,没关系,复制到http://www.runoob.com/jsontool 网页上就可以清楚看见文件的结构

{"now":{"cond":{"code":"100","txt":"晴"},"fl":"33","hum":"28","pcpn":"0","pres":"1005","tmp":"32","vis":"10","wind":{"deg":"350","dir":"东北风","sc":"4-5","spd":"11"}}}

json文件都是以键值对进行保存“键:值”,而如果值是个数组,则按如下表示

{Key:["status":"ok","city":"大连"]}

稍加观察,并不复杂

5.解析数据:

public class JsonUtil {
    public static ContentValues parseJSONToWeather(String jsonData) {
        ContentValues contentValues = new ContentValues();
        try {
            JSONObject jsonObject = new JSONObject(jsonData);
//此时将字符串转变为一个JSONObject实例,形象的说法就是{"key":"value"}这就是个object
            JSONArray jsonArray = jsonObject.getJSONArray("HeWeather data service 3.0");
//这里在此object中get了一个数组(JSONArray),输入这个数组的key,即可得到
            JSONObject allJsonObject = jsonArray.getJSONObject(0);
            String status = allJsonObject.getString("status");
            if (status.equals("ok")) {
                JSONObject basic = allJsonObject.getJSONObject("basic");
                contentValues.put("id", basic.getString("id"));
                contentValues.put("city", basic.getString("city"));
                JSONObject now = allJsonObject.getJSONObject("now");
                JSONObject now_cond = now.getJSONObject("cond");
                contentValues.put("now_cond_txt", now_cond.getString("txt"));
                contentValues.put("now_tmp", now.getString("tmp"));
                JSONArray daily_forecast = allJsonObject.getJSONArray("daily_forecast");
                for (int i = 0; i < 5; i++) {
                    String num = null;
                    switch (i){
                        case 0:
                            num = "first";
                            break;
                        case 1:
                            num = "second";
                            break;
                        case 2:
                            num = "third";
                            break;
                        case 3:
                            num = "fourth";
                            break;
                        case 4:
                            num = "fifth";
                            break;
                    }
                    JSONObject data = daily_forecast.getJSONObject(i);
                    contentValues.put(num + "_date", data.getString("date"));
                    JSONObject cond = data.getJSONObject("cond");
                    contentValues.put(num + "_txt_d", cond.getString("txt_d"));
                    contentValues.put(num + "_txt_n", cond.getString("txt_n"));
                    JSONObject tmp = data.getJSONObject("tmp");
                    contentValues.put(num + "_tmp_max", tmp.getString("max"));
                    contentValues.put(num + "_tmp_min", tmp.getString("min"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return contentValues;     //包含了所有的数据库信息
    }
}

代码解析:

基本上就Object和Array这两种东西,慢慢按照结构把最终的值使用类似getString的方法取到。慢慢扣出了我需要提取的数据……

最后我将取得的键值组成了ContentValues,,其实本来用Map类型进行保存的,然后在外部在再次转换为ContentValues进行数据库操作,后来转念一想这两东西结构不是一样的嘛!!!于是省了一步……

因为json里的数据名有重名的,我稍微利用for循环和switch进行重命名,数据库不接受数字开头的字符串当列名……

将数据缓存到数据库,而页面显示时,直接从数据库提取数据,最终效果就是这样了

-完-

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.09.02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Android网络与数据存储
    • 第二章学习
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档