主要功能:
  1. 登录、注册(需要有Web端):这个很好写,我使用SpringBoot搭建的Web端,配置好Mybatis,编写Dao层、Service层和Controller层就基本完成了。
  2. 首页显示所在地天气信息:通过网络定位获取所在位置的经纬度,然后调用高德的逆地理编码API将经纬度作为参数传入,解析返回结果,获取adcode(行政区编码),再调用高德天气查询API将adcode作为参数传入,解析返回的结果得到今天、明天、后天的天气信息,通过ListVIew将其显示出来。
  3. 查询其他城市天气信息:在输入框中输入要查询的城市、省份等位置信息,点击查询按钮,调用高德的地理编码API将城市名、省份或其他位置作为参数传入,解析返回结果,获取adcode,剩下的操作同上。
  用到的高德API服务:地理/逆地理编码,天气查询
  效果图:

  Web端主要代码实现:
  • 负责用户登录和注册的Controller:
@RestController
public class UserController {@AutowiredUserService userService;/*** 负责Android端登录请求** @param username* @param password* @return*/@PostMapping("/login")public String login(@RequestParam("username") String username, @RequestParam("password") String password) {// 根据用户名和密码查询该用户是否存在User user = new User(null, username, password);boolean canLogin = userService.checkLogin(user);// 若该用户存在返回登录成功信息if (canLogin) {return "LOGIN_SUCCESS";}// 若该用户不存在返回登录失败信息return "LOGIN_FAIL";}/*** 负责Android端注册请求** @param username* @param password* @return*/@PostMapping("/register")public String register(@RequestParam("username") String username, @RequestParam("password") String password) {// 查询该用户名是否存在,若存在返回用户已存在信息if (userService.checkExistUserName(username)) {return "USER_EXIST";}// 添加用户User user = new User(null, username, password);boolean canRegister = userService.checkRegister(user);// 添加成功返回成功信息if (canRegister) {return "REG_SUCCESS";}// 添加失败返回失败信息return "REG_FAIL";}
}
  Android端主要代码实现:
  • 在manifest文件中声明权限、Service和apikey:(apikey需要在高德控制台申请,创建应用后,点击添加key,选择服务平台,使用定位服务选择Android平台,使用天气查询API服务和地理编码服务选择Web服务,不要弄混)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.youngpain.weatherf"><!--用于访问网络,网络定位需要上网--><uses-permission android:name="android.permission.INTERNET" /><!--用于进行网络定位--><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><!--用于访问GPS定位--><!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />--><!--用于获取运营商信息,用于支持提供运营商信息相关的接口--><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><!--用于访问wifi网络信息,wifi信息会用于进行网络定位--><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><!--用于获取wifi的获取权限,wifi信息会用来进行网络定位--><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><applicationandroid:allowBackup="true"android:icon="@drawable/weather"android:label="@string/app_name"android:roundIcon="@drawable/weather"android:supportsRtl="true"android:theme="@style/AppTheme"tools:ignore="GoogleAppIndexingWarning"><activity android:name=".activity.Login"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><!--application标签中声明service组件,每个app拥有自己单独的定位service--><service android:name="com.amap.api.location.APSService" /><!--设置apikey--><meta-dataandroid:name="com.amap.api.v2.apikey"android:value="你在高德控制台申请的Android平台服务的apikey" /><activity android:name=".activity.ShowWeather" /><activity android:name=".activity.SearchWeather" /><activity android:name=".activity.Register" /></application>
</manifest>
  • 用户登录:
public class Login extends AppCompatActivity {//控件private EditText nameEdit;private EditText pwdEdit;private Button loginButton;private Button notLoginButton;private Button registerButton;//定义状态码private final int ERROR = 0;private final int LOGIN_FAIL = 1;private final int LOGIN_SUCCESS = 2;//保存用户信息private String username;private String password;//构建Web端登录请求URLprivate final String url = "http://192.168.0.101:8080/user/login";//使用OkHttpClient进行网络请求private OkHttpClient httpClient = new OkHttpClient();@SuppressLint("HandlerLeak")private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case ERROR://获取Message中的内容String message0 = (String) msg.obj;//Toast弹出错误Toast.makeText(Login.this, message0, Toast.LENGTH_SHORT).show();break;case LOGIN_FAIL://获取Message中的内容String message1 = (String) msg.obj;//Toast弹出登录失败Toast.makeText(Login.this, message1, Toast.LENGTH_SHORT).show();break;case LOGIN_SUCCESS://获取Message中的内容String message2 = (String) msg.obj;//Toast弹出登录成功Toast.makeText(Login.this, message2, Toast.LENGTH_SHORT).show();//登录成功跳转到个人信息页面startActivity(new Intent(Login.this, ShowWeather.class));finish();break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//去除标题栏requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.login);//初始化init();}private void init() {//获取控件nameEdit = findViewById(R.id.login_et_user);pwdEdit = findViewById(R.id.login_et_password);loginButton = findViewById(R.id.bt_login);//绑定监听事件loginButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//获取用户名和密码username = nameEdit.getText().toString().trim();password = pwdEdit.getText().toString().trim();if ("".equals(username) || "".equals(password)) {Toast.makeText(Login.this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();} else {//调用login()方法请求Web端login(username, password);}}});notLoginButton = findViewById(R.id.not_login);notLoginButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(Login.this, ShowWeather.class));}});registerButton = findViewById(R.id.register_user);registerButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(Login.this, Register.class));}});}/*** 发送登录请求到Web端** @param username* @param password*/private void login(String username, String password) {//创建请求表单RequestBody body = new FormBody.Builder().add("username", username)//添加用户名.add("password", password)//添加密码.build();//创建请求final Request request = new Request.Builder().url(url).post(body).build();//在子线程中获取服务器响应new Thread(new Runnable() {@Overridepublic void run() {Response response = null;try {response = httpClient.newCall(request).execute();//请求成功if (response.isSuccessful()) {String result = response.body().string();Log.i("服务器返回的结果:", result);Message message = Message.obtain();if ("LOGIN_SUCCESS".equals(result)) {message.what = LOGIN_SUCCESS;//设置标志message.obj = "登录成功";//设置内容}if ("LOGIN_FAIL".equals(result)) {message.what = LOGIN_FAIL;//设置标志message.obj = "用户名或密码错误";//设置内容}handler.sendMessage(message);} else {Toast.makeText(Login.this, "服务器无响应", Toast.LENGTH_SHORT).show();}} catch (Exception e) {Log.i("Login.java", "服务器异常:" + e.toString());Message message = Message.obtain();message.what = ERROR;message.obj = e.toString();e.printStackTrace();}}}).start();}
}
  • 解析天气查询API返回结果用到的Bean:
/*** 天气查询API返回结果*/
public class Weather {//值为0或1:1:成功;0:失败private String status;//返回状态private String count;//返回结果总数目private String info;//返回的状态信息private String infocode;//返回状态说明,10000代表正确private List<Forecasts> forecasts;//预报天气信息数据getter/setter方法省略
}
/*** 预报天气信息数据*/
public class Forecasts {private String city;//城市名private String adcode;//区域编码private String province;//省份名private String reporttime;//数据发布的时间private List<Casts> casts;//预报数据list结构,元素cast,按顺序为当天、第二天、第三天的预报数据getter/setter方法省略
}
/*** 预报数据list结构,元素cast,按顺序为当天、第二天、第三天的预报数据*/
public class Casts {private String date;private String week;private String dayweather;private String nightweather;private String daytemp;private String nighttemp;private String daywind;private String nightwind;private String daypower;private String nightpower;getter/setter方法省略
}
  • 首页布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/show_city"android:layout_width="match_parent"android:layout_height="40dp"android:layout_centerHorizontal="true"android:gravity="center"android:text="蜀山区"android:textSize="18sp" /><ListViewandroid:id="@+id/home_weather"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@+id/bottom_bar"android:layout_below="@+id/show_city"android:layout_centerHorizontal="true" /><includeandroid:id="@+id/bottom_bar"layout="@layout/bottombar"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true" />
</RelativeLayout>
  • ListView子项的布局文件,显示天气信息:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><RelativeLayoutandroid:id="@+id/relative_layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@+id/show_city"><TextViewandroid:id="@+id/date"android:layout_width="80dp"android:layout_height="30dp"android:layout_alignParentLeft="true"android:layout_marginLeft="20dp"android:gravity="center"android:text="今天"android:textColor="#48d1cc"android:textSize="18sp" /><TextViewandroid:id="@+id/day"android:layout_width="320dp"android:layout_height="30dp"android:layout_below="@+id/date"android:layout_centerHorizontal="true"android:gravity="center"android:text="白天"android:textColor="#1e90ff"android:textSize="16sp" /><TextViewandroid:id="@+id/day_weather"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/day"android:layout_gravity="center_vertical"android:layout_marginLeft="20dp"android:layout_toLeftOf="@+id/center_fill"android:gravity="center"android:text="小雨"android:textStyle="bold" /><TextViewandroid:id="@+id/center_fill"android:layout_width="2dp"android:layout_height="30dp"android:layout_below="@+id/day"android:layout_centerHorizontal="true" /><TextViewandroid:id="@+id/day_temp"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/day"android:layout_gravity="center_vertical"android:layout_marginRight="20dp"android:layout_toRightOf="@+id/center_fill"android:gravity="center"android:text="11℃"android:textStyle="bold" /><TextViewandroid:id="@+id/day_wind"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/day_temp"android:layout_gravity="center_vertical"android:layout_marginLeft="10dp"android:layout_toLeftOf="@+id/center_fill"android:gravity="center"android:text="北风"android:textStyle="bold" /><TextViewandroid:id="@+id/center_fill2"android:layout_width="2dp"android:layout_height="30dp"android:layout_below="@+id/day_weather"android:layout_centerHorizontal="true" /><TextViewandroid:id="@+id/day_power"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/day_temp"android:layout_gravity="center_vertical"android:layout_marginRight="10dp"android:layout_toRightOf="@+id/center_fill2"android:gravity="center"android:text="≤3级"android:textStyle="bold" /><TextViewandroid:id="@+id/night"android:layout_width="320dp"android:layout_height="30dp"android:layout_below="@+id/day_power"android:layout_centerHorizontal="true"android:layout_marginTop="10dp"android:gravity="center"android:text="夜里"android:textColor="#1e90ff"android:textSize="16sp" /><TextViewandroid:id="@+id/night_weather"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/night"android:layout_gravity="center_vertical"android:layout_marginLeft="10dp"android:layout_toLeftOf="@+id/center_fill3"android:gravity="center"android:text="中雨"android:textStyle="bold" /><TextViewandroid:id="@+id/center_fill3"android:layout_width="2dp"android:layout_height="30dp"android:layout_below="@+id/night"android:layout_centerHorizontal="true" /><TextViewandroid:id="@+id/night_temp"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/night"android:layout_gravity="center_vertical"android:layout_marginRight="10dp"android:layout_toRightOf="@+id/center_fill3"android:gravity="center"android:text="8℃"android:textStyle="bold" /><TextViewandroid:id="@+id/night_wind"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/night_weather"android:layout_gravity="center_vertical"android:layout_marginLeft="10dp"android:layout_toLeftOf="@+id/center_fill4"android:gravity="center"android:text="西北风"android:textStyle="bold" /><TextViewandroid:id="@+id/center_fill4"android:layout_width="2dp"android:layout_height="30dp"android:layout_below="@+id/night_weather"android:layout_centerHorizontal="true" /><TextViewandroid:id="@+id/night_power"android:layout_width="160dp"android:layout_height="30dp"android:layout_below="@+id/night_temp"android:layout_gravity="center_vertical"android:layout_marginRight="10dp"android:layout_toRightOf="@+id/center_fill4"android:gravity="center"android:text="≤3级"android:textStyle="bold" /></RelativeLayout></RelativeLayout>
  • 首页定位获取位置并查询该区域的天气信息:
public class ShowWeather extends AppCompatActivity {//控件private ListView listView;private TextView showCity;private Button searchBtn;//请求的API,详细参考https://lbs.amap.com/api/webservice/guide/api/weatherinfo/private String url = "https://restapi.amap.com/v3/weather/weatherInfo?key=你在高德控制台申请的Web服务的key&city=340104&extensions=all&out=json";//使用OkHttpClient进行网络请求private OkHttpClient httpClient = new OkHttpClient();//使用Gson解析json字符串private Gson gson = new Gson();//存储解析json字符串得到的天气信息private List<Map<String, String>> weatherList = new ArrayList<>();//保存经纬度private String longitude;private String latitude;//声明AMapLocationClient类对象public AMapLocationClient mLocationClient = null;//声明AMapLocationClientOption对象public AMapLocationClientOption mLocationOption = null;//声明定位回调监听器public AMapLocationListener mLocationListener = new AMapLocationListener() {@Overridepublic void onLocationChanged(AMapLocation aMapLocation) {if (aMapLocation != null) {//错误码为0表示定位成功if (aMapLocation.getErrorCode() == 0) {//获取城市信息String city = aMapLocation.getProvince() + aMapLocation.getCity() + aMapLocation.getDistrict();//设置显示showCity.setText(city);//获取经纬度,截取经纬度(不超过6位)longitude = String.valueOf(aMapLocation.getLongitude()).substring(0, 5);latitude = String.valueOf(aMapLocation.getLatitude()).substring(0, 5);Toast.makeText(ShowWeather.this, "经纬度为:" + longitude + "," + latitude, Toast.LENGTH_SHORT).show();//根据经纬度获取adcodegetAdcode(longitude + "," + latitude);} else {Toast.makeText(ShowWeather.this, "定位失败,ErrCode=" + aMapLocation.getErrorCode(), Toast.LENGTH_SHORT).show();//定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。Log.i("AmapError", "location Error, ErrCode:"+ aMapLocation.getErrorCode() + ", errInfo:"+ aMapLocation.getErrorInfo());}}}};@SuppressLint("HandlerLeak")private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 0:Toast.makeText(ShowWeather.this, (String) msg.obj, Toast.LENGTH_SHORT).show();break;case 1:Toast.makeText(ShowWeather.this, "该城市adcode为" + (String) msg.obj, Toast.LENGTH_SHORT).show();break;case 2:Toast.makeText(ShowWeather.this, (String) msg.obj, Toast.LENGTH_SHORT).show();break;case 3://创建Adapterfinal SimpleAdapter simpleAdapter = new SimpleAdapter(ShowWeather.this, weatherList, R.layout.weather_listview_item, new String[]{"date", "day_weather", "day_temp", "day_wind", "day_power", "night_weather", "night_temp", "night_wind", "night_power"}, new int[]{R.id.date, R.id.day_weather, R.id.day_temp, R.id.day_wind, R.id.day_power, R.id.night_weather, R.id.night_temp, R.id.night_wind, R.id.night_power});//绑定AdapterlistView.setAdapter(simpleAdapter);Toast.makeText(ShowWeather.this, (String) msg.obj, Toast.LENGTH_LONG).show();break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//去除标题栏requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.show_weather);//初始化init();if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {//如果权限不足提示请求权限requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);} else {//如果权限已允许,准备定位prepareLocation();}}@Overrideprotected void onDestroy() {super.onDestroy();//停止定位mLocationClient.stopLocation();}/*** Android6.0申请权限的回调方法*/@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {//如果允许权限则准备定位prepareLocation();} else {Toast.makeText(ShowWeather.this, "请允许应用获取相应的权限", Toast.LENGTH_LONG).show();}}/*** 定位准备工作*/private void prepareLocation() {//初始化定位mLocationClient = new AMapLocationClient(getApplicationContext());//设置定位监听mLocationClient.setLocationListener(mLocationListener);//初始化mLocationOption = new AMapLocationClientOption();//低功耗定位模式:不会使用GPS和其他传感器,只会使用网络定位(Wi-Fi和基站定位);mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Battery_Saving);//使用单次定位,默认为falsemLocationOption.setOnceLocation(true);//设置是否返回地址信息(默认返回地址信息)mLocationOption.setNeedAddress(true);//设置定位间隔,单位毫秒,默认为2000msmLocationOption.setInterval(2000);//设置定位参数mLocationClient.setLocationOption(mLocationOption);//启动定位mLocationClient.startLocation();}/*** 初始化控件*/private void init() {//获取控件showCity = findViewById(R.id.show_city);listView = findViewById(R.id.home_weather);searchBtn = findViewById(R.id.search_btn);searchBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(ShowWeather.this, SearchWeather.class);startActivity(intent);}});}/*** 获取经纬度后,通过逆地理编码API获得该区域的adcode,将其作为天气查询API的参数获得当前位置的天气信息** @param location 经纬度信息:经度在前,纬度在后,经纬度间以“,”分割,经纬度小数点后不要超过 6 位*/private void getAdcode(String location) {String url = "https://restapi.amap.com/v3/geocode/regeo?key=你在高德控制台申请的Web服务的key&location=" + location;final Request request = new Request.Builder().url(url).get().build();new Thread(new Runnable() {@Overridepublic void run() {Response response = null;try {response = httpClient.newCall(request).execute();//请求成功if (response.isSuccessful()) {String result = response.body().string();Log.i("result", result);//转JsonObjectJsonObject object = new JsonParser().parse(result).getAsJsonObject();String adcode = object.get("regeocode").getAsJsonObject().get("addressComponent").getAsJsonObject().get("adcode").getAsString();Log.i("测试获取adcode", adcode);//请求天气查询getWeather(adcode);Message message = Message.obtain();message.what = 1;message.obj = adcode;handler.sendMessage(message);}} catch (Exception e) {Log.i("ShowWeather.java", "服务器异常:" + e.toString());Message message = Message.obtain();message.what = 0;message.obj = "服务器异常";e.printStackTrace();}}}).start();}/*** 通过OkHttp发送网络请求查询天气*/private void getWeather(String adcode) {String newUrl = url + "&&city=" + adcode;final Request request = new Request.Builder().url(newUrl).get().build();new Thread(new Runnable() {@Overridepublic void run() {Response response = null;try {response = httpClient.newCall(request).execute();//请求成功if (response.isSuccessful()) {String result = response.body().string();Log.i("服务器返回的结果", result);//使用Gson解析Weather weather = gson.fromJson(result, Weather.class);//获取今天天气信息Casts today = weather.getForecasts().get(0).getCasts().get(0);//添加Map数据到ListMap<String, String> map1 = new HashMap<>();map1.put("date", "今天");map1.put("day_weather", today.getDayweather());map1.put("day_temp", today.getDaytemp() + "℃");//如果是“无风向”,直接显示,否则显示“xx风”,提升显示效果if (WeatherUtil.noWindDirection(today.getDaywind())) {map1.put("day_wind", today.getDaywind());} else {map1.put("day_wind", today.getDaywind() + "风");}map1.put("day_power", today.getDaypower() + "级");map1.put("night_weather", today.getNightweather());map1.put("night_temp", today.getNighttemp() + "℃");if (WeatherUtil.noWindDirection(today.getNightwind())) {map1.put("night_wind", today.getNightwind());} else {map1.put("night_wind", today.getNightwind() + "风");}map1.put("night_power", today.getNightpower() + "级");weatherList.add(map1);Log.i("今天", today.toString());//获取明天天气信息Casts tomorrow = weather.getForecasts().get(0).getCasts().get(1);//添加Map数据到ListMap<String, String> map2 = new HashMap<>();map2.put("date", "明天");map2.put("day_weather", tomorrow.getDayweather());map2.put("day_temp", tomorrow.getDaytemp() + "℃");if (WeatherUtil.noWindDirection(tomorrow.getDaywind())) {map2.put("day_wind", tomorrow.getDaywind());} else {map2.put("day_wind", tomorrow.getDaywind() + "风");}map2.put("day_power", tomorrow.getDaypower() + "级");map2.put("night_weather", tomorrow.getNightweather());map2.put("night_temp", tomorrow.getNighttemp() + "℃");if (WeatherUtil.noWindDirection(tomorrow.getNightwind())) {map2.put("night_wind", tomorrow.getNightwind());} else {map2.put("night_wind", tomorrow.getNightwind() + "风");}map2.put("night_power", tomorrow.getNightpower() + "级");weatherList.add(map2);Log.i("明天", tomorrow.toString());//获取后天天气信息Casts afterTomorrow = weather.getForecasts().get(0).getCasts().get(2);//添加Map数据到ListMap<String, String> map3 = new HashMap<>();map3.put("date", "后天");map3.put("day_weather", afterTomorrow.getDayweather());map3.put("day_temp", afterTomorrow.getDaytemp() + "℃");if (WeatherUtil.noWindDirection(afterTomorrow.getDaywind())) {map3.put("day_wind", afterTomorrow.getDaywind());} else {map3.put("day_wind", afterTomorrow.getDaywind() + "风");}map3.put("day_power", afterTomorrow.getDaypower() + "级");map3.put("night_weather", afterTomorrow.getNightweather());map3.put("night_temp", afterTomorrow.getNighttemp() + "℃");if (WeatherUtil.noWindDirection(afterTomorrow.getNightwind())) {map3.put("night_wind", afterTomorrow.getNightwind());} else {map3.put("night_wind", afterTomorrow.getNightwind() + "风");}map3.put("night_power", afterTomorrow.getNightpower() + "级");weatherList.add(map3);Log.i("后天", afterTomorrow.toString());Message message = Message.obtain();message.what = 3;message.obj = "查询成功";handler.sendMessage(message);}} catch (Exception e) {Log.i("ShowWeather.java", "服务器异常:" + e.toString());Message message = Message.obtain();message.what = 2;message.obj = "服务器异常";e.printStackTrace();}}}).start();}}
  • 查询天气的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><RelativeLayoutandroid:id="@+id/search_weather_layout"android:layout_width="match_parent"android:layout_height="wrap_content"><EditTextandroid:id="@+id/edit_city"android:layout_width="240dp"android:layout_height="40dp"android:layout_centerHorizontal="true"android:layout_marginTop="2dp"android:gravity="center"android:hint="输入城市名查询天气"android:textSize="16sp" /><Buttonandroid:id="@+id/search_w_btn"android:layout_width="wrap_content"android:layout_height="30dp"android:layout_centerVertical="true"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_toRightOf="@+id/edit_city"android:background="#8fbc8f"android:gravity="center"android:text="查询"android:textColor="#ffffff" /></RelativeLayout><ListViewandroid:id="@+id/search_weather"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/search_weather_layout"android:layout_centerHorizontal="true" /></RelativeLayout>
  • 根据输入的位置查询该位置的天气信息;
public class SearchWeather extends AppCompatActivity {private EditText edit_city;private Button search_btn;private ListView listView;//请求的API,详细参考https://lbs.amap.com/api/webservice/guide/api/weatherinfo/private String url = "https://restapi.amap.com/v3/weather/weatherInfo?key=你在高德控制台申请的Web服务的key&extensions=all&out=json";//使用OkHttpClient进行网络请求private OkHttpClient httpClient = new OkHttpClient();//使用Gson解析json字符串private Gson gson = new Gson();@SuppressLint("HandlerLeak")private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 0:Toast.makeText(SearchWeather.this, (String) msg.obj, Toast.LENGTH_SHORT).show();break;case 1:Toast.makeText(SearchWeather.this, (String) msg.obj, Toast.LENGTH_SHORT).show();break;case 2:Toast.makeText(SearchWeather.this, "该城市adcode为" + (String) msg.obj, Toast.LENGTH_SHORT).show();break;case 3:List<Map<String, String>> list = (List<Map<String, String>>) msg.obj;//创建Adapterfinal SimpleAdapter simpleAdapter = new SimpleAdapter(SearchWeather.this, list, R.layout.weather_listview_item, new String[]{"date", "day_weather", "day_temp", "day_wind", "day_power", "night_weather", "night_temp", "night_wind", "night_power"}, new int[]{R.id.date, R.id.day_weather, R.id.day_temp, R.id.day_wind, R.id.day_power, R.id.night_weather, R.id.night_temp, R.id.night_wind, R.id.night_power});//绑定AdapterlistView.setAdapter(simpleAdapter);Toast.makeText(SearchWeather.this, "查询成功", Toast.LENGTH_SHORT).show();default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.search_weather);//初始化init();}private void init() {edit_city = findViewById(R.id.edit_city);search_btn = findViewById(R.id.search_w_btn);search_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//调用方法获取该城市的城市编码getAdcode();}});listView = findViewById(R.id.search_weather);}/*** 高德开发平台请求天气查询API中区域编码adcode是必须项,使用高德地理编码服务获取区域编码* address:结构化地址信息,规则遵循:国家、省份、城市、区县、城镇、乡村、街道、门牌号码、屋邨、大厦*/private void getAdcode() {String address = edit_city.getText().toString();String url = "https://restapi.amap.com/v3/geocode/geo?key=你在高德控制台申请的Web服务的key&address=" + address;final Request request = new Request.Builder().url(url).get().build();new Thread(new Runnable() {@Overridepublic void run() {Response response = null;try {response = httpClient.newCall(request).execute();//请求成功if (response.isSuccessful()) {String result = response.body().string();Log.i("result", result);//转JsonObjectJsonObject object = new JsonParser().parse(result).getAsJsonObject();//转JsonArrayJsonArray array = object.get("geocodes").getAsJsonArray();JsonObject info = array.get(0).getAsJsonObject();//获取adcodeString adcode = info.get("adcode").getAsString();Log.i("测试获取adcode", adcode);//请求天气查询getWeather(adcode);Message message = Message.obtain();message.what = 2;message.obj = adcode;handler.sendMessage(message);}} catch (Exception e) {Log.i("SearchMainActivity.java", "服务器异常:" + e.toString());Message message = Message.obtain();message.what = 0;message.obj = "服务器异常";e.printStackTrace();}}}).start();}/*** 查询天气*/private void getWeather(String adcode) {String newUrl = url + "&&city=" + adcode;final Request request = new Request.Builder().url(newUrl).get().build();new Thread(new Runnable() {@Overridepublic void run() {Response response = null;try {response = httpClient.newCall(request).execute();//请求成功if (response.isSuccessful()) {String result = response.body().string();Log.i("服务器返回的结果:", result);//存储解析json字符串得到的天气信息List<Map<String, String>> weatherList = new ArrayList<>();//使用Gson解析Weather weather = gson.fromJson(result, Weather.class);//获取今天天气信息Casts today = weather.getForecasts().get(0).getCasts().get(0);//添加Map数据到ListMap<String, String> map1 = new HashMap<>();map1.put("date", "今天");map1.put("day_weather", today.getDayweather());map1.put("day_temp", today.getDaytemp() + "℃");if (WeatherUtil.noWindDirection(today.getDaywind())) {map1.put("day_wind", today.getDaywind());} else {map1.put("day_wind", today.getDaywind() + "风");}map1.put("day_power", today.getDaypower() + "级");map1.put("night_weather", today.getNightweather());map1.put("night_temp", today.getNighttemp() + "℃");if (WeatherUtil.noWindDirection(today.getNightwind())) {map1.put("night_wind", today.getNightwind());} else {map1.put("night_wind", today.getNightwind() + "风");}map1.put("night_power", today.getNightpower() + "级");weatherList.add(map1);//获取明天天气信息Casts tomorrow = weather.getForecasts().get(0).getCasts().get(1);//添加Map数据到ListMap<String, String> map2 = new HashMap<>();map2.put("date", "明天");map2.put("day_weather", tomorrow.getDayweather());map2.put("day_temp", tomorrow.getDaytemp() + "℃");if (WeatherUtil.noWindDirection(tomorrow.getDaywind())) {map2.put("day_wind", tomorrow.getDaywind());} else {map2.put("day_wind", tomorrow.getDaywind() + "风");}map2.put("day_power", tomorrow.getDaypower() + "级");map2.put("night_weather", tomorrow.getNightweather());map2.put("night_temp", tomorrow.getNighttemp() + "℃");if (WeatherUtil.noWindDirection(tomorrow.getNightwind())) {map2.put("night_wind", tomorrow.getNightwind());} else {map2.put("night_wind", tomorrow.getNightwind() + "风");}map2.put("night_power", tomorrow.getNightpower() + "级");weatherList.add(map2);//获取后天天气信息Casts afterTomorrow = weather.getForecasts().get(0).getCasts().get(2);//添加Map数据到ListMap<String, String> map3 = new HashMap<>();map3.put("date", "后天");map3.put("day_weather", afterTomorrow.getDayweather());map3.put("day_temp", afterTomorrow.getDaytemp() + "℃");if (WeatherUtil.noWindDirection(afterTomorrow.getDaywind())) {map3.put("day_wind", afterTomorrow.getDaywind());} else {map3.put("day_wind", afterTomorrow.getDaywind() + "风");}map3.put("day_power", afterTomorrow.getDaypower() + "级");map3.put("night_weather", afterTomorrow.getNightweather());map3.put("night_temp", afterTomorrow.getNighttemp() + "℃");if (WeatherUtil.noWindDirection(afterTomorrow.getNightwind())) {map3.put("night_wind", afterTomorrow.getNightwind());} else {map3.put("night_wind", afterTomorrow.getNightwind() + "风");}map3.put("night_power", afterTomorrow.getNightpower() + "级");weatherList.add(map3);//将服务器返回数据写入HandlerMessage message = Message.obtain();message.what = 3;message.obj = weatherList;handler.sendMessage(message);//handler.obtainMessage(1, response).sendToTarget();}} catch (Exception e) {Log.i("SearchWeather.java", "服务器异常:" + e.toString());Message message = Message.obtain();message.what = 1;message.obj = e.toString();e.printStackTrace();}}}).start();}}
csdn下载
github

Android利用高德天气查询API实现天气查询功能相关推荐

