神刀安全网

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

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举个例子:

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"}}}
在线请求天气API,并解析其中的json数据予以显示

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进行重命名,数据库不接受数字开头的字符串当列名……

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

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

-完-

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 在线请求天气API,并解析其中的json数据予以显示

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址