赞
踩
本篇文章中需要获取天气数据了,通过上一篇文章中得到地址去获取天气数据,这里我们依然使用和风天气,虽然有一些其他的API推荐,但是毕竟是小平台,不够稳定,所以我这里还是使用和风API。
这里用的是和风天气API接口,点击进入官网。
点击天气API。进行登录或者注册,然后就可以进行开发者认证。
认证好之后就创建应用进入开发者控制台。
点击项目管理,然后创建项目。
这里你可以选择免费订阅,使用平台选择Web API,注意一个账号只能有一个免费订阅,之前不是这样的,其他的订阅方式是需要花钱的。你可以通过这个订阅规则查看所需要的数据类型。
创建应用完成之后会得到一个KEY,点击查看就知道你的KEY的值了,通过这个KEY我们可以去访问和风的天气API接口,拿到数据。
可以通过和风天气开发文档查看有哪些数据API。
这里我们先使用城市搜索的API,为什么先使用这个API呢?因为我们现在通过百度定位得到位置信息,那么这个位置信息是不能够直接去使用的,需要先通过和风的城市搜索API得到城市的Location ID,通过Location ID才能去使用和风的其他API接口,我们看一下这个接口要怎么写。
这里我们看到接口的方式就是一个地址URL,往下滑动还能看到请求示例和返回数据,有这些内容我们就可以在项目中写一个网络请求来获取返回的数据,构建出一个数据实体。主要就是JSON的使用。
这篇文章中我们先简单使用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<LocationBean> 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<LocationBean> getLocation() {
return location;
}
public void setLocation(List<LocationBean> location) {
this.location = location;
}
public static class ReferBean {
private List<String> sources;
private List<String> license;
public List<String> getSources() {
return sources;
}
public void setSources(List<String> sources) {
this.sources = sources;
}
public List<String> getLicense() {
return license;
}
public void setLicense(List<String> 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
这里用的是和风天气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<HeWeather6Bean> HeWeather6;
public List<HeWeather6Bean> getHeWeather6() {
return HeWeather6;
}
public void setHeWeather6(List<HeWeather6Bean> 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方法了,都给你生成好了。一步到位,用了之后根本停不下来。
通过上面的访问地址,我们可以看得出来,只要修改location的值就可以得到不同地方的天气数据信息了,刚才是在网页上访问的,接下来就通过Android来访问这个地址,得到数据并且显示出来。
说到网络请求,就不得不提一下OKHttp网络请求框架,刚开始你可能比较陌生,这里做一下简单的讲解。
OkHttp是一个第三方类库,用于android中请求网络。这是一个开源项目,是安卓端最火热的轻量级框架。
网络请求分两种方式Post请求和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。
这种方式不用再次开启子线程,但回调方法是执行在子线程中,所以在更新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。
示例代码
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();
}
示例代码
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。