  1. HTML + CSS + JS 利用邮编查询 API 实现邮编查询工具

    引言 邮政编码是地址信息的重要组成部分,可以帮助快递公司.物流公司等对地址进行快速.准确的识别和派送.因此,邮编查询工具应用在许多业务场景中都有广泛的应用,例如:电商平台.物流公司.金融机构等.通过使 ...

  2. 利用有道翻译Api实现英文翻译功能

    有道翻译提供了翻译和查词的数据接口.通过数据接口,您可以获得一段文本的翻译结果或者查词结果.       通过调用有道翻译API数据接口,您可以在您的网站或应用中更灵活地定制翻译和查词功能. 第一步: ...

  3. Java调用和风天气台API查看天气

    创建一个Java Project即可 import java.io.*; import java.net.URL; import java.net.URLConnection; import java ...

  4. jpa的查询api_为JPA的本机查询API键入安全查询

    jpa的查询api 当您使用JPA时-有时-JPQL不能解决问题,您将不得不使用本机SQL. 从一开始,像Hibernate这样的ORM就为这些情况保留了开放的"后门",并为Spr ...

  5. 为JPA的本机查询API键入安全查询

    当您使用JPA时-有时-JPQL无法解决问题,您将不得不使用本机SQL. 从一开始,像Hibernate这样的ORM就为这些情况保留了一个开放的"后门",并为Spring的Jdbc ...

