diff --git a/app/build.gradle b/app/build.gradle
index 0a0776d..c0c3a5a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,7 +4,7 @@ android {
compileSdkVersion 26
defaultConfig {
applicationId "tech.panbin.android.firstweather"
- minSdkVersion 19
+ minSdkVersion 17
targetSdkVersion 26
versionCode 1
versionName "1.0"
@@ -19,18 +19,16 @@ android {
}
dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
-
compile 'org.litepal.android:core:1.6.1'
compile 'com.squareup.okhttp3:okhttp:3.7.0'
compile 'com.google.code.gson:gson:2.8.0'
-
implementation 'com.github.bumptech.glide:glide:4.5.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 42e651c..f5b5218 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,13 +2,14 @@
+
+
@@ -18,6 +19,7 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/tech/panbin/android/firstweather/ChooseAreaFragment.java b/app/src/main/java/tech/panbin/android/firstweather/ChooseAreaFragment.java
new file mode 100644
index 0000000..5b321e1
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/ChooseAreaFragment.java
@@ -0,0 +1,287 @@
+package tech.panbin.android.firstweather;
+
+import android.annotation.TargetApi;
+
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.litepal.crud.DataSupport;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Response;
+import tech.panbin.android.firstweather.db.City;
+import tech.panbin.android.firstweather.db.Country;
+import tech.panbin.android.firstweather.db.Province;
+import tech.panbin.android.firstweather.util.HttpUtil;
+import tech.panbin.android.firstweather.util.Utility;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class ChooseAreaFragment extends Fragment {
+
+ public static final int LEVEL_PROVINCE = 0;
+
+ public static final int LEVEL_CITY = 1;
+
+ public static final int LEVEL_COUNTRY = 2;
+
+ private ProgressDialog progressDialog;
+
+ private TextView titleText;
+
+ private Button backButton;
+
+ private ListView listView;
+
+ private ArrayAdapter adapter;
+
+ private List dataList = new ArrayList<>();
+
+// 省列表
+ private List provinceList;
+
+// 市列表
+ private List cityList;
+
+// 县区列表
+ private List countryList;
+
+// 选中的省份
+ private Province selectedProvince;
+
+// 选中的城市
+ private City selectedCity;
+
+// 选中的县区
+ private Country selectedCountry;
+
+// 当前选中的级别
+ private int currentLevel;
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ View view = inflater.inflate(R.layout.choose_area, container,false);
+ titleText = (TextView) view.findViewById(R.id.title_text);
+ backButton = (Button) view.findViewById(R.id.back_button);
+ listView = (ListView) view.findViewById(R.id.list_view);
+ adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, dataList);
+ listView.setAdapter(adapter);
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> adapterView, View view, int posion, long id) {
+
+ if(currentLevel == LEVEL_PROVINCE){
+ selectedProvince = provinceList.get(posion);
+ queryCities();
+ }else if(currentLevel == LEVEL_CITY){
+ selectedCity = cityList.get(posion);
+ queryCountries();
+ }
+ else if(currentLevel == LEVEL_COUNTRY){
+ // Added on 2018/1/14 ,by PanBin
+ String weatherId = countryList.get(posion).getWeatherId();
+
+ if(getActivity() instanceof MainActivity){
+ Intent intent = new Intent(getActivity(), WeatherActivity.class);
+
+ intent.putExtra("weather_id",weatherId);
+ startActivity(intent);
+ getActivity().finish();
+ }
+ else if(getActivity() instanceof WeatherActivity){
+ WeatherActivity weatherActivity =(WeatherActivity) getActivity();
+ weatherActivity.drawerLayout.closeDrawers();
+ weatherActivity.swipeRefreshLayout.setRefreshing(true);
+ weatherActivity.requestWeather(weatherId);
+ }
+
+ }
+ }
+ });
+
+ backButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(currentLevel == LEVEL_COUNTRY){
+ queryCities();
+ }else if(currentLevel == LEVEL_CITY){
+ queryProvinces();
+ }
+ }
+ });
+
+ queryProvinces();
+ }
+
+
+// 查询所有的省,先查数据库,若没有再查服务器
+ private void queryProvinces(){
+ titleText.setText("中国");
+ backButton.setVisibility(View.GONE);
+
+ provinceList = DataSupport.findAll(Province.class);
+
+ if(provinceList.size()>0){
+ dataList.clear();
+ for(Province province:provinceList){
+ dataList.add(province.getProvinceName());
+ }
+ adapter.notifyDataSetChanged();
+ listView.setSelection(0);
+ currentLevel = LEVEL_PROVINCE;
+
+ }else{
+ String address = "http://guolin.tech/api/china";
+ queryFromServer(address,"province");
+ }
+ }
+
+// 查询所有的市,先查数据库,若没有再查服务器
+ private void queryCities(){
+
+ titleText.setText(selectedProvince.getProvinceName());
+ backButton.setVisibility(View.VISIBLE);
+
+ cityList = DataSupport.where("provinceid = ?",String.valueOf(selectedProvince.getId())).find(City.class);
+ if(cityList.size()>0){
+ dataList.clear();
+ for(City city: cityList){
+ dataList.add(city.getCityName());
+ }
+ adapter.notifyDataSetChanged();
+ listView.setSelection(0);
+ currentLevel = LEVEL_CITY;
+ }else{
+ int provinceCode = selectedProvince.getProvinceCode();
+ String address = "http://guolin.tech/api/china/" + provinceCode;
+ queryFromServer(address,"city");
+ }
+ }
+
+// 查询所有的县区,先查数据库,若没有再查服务器
+ private void queryCountries(){
+
+ titleText.setText(selectedCity.getCityName());
+ backButton.setVisibility(View.VISIBLE);
+ countryList = DataSupport.where("cityid = ?",String.valueOf(selectedCity.getId())).find(Country.class);
+
+ if(countryList.size()>0){
+ dataList.clear();
+ for(Country country:countryList){
+ dataList.add(country.getCountryName());
+ }
+ adapter.notifyDataSetChanged();
+ listView.setSelection(0);
+ currentLevel = LEVEL_COUNTRY;
+
+ }else{
+ int provinceCode = selectedProvince.getProvinceCode();
+ int cityCode = selectedCity.getCityCode();
+
+ String address = "http://guolin.tech/api/china/" + provinceCode +"/"+ cityCode;
+ queryFromServer(address,"country");
+ }
+ }
+
+// 从服务器查询
+ private void queryFromServer(String address, final String type){
+
+ showProgressDialog();
+
+ HttpUtil.sendOkHttpRequest(address, new Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+
+ getActivity().runOnUiThread(new Runnable() {
+ @TargetApi(Build.VERSION_CODES.M)
+ @Override
+ public void run() {
+ closeProgressDialog();
+ Toast.makeText(getContext(),"加载失败",Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+ String responseText = response.body().string();
+ boolean result = false;
+
+ if("province".equals(type)){
+ result = Utility.handleProvinceResponse(responseText);
+ }
+ else if ("city".equals(type)){
+ result = Utility.handleCityResponse(responseText, selectedProvince.getId());
+ }
+ else if ("country".equals(type)){
+ result = Utility.handleCountryResponse(responseText, selectedCity.getId());
+ }
+
+ if(result){
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ closeProgressDialog();
+ if("province".equals(type)){
+ queryProvinces();
+ }
+ else if ("city".equals(type)){
+ queryCities();
+ }
+ else if ("country".equals(type)){
+ queryCountries();
+ }
+ }
+ });
+ }
+ }
+ });
+
+ }
+
+// 显示进度对话框
+ private void showProgressDialog(){
+ if(progressDialog == null){
+ progressDialog = new ProgressDialog(getActivity());
+ progressDialog.setMessage("正在加载...");
+ progressDialog.setCanceledOnTouchOutside(false);
+ }
+ progressDialog.show();
+ }
+
+// 关闭进度对话框
+ private void closeProgressDialog(){
+ if(progressDialog != null){
+ progressDialog.dismiss();
+ }
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/MainActivity.java b/app/src/main/java/tech/panbin/android/firstweather/MainActivity.java
index b4646b6..15f4b9f 100644
--- a/app/src/main/java/tech/panbin/android/firstweather/MainActivity.java
+++ b/app/src/main/java/tech/panbin/android/firstweather/MainActivity.java
@@ -1,7 +1,11 @@
package tech.panbin.android.firstweather;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
+import android.util.Log;
public class MainActivity extends AppCompatActivity {
@@ -9,5 +13,12 @@ public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+// Log.d("MainActivity","onCreate");
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ if(null != preferences.getString("weather",null)){
+ Intent intent = new Intent(this, WeatherActivity.class);
+ startActivity(intent);
+ finish();
+ }
}
}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/WeatherActivity.java b/app/src/main/java/tech/panbin/android/firstweather/WeatherActivity.java
new file mode 100644
index 0000000..e28d41e
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/WeatherActivity.java
@@ -0,0 +1,285 @@
+package tech.panbin.android.firstweather;
+
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.bumptech.glide.Glide;
+
+import java.io.IOException;
+import java.util.prefs.PreferenceChangeEvent;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Response;
+import tech.panbin.android.firstweather.gson.Forecast;
+import tech.panbin.android.firstweather.gson.Weather;
+import tech.panbin.android.firstweather.util.HttpUtil;
+import tech.panbin.android.firstweather.util.Utility;
+
+public class WeatherActivity extends AppCompatActivity {
+
+ private final String weatherApiKey = "bc0418b57b2d4918819d3974ac1285d9";
+
+ private ScrollView weatherLayout;
+
+ private TextView titleCity;
+
+ private TextView titleUpdateTime;
+
+ private TextView degreeText;
+
+ private TextView weatherInfoText;
+
+ private TextView aqiText;
+
+ private TextView pm25Text;
+
+ private TextView comfortText;
+
+ private TextView carWashText;
+
+ private TextView sportText;
+
+ private LinearLayout forecastLayout;
+
+ /*
+ *背景图片
+ * */
+ private ImageView bingPicImg;
+
+ /*
+ * 下拉刷新
+ * */
+ public SwipeRefreshLayout swipeRefreshLayout;
+ private String mWeatherId;
+
+ /*
+ * 切换城市
+ * */
+ public DrawerLayout drawerLayout;
+ private Button navButton;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_weather);
+
+// 初始化各个控件
+ weatherLayout = (ScrollView) findViewById(R.id.weather_layout);
+ titleCity = findViewById(R.id.title_city);
+ titleUpdateTime = findViewById(R.id.update_time);
+ degreeText = findViewById(R.id.degree_text);
+ weatherInfoText = findViewById(R.id.weather_info_text);
+ aqiText = findViewById(R.id.aqi_text);
+ pm25Text = findViewById(R.id.pm25_text);
+ comfortText = findViewById(R.id.comfort_text);
+ carWashText = findViewById(R.id.car_wash_text);
+ sportText = findViewById(R.id.sport_text);
+ forecastLayout = (LinearLayout) findViewById(R.id.forecast_layout);
+
+ bingPicImg = findViewById(R.id.bing_pic_img);
+
+ swipeRefreshLayout = findViewById(R.id.swipe_refresh);
+ swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
+
+ drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+ navButton = findViewById(R.id.nav_button);
+
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ String weatherString = preferences.getString("weather",null);
+ if(null != weatherString){
+ /*
+ * 有缓存时直接解析天气数据
+ * */
+ Weather weather = Utility.handleWeatherResponse(weatherString);
+
+ mWeatherId = weather.basic.weatherId;/*下拉刷新*/
+
+ showWeatherInfo(weather);
+ }
+ else{
+ /*
+ * 无缓存时查服务器
+ * */
+// String weatherId = getIntent().getStringExtra("weather_id");
+ mWeatherId = getIntent().getStringExtra("weather_id");/*下拉刷新*/
+ weatherLayout.setVisibility(View.INVISIBLE);
+// requestWeather(WeatherId);
+ requestWeather(mWeatherId);
+ }
+ /*
+ * 下拉刷新
+ * */
+ swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ requestWeather(mWeatherId);
+ }
+ });
+
+ /*
+ * 背景图片
+ * */
+ String bingPic = preferences.getString("bing_pic",null);
+ if(null != bingPic){
+ Glide.with(this).load(bingPic).into(bingPicImg);
+ }
+ else{
+ loadBingPic();
+ }
+
+ /*
+ * 切换城市
+ * */
+ navButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ drawerLayout.openDrawer(GravityCompat.START);
+ }
+ });
+
+ }
+
+ /*
+ * 根据城市id请求城市天气信息
+ * */
+ public void requestWeather(final String weatherId){
+
+ String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=" + weatherApiKey;
+
+ HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+ e.printStackTrace();
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(WeatherActivity.this,"网络请求失败,无法获取城市"+weatherId+"天气信息",Toast.LENGTH_SHORT).show();
+ swipeRefreshLayout.setRefreshing(false);
+ }
+ });
+ }
+
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+
+ final String responseText = response.body().string();
+ final Weather weather = Utility.handleWeatherResponse(responseText);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if(null != weather && "ok".equals(weather.status)){
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();
+ editor.putString("weather",responseText);
+ editor.apply();
+
+ mWeatherId = weather.basic.weatherId;
+
+ showWeatherInfo(weather);
+ }
+ else{
+// Toast.makeText(WeatherActivity.this,"获取城市"+weatherId+"天气信息失败",Toast.LENGTH_SHORT).show();
+
+ /*
+ * Debug
+ * */
+ Toast.makeText(WeatherActivity.this,"数据解析失败!\n返回值:\n"+responseText,Toast.LENGTH_LONG).show();
+ }
+ swipeRefreshLayout.setRefreshing(false);
+ }
+ });
+
+ }
+ });
+
+ loadBingPic();
+ }
+
+ /*
+ * 处理并战士Weather实体类中的数据
+ * */
+ private void showWeatherInfo(Weather weather){
+ String cityName = weather.basic.cityName;
+ String updateTime = weather.basic.update.updateTime.split(" ")[1];
+ String degree = weather.now.nowTemperature + "℃";
+ String weatherInfo = weather.now.nowCond.info;
+
+ titleCity.setText(cityName);
+ titleUpdateTime.setText(updateTime+"发布");
+ degreeText.setText(degree);
+ weatherInfoText.setText(weatherInfo);
+ forecastLayout.removeAllViews();
+ for (Forecast forecast: weather.forecastList){
+
+ View view = LayoutInflater.from(this).inflate(R.layout.forecast_item, forecastLayout, false);
+ TextView dateText = view.findViewById(R.id.date_text);
+ TextView infoText = view.findViewById(R.id.info_text);
+ TextView maxText = view.findViewById(R.id.max_text);
+ TextView minText = view.findViewById(R.id.min_text);
+
+ dateText.setText(forecast.date);
+ infoText.setText(forecast.forecastCond.info);
+ maxText.setText(forecast.forecastTmp.forecastMaxTmp);
+ minText.setText(forecast.forecastTmp.forecastMinTmp);
+ forecastLayout.addView(view);
+ }
+
+ if(null != weather.aqi){
+
+ aqiText.setText(weather.aqi.city.aqi);
+ pm25Text.setText(weather.aqi.city.pm25);
+ }
+
+ String comfort = "舒适度:" + weather.suggestion.comfort.info;
+ String carWash = "洗车指数:" + weather.suggestion.carWash.info;
+ String sport = "运动建议:" + weather.suggestion.sport.info;
+
+ comfortText.setText(comfort);
+ carWashText.setText(carWash);
+ sportText.setText(sport);
+ weatherLayout.setVisibility(View.VISIBLE);
+ }
+
+ /*
+ * 加载Bing每日一图
+ * */
+ private void loadBingPic(){
+ String requestBingPic = "http://guolin.tech/api/bing_pic";
+ HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+ e.printStackTrace();
+ }
+
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+
+ final String bingPic = response.body().string();
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();
+
+ editor.putString("bing_pic",bingPic);
+ editor.apply();
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Glide.with(WeatherActivity.this).load(bingPic).into(bingPicImg);
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/gson/AQI.java b/app/src/main/java/tech/panbin/android/firstweather/gson/AQI.java
new file mode 100644
index 0000000..0935578
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/gson/AQI.java
@@ -0,0 +1,23 @@
+package tech.panbin.android.firstweather.gson;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class AQI {
+
+ public AQICity city;
+
+ public class AQICity{
+
+ /*
+ * 空气质量指数
+ * */
+ public String aqi;
+
+ /*
+ * PM2.5
+ * */
+ public String pm25;
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/gson/Basic.java b/app/src/main/java/tech/panbin/android/firstweather/gson/Basic.java
new file mode 100644
index 0000000..760ff0a
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/gson/Basic.java
@@ -0,0 +1,25 @@
+package tech.panbin.android.firstweather.gson;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class Basic {
+
+ @SerializedName("city")
+ public String cityName;
+
+ @SerializedName("id")
+ public String weatherId;
+
+ @SerializedName("update")
+ public Update update;
+
+ public class Update{
+
+ @SerializedName("loc")
+ public String updateTime;
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/gson/Forecast.java b/app/src/main/java/tech/panbin/android/firstweather/gson/Forecast.java
new file mode 100644
index 0000000..b4bf352
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/gson/Forecast.java
@@ -0,0 +1,35 @@
+package tech.panbin.android.firstweather.gson;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class Forecast {
+
+ @SerializedName("date")
+ public String date;
+
+ @SerializedName("cond")
+ public ForecastCond forecastCond;
+
+ public class ForecastCond{
+
+ @SerializedName("txt_d")
+ public String info;
+ }
+
+ @SerializedName("tmp")
+ public ForecastTmp forecastTmp;
+
+ public class ForecastTmp{
+
+ @SerializedName("max")
+ public String forecastMaxTmp;
+
+ @SerializedName("min")
+ public String forecastMinTmp;
+
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/gson/Now.java b/app/src/main/java/tech/panbin/android/firstweather/gson/Now.java
new file mode 100644
index 0000000..69640f3
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/gson/Now.java
@@ -0,0 +1,22 @@
+package tech.panbin.android.firstweather.gson;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class Now {
+
+ @SerializedName("tmp")
+ public String nowTemperature;
+
+ @SerializedName("cond")
+ public NowCond nowCond;
+
+ public class NowCond{
+
+ @SerializedName("txt")
+ public String info;
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/gson/Suggestion.java b/app/src/main/java/tech/panbin/android/firstweather/gson/Suggestion.java
new file mode 100644
index 0000000..4986727
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/gson/Suggestion.java
@@ -0,0 +1,37 @@
+package tech.panbin.android.firstweather.gson;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class Suggestion {
+
+ @SerializedName("comf")
+ public Comfort comfort;
+
+ @SerializedName("cw")
+ public CarWash carWash;
+
+ @SerializedName("sport")
+ public Sport sport;
+
+ public class Comfort{
+
+ @SerializedName("txt")
+ public String info;
+ }
+
+ public class CarWash{
+
+ @SerializedName("txt")
+ public String info;
+ }
+
+ public class Sport{
+
+ @SerializedName("txt")
+ public String info;
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/gson/Weather.java b/app/src/main/java/tech/panbin/android/firstweather/gson/Weather.java
new file mode 100644
index 0000000..f322f4d
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/gson/Weather.java
@@ -0,0 +1,30 @@
+package tech.panbin.android.firstweather.gson;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class Weather {
+
+ @SerializedName("status")
+ public String status;
+
+ @SerializedName("basic")
+ public Basic basic;
+
+ @SerializedName("aqi")
+ public AQI aqi;
+
+ @SerializedName("daily_forecast")
+ public List forecastList;
+
+ @SerializedName("now")
+ public Now now;
+
+ @SerializedName("suggestion")
+ public Suggestion suggestion;
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/util/HttpUtil.java b/app/src/main/java/tech/panbin/android/firstweather/util/HttpUtil.java
new file mode 100644
index 0000000..c59a394
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/util/HttpUtil.java
@@ -0,0 +1,17 @@
+package tech.panbin.android.firstweather.util;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class HttpUtil {
+
+ public static void sendOkHttpRequest(String address, okhttp3.Callback callback){
+ OkHttpClient client = new OkHttpClient();
+ Request request = new Request.Builder().url(address).build();
+ client.newCall(request).enqueue(callback);
+ }
+}
diff --git a/app/src/main/java/tech/panbin/android/firstweather/util/Utility.java b/app/src/main/java/tech/panbin/android/firstweather/util/Utility.java
new file mode 100644
index 0000000..9e787f6
--- /dev/null
+++ b/app/src/main/java/tech/panbin/android/firstweather/util/Utility.java
@@ -0,0 +1,111 @@
+package tech.panbin.android.firstweather.util;
+
+import android.text.TextUtils;
+
+import com.google.gson.Gson;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import tech.panbin.android.firstweather.db.City;
+import tech.panbin.android.firstweather.db.Country;
+import tech.panbin.android.firstweather.db.Province;
+import tech.panbin.android.firstweather.gson.Weather;
+
+/**
+ * Created by PanBin on 2018/01/13.
+ */
+
+public class Utility {
+
+// 解析返回的省级数据
+ public static boolean handleProvinceResponse(String response){
+
+ if(!TextUtils.isEmpty(response)){
+ try{
+ JSONArray allProvinces = new JSONArray(response);
+ for (int i = 0; i < allProvinces.length(); i++) {
+ JSONObject provinceObject = allProvinces.getJSONObject(i);
+
+ Province province = new Province();
+ province.setProvinceCode(provinceObject.getInt("id"));
+ province.setProvinceName(provinceObject.getString("name"));
+
+ province.save();
+ }
+ return true;
+
+ }catch (JSONException e){
+ e.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+// 解析市级数据
+ public static boolean handleCityResponse(String response, int provinceId){
+ if(!TextUtils.isEmpty(response)){
+ try{
+ JSONArray allCites = new JSONArray(response);
+ for (int i = 0; i < allCites.length(); i++) {
+ JSONObject cityObject = allCites.getJSONObject(i);
+
+ City city = new City();
+ city.setCityCode(cityObject.getInt("id"));
+ city.setCityName(cityObject.getString("name"));
+ city.setProvinceId(provinceId);
+ city.save();
+ }
+ return true;
+
+ }catch (JSONException e){
+ e.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+// 解析县区级数据
+ public static boolean handleCountryResponse(String response, int cityId){
+
+ if(!TextUtils.isEmpty(response)){
+
+ try {
+ JSONArray allCountries = new JSONArray(response);
+ for (int i = 0; i < allCountries.length(); i++) {
+ JSONObject countryObject = allCountries.getJSONObject(i);
+
+ Country country = new Country();
+ country.setCountryName(countryObject.getString("name"));
+ country.setWeatherId(countryObject.getString("weather_id"));
+ country.setCityId(cityId);
+ country.save();
+ }
+
+ return true;
+ }catch (JSONException e){
+ e.printStackTrace();;
+ }
+ }
+ return false;
+ }
+
+
+ /*
+ * 解析天气数据
+ * */
+ public static Weather handleWeatherResponse(String response){
+
+ try {
+ JSONObject jsonObject = new JSONObject(response);
+ JSONArray jsonArray = jsonObject.getJSONArray("HeWeather");
+ String weatherContent = jsonArray.getJSONObject(0).toString();
+ return new Gson().fromJson(weatherContent, Weather.class);
+
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/app/src/main/res/drawable/ic_back.png b/app/src/main/res/drawable/ic_back.png
new file mode 100644
index 0000000..32a6d91
Binary files /dev/null and b/app/src/main/res/drawable/ic_back.png differ
diff --git a/app/src/main/res/drawable/ic_home.png b/app/src/main/res/drawable/ic_home.png
new file mode 100644
index 0000000..f7dc554
Binary files /dev/null and b/app/src/main/res/drawable/ic_home.png differ
diff --git a/app/src/main/res/drawable/logo.png b/app/src/main/res/drawable/logo.png
new file mode 100644
index 0000000..6baddb1
Binary files /dev/null and b/app/src/main/res/drawable/logo.png differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 43ae6f0..fe61768 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,18 +1,37 @@
-
-
-
-
-
+ android:layout_height="match_parent">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_weather.xml b/app/src/main/res/layout/activity_weather.xml
new file mode 100644
index 0000000..5a92eb1
--- /dev/null
+++ b/app/src/main/res/layout/activity_weather.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/aqi.xml b/app/src/main/res/layout/aqi.xml
new file mode 100644
index 0000000..041e889
--- /dev/null
+++ b/app/src/main/res/layout/aqi.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/choose_area.xml b/app/src/main/res/layout/choose_area.xml
new file mode 100644
index 0000000..700f0f2
--- /dev/null
+++ b/app/src/main/res/layout/choose_area.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/forecast.xml b/app/src/main/res/layout/forecast.xml
new file mode 100644
index 0000000..a8bfbfa
--- /dev/null
+++ b/app/src/main/res/layout/forecast.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/forecast_item.xml b/app/src/main/res/layout/forecast_item.xml
new file mode 100644
index 0000000..e5699fa
--- /dev/null
+++ b/app/src/main/res/layout/forecast_item.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/now.xml b/app/src/main/res/layout/now.xml
new file mode 100644
index 0000000..8294b85
--- /dev/null
+++ b/app/src/main/res/layout/now.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/suggestion.xml b/app/src/main/res/layout/suggestion.xml
new file mode 100644
index 0000000..98b7c6f
--- /dev/null
+++ b/app/src/main/res/layout/suggestion.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/title.xml b/app/src/main/res/layout/title.xml
new file mode 100644
index 0000000..fefdcb0
--- /dev/null
+++ b/app/src/main/res/layout/title.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/logo.png b/app/src/main/res/mipmap-anydpi-v26/logo.png
new file mode 100644
index 0000000..06f9644
Binary files /dev/null and b/app/src/main/res/mipmap-anydpi-v26/logo.png differ
diff --git a/app/src/main/res/mipmap-hdpi/logo.png b/app/src/main/res/mipmap-hdpi/logo.png
new file mode 100644
index 0000000..85ffe9f
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/logo.png differ
diff --git a/app/src/main/res/mipmap-mdpi/logo.png b/app/src/main/res/mipmap-mdpi/logo.png
new file mode 100644
index 0000000..3cc48ac
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/logo.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/loog.png b/app/src/main/res/mipmap-xhdpi/loog.png
new file mode 100644
index 0000000..68578ca
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/loog.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/loog.png b/app/src/main/res/mipmap-xxhdpi/loog.png
new file mode 100644
index 0000000..68578ca
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/loog.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/loog.png b/app/src/main/res/mipmap-xxxhdpi/loog.png
new file mode 100644
index 0000000..68578ca
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/loog.png differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6e7adc6..93e5c14 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,3 @@
- FirstWeather
+ 天气
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 5885930..e7517e1 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,8 +1,9 @@
-