Android 天气APP(三)访问天气API与数据请求 您所在的位置:网站首页 和风天气api文档怎么做 Android 天气APP(三)访问天气API与数据请求

Android 天气APP(三)访问天气API与数据请求

2024-01-20 03:38| 来源: 网络整理| 查看: 265

上一篇:Android 天气APP(二)获取定位信息

访问天气API与数据请求 新版-------------------一、和风天气二、城市搜索接口三、OKHttp使用四、文章源码 旧版-------------------2. 访问天气API接口3. 网络请求① OKHttp1.Post和Get的区别2.同步和异步的区别3.Get的同步请求4.Get的异步请求5.Post的同步请求5.Post的异步请求

新版-------------------

  本篇文章中需要获取天气数据了,通过上一篇文章中得到地址去获取天气数据,这里我们依然使用和风天气,虽然有一些其他的API推荐,但是毕竟是小平台,不够稳定,所以我这里还是使用和风API。

一、和风天气

这里用的是和风天气API接口,点击进入官网。

在这里插入图片描述

点击天气API。进行登录或者注册,然后就可以进行开发者认证。

在这里插入图片描述

认证好之后就创建应用进入开发者控制台。

在这里插入图片描述

点击项目管理,然后创建项目。

在这里插入图片描述

这里你可以选择免费订阅,使用平台选择Web API,注意一个账号只能有一个免费订阅,之前不是这样的,其他的订阅方式是需要花钱的。你可以通过这个订阅规则查看所需要的数据类型。

创建应用完成之后会得到一个KEY,点击查看就知道你的KEY的值了,通过这个KEY我们可以去访问和风的天气API接口,拿到数据。

在这里插入图片描述

可以通过和风天气开发文档查看有哪些数据API。

二、城市搜索接口

在这里插入图片描述

这里我们先使用城市搜索的API,为什么先使用这个API呢?因为我们现在通过百度定位得到位置信息,那么这个位置信息是不能够直接去使用的,需要先通过和风的城市搜索API得到城市的Location ID,通过Location ID才能去使用和风的其他API接口,我们看一下这个接口要怎么写。

在这里插入图片描述

这里我们看到接口的方式就是一个地址URL,往下滑动还能看到请求示例和返回数据,有这些内容我们就可以在项目中写一个网络请求来获取返回的数据,构建出一个数据实体。主要就是JSON的使用。

这篇文章中我们先简单使用OKHttp来访问数据,后面再对网络请求进一步封装。

三、OKHttp使用

首先我们在app的build.gradle的dependencies{}闭包下添加如下代码:

implementation 'com.squareup.okhttp3:okhttp:3.14.9'

添加位置如下图所示:

在这里插入图片描述

然后点击Sync Now,同步,下面我们在MainActivity中添加如下所示方法代码:

private void searchCity(String district) { //使用Get异步请求 OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() //拼接访问地址 .url("https://geoapi.qweather.com/v2/city/lookup?key=3086e91d66c04ce588a7f538f917c7f4&location="+district) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if(response.isSuccessful()){//回调的方法执行在子线程。 Log.d("a","获取数据成功了"); Log.d("a","response.code()=="+response.code()); Log.d("a","response.body().string()=="+response.body().string()); } } }); }

这里面其实就是OkHttp的基本使用方法,很简单,你要注意的就是那个请求的URL的拼接,这里我使用的是我的Key然后加上区的值就可以了,注意返回数据是在子线程中。然后我们在onReceiveLocation()回调中调用。

在这里插入图片描述

最后运行一下看看,用真机运行。可以看到数据返回了,请在Logcat下查看。

在这里插入图片描述

这个数据是可以作为实体Bean的生成的。

{ "code":"200", "location":[ { "name":"南山", "id":"101280604", "lat":"22.53122", "lon":"113.92942", "adm2":"深圳", "adm1":"广东省", "country":"中国", "tz":"Asia/Shanghai", "utcOffset":"+08:00", "isDst":"0", "type":"city", "rank":"25", "fxLink":"http://hfx.link/1u0z1" }, { "name":"南山", "id":"101051206", "lat":"47.31324", "lon":"130.27552", "adm2":"鹤岗", "adm1":"黑龙江省", "country":"中国", "tz":"Asia/Shanghai", "utcOffset":"+08:00", "isDst":"0", "type":"city", "rank":"45", "fxLink":"http://hfx.link/1tlo1" } ], "refer":{ "sources":[ "QWeather" ], "license":[ "QWeather Developers License" ] } }

这里的实体Bean可以统一放在bean包下,在com.llw.goodweather包下新建这个bean包,然后bean包下新建一个SearchCityResponse类,手动写一下这个实体类,代码如下:

public class SearchCityResponse { private String code; private ReferBean refer; private List location; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public ReferBean getRefer() { return refer; } public void setRefer(ReferBean refer) { this.refer = refer; } public List getLocation() { return location; } public void setLocation(List location) { this.location = location; } public static class ReferBean { private List sources; private List license; public List getSources() { return sources; } public void setSources(List sources) { this.sources = sources; } public List getLicense() { return license; } public void setLicense(List license) { this.license = license; } } public static class LocationBean { private String name; private String id; private String lat; private String lon; private String adm2; private String adm1; private String country; private String tz; private String utcOffset; private String isDst; private String type; private String rank; private String fxLink; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getLat() { return lat; } public void setLat(String lat) { this.lat = lat; } public String getLon() { return lon; } public void setLon(String lon) { this.lon = lon; } public String getAdm2() { return adm2; } public void setAdm2(String adm2) { this.adm2 = adm2; } public String getAdm1() { return adm1; } public void setAdm1(String adm1) { this.adm1 = adm1; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getTz() { return tz; } public void setTz(String tz) { this.tz = tz; } public String getUtcOffset() { return utcOffset; } public void setUtcOffset(String utcOffset) { this.utcOffset = utcOffset; } public String getIsDst() { return isDst; } public void setIsDst(String isDst) { this.isDst = isDst; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getRank() { return rank; } public void setRank(String rank) { this.rank = rank; } public String getFxLink() { return fxLink; } public void setFxLink(String fxLink) { this.fxLink = fxLink; } } } 四、文章源码

欢迎 Star 和 Fork

第三篇文章源码地址:GoodWeather-New-3

旧版------------------- 2. 访问天气API接口

这里用的是和风天气API接口,点击进入官网 在这里插入图片描述

点击天气API进行登录控制台或者注册账号 在这里插入图片描述 注册用邮箱就可以了,这里没有什么好讲解的,我是已经注册过了,所以我登录就可以了,然后进入控制台,创建应用。 在这里插入图片描述 本来我想输入GoodWeather,但是最多输入11个字符,所以我就去掉了Good 在这里插入图片描述 这里注意,一个邮箱只能创建一个免费应用。 在这里插入图片描述 免费版有很多限制的,有钱的大佬可以升级成付费版,像我这种穷人就只能白嫖,好了,然后添加KEY,没有KEY的话应用访问不了。 在这里插入图片描述 点击创建 在这里插入图片描述

接下来我们看一下开发文档怎么去获取天气数据 在这里插入图片描述 点击常规天气数据,免费版 在这里插入图片描述 now就是今天的天气,根据这个文档我们来写一个访问地址

https://free-api.heweather.net/s6/weather/now?key=3086e91d66c04ce588a7f538f917c7f4&location=深圳

请注意,这个key=后面的这一串是你的应用的KEY,每个都不一样。 随便打开一个网页,地址栏粘贴进去,回车即可得到数据,

{"HeWeather6":[{"basic":{"cid":"CN101280601","location":"深圳","parent_city":"深圳","admin_area":"广东","cnty":"中国","lat":"22.54700089","lon":"114.08594513","tz":"+8.00"},"update":{"loc":"2020-04-01 15:45","utc":"2020-04-01 07:45"},"status":"ok","now":{"cloud":"100","cond_code":"104","cond_txt":"阴","fl":"18","hum":"82","pcpn":"0.0","pres":"1006","tmp":"18","vis":"16","wind_deg":"79","wind_dir":"东北风","wind_sc":"2","wind_spd":"9"}}]}

这是返回的数据,JSON数据,而我要把他转化成实体Bean来接收。这个时候就可以用到另一个Android Studio的插件了,GsonFormat

快速将JSON字符串转换成一个Java Bean,免去我们根据JSON字符串手写对应java Bean的过程。 在这里插入图片描述 当然安装完之后是要重启Android Studio才能生效的,重启完毕之后来使用找个插件, 在这里插入图片描述 然后复制刚才的返回值, 在这里插入图片描述 鼠标点击光标处,Alt + S 弹出一个窗口 在这里插入图片描述 框内粘贴返回值,点击OK 在这里插入图片描述 这个页面可以修改参数的属性值和属性名,如果没有要修改就OK,然后实体Bean就生成了。 在这里插入图片描述 严谨一点,我把这个实体Bean的代码粘贴一下

package com.llw.goodweather.bean; import java.util.List; public class TodayResponse { //生成实体Bean private List HeWeather6; public List getHeWeather6() { return HeWeather6; } public void setHeWeather6(List HeWeather6) { this.HeWeather6 = HeWeather6; } public static class HeWeather6Bean { /** * basic : {"cid":"CN101280601","location":"深圳","parent_city":"深圳","admin_area":"广东","cnty":"中国","lat":"22.54700089","lon":"114.08594513","tz":"+8.00"} * update : {"loc":"2020-04-01 15:45","utc":"2020-04-01 07:45"} * status : ok * now : {"cloud":"100","cond_code":"104","cond_txt":"阴","fl":"18","hum":"82","pcpn":"0.0","pres":"1006","tmp":"18","vis":"16","wind_deg":"79","wind_dir":"东北风","wind_sc":"2","wind_spd":"9"} */ private BasicBean basic; private UpdateBean update; private String status; private NowBean now; public BasicBean getBasic() { return basic; } public void setBasic(BasicBean basic) { this.basic = basic; } public UpdateBean getUpdate() { return update; } public void setUpdate(UpdateBean update) { this.update = update; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public NowBean getNow() { return now; } public void setNow(NowBean now) { this.now = now; } public static class BasicBean { /** * cid : CN101280601 * location : 深圳 * parent_city : 深圳 * admin_area : 广东 * cnty : 中国 * lat : 22.54700089 * lon : 114.08594513 * tz : +8.00 */ private String cid; private String location; private String parent_city; private String admin_area; private String cnty; private String lat; private String lon; private String tz; public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getParent_city() { return parent_city; } public void setParent_city(String parent_city) { this.parent_city = parent_city; } public String getAdmin_area() { return admin_area; } public void setAdmin_area(String admin_area) { this.admin_area = admin_area; } public String getCnty() { return cnty; } public void setCnty(String cnty) { this.cnty = cnty; } public String getLat() { return lat; } public void setLat(String lat) { this.lat = lat; } public String getLon() { return lon; } public void setLon(String lon) { this.lon = lon; } public String getTz() { return tz; } public void setTz(String tz) { this.tz = tz; } } public static class UpdateBean { /** * loc : 2020-04-01 15:45 * utc : 2020-04-01 07:45 */ private String loc; private String utc; public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } public String getUtc() { return utc; } public void setUtc(String utc) { this.utc = utc; } } public static class NowBean { /** * cloud : 100 * cond_code : 104 * cond_txt : 阴 * fl : 18 * hum : 82 * pcpn : 0.0 * pres : 1006 * tmp : 18 * vis : 16 * wind_deg : 79 * wind_dir : 东北风 * wind_sc : 2 * wind_spd : 9 */ private String cloud; private String cond_code; private String cond_txt; private String fl; private String hum; private String pcpn; private String pres; private String tmp; private String vis; private String wind_deg; private String wind_dir; private String wind_sc; private String wind_spd; public String getCloud() { return cloud; } public void setCloud(String cloud) { this.cloud = cloud; } public String getCond_code() { return cond_code; } public void setCond_code(String cond_code) { this.cond_code = cond_code; } public String getCond_txt() { return cond_txt; } public void setCond_txt(String cond_txt) { this.cond_txt = cond_txt; } public String getFl() { return fl; } public void setFl(String fl) { this.fl = fl; } public String getHum() { return hum; } public void setHum(String hum) { this.hum = hum; } public String getPcpn() { return pcpn; } public void setPcpn(String pcpn) { this.pcpn = pcpn; } public String getPres() { return pres; } public void setPres(String pres) { this.pres = pres; } public String getTmp() { return tmp; } public void setTmp(String tmp) { this.tmp = tmp; } public String getVis() { return vis; } public void setVis(String vis) { this.vis = vis; } public String getWind_deg() { return wind_deg; } public void setWind_deg(String wind_deg) { this.wind_deg = wind_deg; } public String getWind_dir() { return wind_dir; } public void setWind_dir(String wind_dir) { this.wind_dir = wind_dir; } public String getWind_sc() { return wind_sc; } public void setWind_sc(String wind_sc) { this.wind_sc = wind_sc; } public String getWind_spd() { return wind_spd; } public void setWind_spd(String wind_spd) { this.wind_spd = wind_spd; } } } }

这样就不用在一个个的去写Get和Set方法了,都给你生成好了。一步到位,用了之后根本停不下来。

3. 网络请求

通过上面的访问地址,我们可以看得出来,只要修改location的值就可以得到不同地方的天气数据信息了,刚才是在网页上访问的,接下来就通过Android来访问这个地址,得到数据并且显示出来。 说到网络请求,就不得不提一下OKHttp网络请求框架,刚开始你可能比较陌生,这里做一下简单的讲解。

① OKHttp

OkHttp是一个第三方类库,用于android中请求网络。这是一个开源项目,是安卓端最火热的轻量级框架。 网络请求分两种方式Post请求和Get请求

1.Post和Get的区别 浏览器对URL的长度有限制,所以GET请求不能代替POST请求发送大量数据GET请求发送数据更小POST请求不能被缓存POST请求相对GET请求是「安全」的POST请求Request Body传递参数

以上皆是个人理解,如有不对,望斧正。

2.同步和异步的区别 同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

以上皆是个人理解,如有不对,望斧正。

3.Get的同步请求

对于同步请求在请求时需要开启子线程,请求成功后需要跳转到UI线程修改UI,示例代码如下:

public void getDataSync() { //创建新的线程 new Thread(new Runnable() { @Override public void run() { try { OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象 Request request = new Request.Builder() .url("http://www.baidu.com")//请求接口。如果需要传参拼接到接口后面。 .build();//创建Request 对象 Response response = null; response = client.newCall(request).execute();//得到Response 对象 if (response.isSuccessful()) { Log.d("kwwl", "response.code()==" + response.code()); Log.d("kwwl", "response.message()==" + response.message()); Log.d("kwwl", "res==" + response.body().string()); //此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。 } } catch (Exception e) { e.printStackTrace(); } } }).start(); }

注意事项: 1,Response.code是http响应行中的code,如果访问成功则返回200.这个不是服务器设置的,而是http协议中自带的。res中的code才是服务器设置的。注意二者的区别。 2,response.body().string()本质是输入流的读操作,所以它还是网络请求的一部分,所以这行代码必须放在子线程。 3,response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。原因是:response.body().string()的本质是输入流的读操作,必须有服务器的输出流的写操作时客户端的读操作才能得到数据。而服务器的写操作只执行一次,所以客户端的读操作也只能执行一次,第二次将返回null。

4.Get的异步请求

这种方式不用再次开启子线程,但回调方法是执行在子线程中,所以在更新UI时还要跳转到UI线程中。

private void getDataAsync() { //创建OkHttpClient对象 OkHttpClient client = new OkHttpClient(); //创建Request 对象 Request request = new Request.Builder() .url("http://www.baidu.com") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) {//回调的方法执行在子线程。 Log.d("kwwl", "获取数据成功了"); Log.d("kwwl", "response.code()==" + response.code()); Log.d("kwwl", "response.body().string()==" + response.body().string()); } } }); }

注意事项: 1,回调接口的onFailure方法和onResponse执行在子线程。 2,response.body().string()方法也必须放在子线程中。当执行这行代码得到结果后,再跳转到UI线程修改UI。

5.Post的同步请求

示例代码

public void postDataWithParame() { //创建新的线程 new Thread(new Runnable() { @Override public void run() { try { OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。 FormBody.Builder formBody = new FormBody.Builder();//创建表单请求体 formBody.add("username","zhangsan");//传递键值对参数 Request request = new Request.Builder()//创建Request 对象。 .url("http://www.baidu.com") .post(formBody.build())//传递请求体 .build(); client.newCall(request).execute();//得到Response 对象 if (response.isSuccessful()) { Log.d("kwwl", "response.code()==" + response.code()); Log.d("kwwl", "response.message()==" + response.message()); Log.d("kwwl", "res==" + response.body().string()); //此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。 } } catch (Exception e) { e.printStackTrace(); } } }).start(); } 5.Post的异步请求

示例代码

private void postDataWithParame() { OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。 FormBody.Builder formBody = new FormBody.Builder();//创建表单请求体 formBody.add("username","zhangsan");//传递键值对参数 Request request = new Request.Builder()//创建Request 对象。 .url("http://www.baidu.com") .post(formBody.build())//传递请求体 .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) {//回调的方法执行在子线程。 Log.d("kwwl", "获取数据成功了"); Log.d("kwwl", "response.code()==" + response.code()); Log.d("kwwl", "response.body().string()==" + response.body().string()); } } }); }

不知道你有没有看懵逼,好了,接下来我们使用异步Get来请求这个APi的数据返回。

//获取今天的天气数据 private void getTodayWeather(String district) { //使用Get异步请求 OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() //拼接访问地址 .url("https://free-api.heweather.net/s6/weather/now?key=3086e91d66c04ce588a7f538f917c7f4&location="+district) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if(response.isSuccessful()){//回调的方法执行在子线程。 Log.d("kwwl","获取数据成功了"); Log.d("kwwl","response.code()=="+response.code()); Log.d("kwwl","response.body().string()=="+response.body().string()); } } }); }

在这里插入图片描述 在定位结果里面调用网络请求方法,设置参数为区/县的定位值。 运行起来,然后看一下控制台的日志打印: 在这里插入图片描述 这就是通过地址请求返回的当天的天气数据 {“HeWeather6”:[{“basic”:{“cid”:“CN101280604”,“location”:“南山”,“parent_city”:“深圳”,“admin_area”:“广东”,“cnty”:“中国”,“lat”:“22.53122139”,“lon”:“113.9294281”,“tz”:“+8.00”},“update”:{“loc”:“2020-04-01 17:09”,“utc”:“2020-04-01 09:09”},“status”:“ok”,“now”:{“cloud”:“100”,“cond_code”:“104”,“cond_txt”:“阴”,“fl”:“19”,“hum”:“83”,“pcpn”:“0.0”,“pres”:“1006”,“tmp”:“18”,“vis”:“16”,“wind_deg”:“95”,“wind_dir”:“东风”,“wind_sc”:“1”,“wind_spd”:“5”}},{“basic”:{“cid”:“CN101051206”,“location”:“南山”,“parent_city”:“鹤岗”,“admin_area”:“黑龙江”,“cnty”:“中国”,“lat”:“47.31324005”,“lon”:“130.27552795”,“tz”:“+8.00”},“update”:{“loc”:“2020-04-01 17:09”,“utc”:“2020-04-01 09:09”},“status”:“ok”,“now”:{“cloud”:“0”,“cond_code”:“100”,“cond_txt”:“晴”,“fl”:“5”,“hum”:“23”,“pcpn”:“0.0”,“pres”:“988”,“tmp”:“10”,“vis”:“16”,“wind_deg”:“269”,“wind_dir”:“西风”,“wind_sc”:“3”,“wind_spd”:“19”}}]}

源码地址:GoodWeather 欢迎 Star 和 Fork

下一篇:Android 天气APP(四)搭建MVP框架与使用



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有