  6. python电脑怎么打开任务管理器_利用Python调用Windows API,实现任务管理器功能

    任务管理器具体功能有: 1. 列出系统当前所有进程. 2. 列出隶属于该进程的所有线程. 3. 如果进程有窗口,可以显示和隐藏窗口. 4. 强行结束指定进程. 通过Python调用Windows AP ...

  7. 苏州公交实时查询api 根据线路编码查询详细信息

    苏州公交实时查询api-苏州公交状态实时跟踪,根据线路编码查询详细信息. 接口名称:苏州公交实时查询api 接口平台:api接口 接口地址:http://apis.juhe.cn/szbusline/ ...

  8. 利用Python调用Windows API,实现任务管理器功能

    任务管理器具体功能有: 1. 列出系统当前所有进程. 2. 列出隶属于该进程的所有线程. 3. 如果进程有窗口,可以显示和隐藏窗口. 4. 强行结束指定进程. 通过Python调用Windows AP ...

  9. LINE分享android利用系统自带分享实现LINE分享功能

    android利用系统自带分享实现分享功能之LINE分享 最近公司向海外发展,提出了一个国外主流的社交APP分享需求.原来我使用的是第三方分享工具,但是太鸡肋,国内的APP支持的还是不错的,但是国外支 ...

最新文章

  1. SAP UI5 应用的 OData XML 格式的元数据请求解析原理,基于 DOMParser
  2. java.util.ComparableTimSort中的sort()方法简单分析
  3. LeetCode 694. 不同岛屿的数量(BFS/DFS+set)
  4. 中台到底是什么?传统企业怎样建设中台?
  5. JAVA之旅(五)——this,static,关键字,main函数,封装工具类,生成javadoc说明书,静态代码块...
  6. AWS 创建 pem 文件
  7. opencv常用函数整理(一)
  8. 推荐5款超实用的Chrome广告拦截插件
  9. 小马哥---深度解析mtk刷机平台报错解决 4032 8038等
  10. 中科院阿里云联合发布11比特云接入超导量子计算服务
  11. php钱兆楼,PHP动态网站开发实例教程(第2版)
  12. 君正X1000开发板/方案开发介绍
  13. 你的离职是为了事业还为了工作??
  14. Linux进阶 | ❤Docker+NFS+Volume实现数据一致性❤
  15. 洛谷【p1007】独木桥
  16. Install Qualcomm Development Environment
  17. 架设游戏的服务器系统,架设游戏服务器需要备案吗
  18. Node.js快速入门
  19. 一文详解激光SLAM框架LeGO-LOAM
  20. 【OJ每日一练】1022 - 梯形的面积

热门文章

  1. View Design 全系产品升级至 Vue 3,并发布 View UI Plus 正式版
  2. android 录像和拍照功能
  3. 【蓝桥真题7】贴吧车队作弊?应对线上考和双填趋势,我们该如何备考?
  4. 理论与实践在创新过程中的作用
  5. Java Word文档合并(支持图片)-增加去除分页符/分页标识
  6. excel计算日期时间差 8位数字转化成日期 excel输入天数计算日期 excel输入天数生成日期
  7. 入手评测 荣耀手环6和华为手环6区别
  8. 如何新建PDF空白页的几个方法
  9. MPLS多协议标签交换
  10. 真香,写代码神器!32寸曲面屏显示器免费送