From 90842db0e1123824108b631f5eedc7eeed6bca49 Mon Sep 17 00:00:00 2001 From: LiLongwei Date: Fri, 23 Jul 2021 16:32:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A8=8B=E5=BA=8F=E5=B4=A9?= =?UTF-8?q?=E6=BA=83=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=A4=9A?= =?UTF-8?q?=E6=AC=A1=E8=AF=B7=E6=B1=82=E7=BD=91=E7=BB=9C=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E6=9B=B4=E6=94=B9=E7=BD=91=E7=BB=9C=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E6=A1=86=E6=9E=B6=EF=BC=8C=E9=87=87=E7=94=A8OkHttp+Re?= =?UTF-8?q?trofit+RxJava=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/compiler.xml | 2 +- .idea/misc.xml | 2 +- app/build.gradle | 2 +- .../com/llw/goodweather/MainActivity.java | 171 +++++++------- .../llw/goodweather/NetworkRequiredInfo.java | 51 ++++ .../llw/goodweather/WeatherApplication.java | 4 + .../com/llw/goodweather/api/ApiService.java | 48 ++-- .../contract/MapWeatherContract.java | 120 +++++----- .../goodweather/contract/MoreAirContract.java | 117 ++++----- .../contract/MoreDailyContract.java | 25 +- .../contract/MoreLifestyleContract.java | 45 ++-- .../contract/SearchCityContract.java | 45 ++-- .../goodweather/contract/SplashContract.java | 41 ++-- .../contract/WallPaperContract.java | 41 ++-- .../goodweather/contract/WeatherContract.java | 173 +++++++------- .../contract/WorldCityContract.java | 22 +- .../contract/WorldCityWeatherContract.java | 54 +++-- .../ui/CommonlyUsedCityActivity.java | 10 +- .../goodweather/ui/MapWeatherActivity.java | 133 +++++------ .../llw/goodweather/ui/MoreAirActivity.java | 30 +-- .../llw/goodweather/ui/MoreDailyActivity.java | 8 +- .../goodweather/ui/MoreLifestyleActivity.java | 8 +- .../goodweather/ui/SearchCityActivity.java | 10 +- .../llw/goodweather/ui/SplashActivity.java | 39 ++- .../llw/goodweather/ui/WallPaperActivity.java | 15 +- .../goodweather/ui/WorldCityListActivity.java | 8 +- .../ui/WorldCityWeatherActivity.java | 34 +-- .../goodweather/utils/AppStartUpUtils.java | 3 +- .../com/llw/goodweather/utils/SpeechUtil.java | 4 +- download/code.png | Bin 19086 -> 50430 bytes mvplibrary/build.gradle | 19 +- .../com/llw/mvplibrary/net/NetCallBack.java | 2 +- .../llw/mvplibrary/newnet/BaseResponse.java | 21 ++ .../newnet/INetworkRequiredInfo.java | 31 +++ .../com/llw/mvplibrary/newnet/NetworkApi.java | 222 ++++++++++++++++++ .../llw/mvplibrary/newnet/NetworkUtils.java | 120 ++++++++++ .../NetworkEnvironmentActivity.java | 97 ++++++++ .../newnet/errorhandler/ExceptionHandle.java | 145 ++++++++++++ .../newnet/errorhandler/HttpErrorHandler.java | 22 ++ .../interceptor/RequestInterceptor.java | 45 ++++ .../interceptor/ResponseInterceptor.java | 28 +++ .../newnet/observer/BaseObserver.java | 42 ++++ .../newnet/observer/NetObserver.java | 6 + .../llw/mvplibrary/newnet/utils/DateUtil.java | 171 ++++++++++++++ .../com/llw/mvplibrary/newnet/utils/KLog.java | 205 ++++++++++++++++ .../newnet/utils/StatusBarUtil.java | 189 +++++++++++++++ .../main/res/drawable/ic_network_settings.xml | 15 ++ .../layout/activity_network_environment.xml | 5 + .../src/main/res/values/network_array.xml | 12 + mvplibrary/src/main/res/values/strings.xml | 2 + .../main/res/xml/environment_preference.xml | 12 + .../main/res/xml/network_security_config.xml | 4 + 52 files changed, 2079 insertions(+), 601 deletions(-) create mode 100644 app/src/main/java/com/llw/goodweather/NetworkRequiredInfo.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/BaseResponse.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/INetworkRequiredInfo.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkApi.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkUtils.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/environment/NetworkEnvironmentActivity.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/ExceptionHandle.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/HttpErrorHandler.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/RequestInterceptor.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/ResponseInterceptor.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/BaseObserver.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/NetObserver.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/DateUtil.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/KLog.java create mode 100644 mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/StatusBarUtil.java create mode 100644 mvplibrary/src/main/res/drawable/ic_network_settings.xml create mode 100644 mvplibrary/src/main/res/layout/activity_network_environment.xml create mode 100644 mvplibrary/src/main/res/values/network_array.xml create mode 100644 mvplibrary/src/main/res/xml/environment_preference.xml create mode 100644 mvplibrary/src/main/res/xml/network_security_config.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml index fb7f4a8..61a9130 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 860da66..d5d35ec 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/build.gradle b/app/build.gradle index d9d43c5..ff3bc34 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { minSdkVersion 21 targetSdkVersion 28 versionCode 1 - versionName "2.6" + versionName "2.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/com/llw/goodweather/MainActivity.java b/app/src/main/java/com/llw/goodweather/MainActivity.java index 4d5acff..85796ef 100644 --- a/app/src/main/java/com/llw/goodweather/MainActivity.java +++ b/app/src/main/java/com/llw/goodweather/MainActivity.java @@ -968,7 +968,8 @@ public void onViewClicked(View view) { } break; case R.id.fab_voice_search://语音搜索 - SpeechUtil.startDictation(cityName -> { + + SpeechUtil.startDictation(this, cityName -> { if (cityName.isEmpty()) { return; } @@ -1061,41 +1062,46 @@ public void getWeatherDataFailed() { * @param response */ @Override - public void getNewSearchCityResult(Response response) { + public void getNewSearchCityResult(NewSearchCityResponse response) { refresh.finishRefresh();//关闭刷新 if (mLocationClient != null) { mLocationClient.stop();//数据返回后关闭定位 } - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - if (response.body().getLocation() != null && response.body().getLocation().size() > 0) { - NewSearchCityResponse.LocationBean locationBean = response.body().getLocation().get(0); - //如果是定位到当前地方则添加到常用城市 - addCommonlyUsedCity(locationBean); - //日期所在地 - dateDetailStr = "今天是" + DateUtils.getNowDateStr() + "," - + DateUtils.getWeekOfDate(new Date()) + ",当前所在地:" + locationBean.getName() + "。"; - - tvCity.setText(locationBean.getName());//城市 - locationId = locationBean.getId();//城市Id - stationName = locationBean.getAdm2();//上级城市 也是空气质量站点 - lon = locationBean.getLon();//经度 - lat = locationBean.getLat();//纬度 - mPresent.nowWarn(locationId);//灾害预警 - mPresent.nowWeather(locationId);//查询实况天气 - mPresent.getMinutePrec(lon + "," + lat);//分钟级降水 - mPresent.hourlyWeather(locationId);//查询逐小时天气预报 - mPresent.dailyWeather(locationId);//查询天气预报 - mPresent.airNowWeather(locationId);//空气质量 - mPresent.lifestyle(locationId);//生活指数 + if(response != null) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + if (response.getLocation() != null && response.getLocation().size() > 0) { + NewSearchCityResponse.LocationBean locationBean = response.getLocation().get(0); + //如果是定位到当前地方则添加到常用城市 + addCommonlyUsedCity(locationBean); + //日期所在地 + dateDetailStr = "今天是" + DateUtils.getNowDateStr() + "," + + DateUtils.getWeekOfDate(new Date()) + ",当前所在地:" + locationBean.getName() + "。"; + + tvCity.setText(locationBean.getName());//城市 + locationId = locationBean.getId();//城市Id + stationName = locationBean.getAdm2();//上级城市 也是空气质量站点 + lon = locationBean.getLon();//经度 + lat = locationBean.getLat();//纬度 + mPresent.nowWarn(locationId);//灾害预警 + mPresent.nowWeather(locationId);//查询实况天气 + mPresent.getMinutePrec(lon + "," + lat);//分钟级降水 + mPresent.hourlyWeather(locationId);//查询逐小时天气预报 + mPresent.dailyWeather(locationId);//查询天气预报 + mPresent.airNowWeather(locationId);//空气质量 + mPresent.lifestyle(locationId);//生活指数 + } else { + ToastUtils.showShortToast(context, "数据为空"); + } } else { - ToastUtils.showShortToast(context, "数据为空"); + dismissLoadingDialog(); + tvCity.setText("查询城市失败"); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } else { - dismissLoadingDialog(); - tvCity.setText("查询城市失败"); - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context,"搜索城市数据为空"); } + } /** @@ -1104,40 +1110,35 @@ public void getNewSearchCityResult(Response response) { * @param response */ @Override - public void getNowResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) {//200则成功返回数据 + public void getNowResult(NowResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) {//200则成功返回数据 //根据V7版本的原则,只要是200就一定有数据,我们可以不用做判空处理,但是,为了使程序不ANR,还是要做的,信自己得永生 - NowResponse data = response.body(); - if (data != null) { - Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Light.ttf"); - tvTemperature.setText(data.getNow().getTemp());//温度 - - tempStr = "当前温度:" + data.getNow().getTemp() + "度,天气" + data.getNow().getText() + "。"; - dialogTemp = data.getNow().getTemp(); - dialogWeatherState = data.getNow().getText(); - dialogWeatherStateCode = Integer.parseInt(data.getNow().getIcon()); - - tvTemperature.setTypeface(typeface);//使用字体 - if (flag) { - ivLocation.setVisibility(View.VISIBLE);//显示定位图标 - } else { - ivLocation.setVisibility(View.GONE);//显示定位图标 - } - tvWeek.setText(DateUtils.getWeekOfDate(new Date()));//星期 - tvInfo.setText(data.getNow().getText());//天气状况 + Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Light.ttf"); + tvTemperature.setText(response.getNow().getTemp());//温度 - String time = DateUtils.updateTime(data.getUpdateTime());//截去前面的字符,保留后面所有的字符,就剩下 22:00 + tempStr = "当前温度:" + response.getNow().getTemp() + "度,天气" + response.getNow().getText() + "。"; + dialogTemp = response.getNow().getTemp(); + dialogWeatherState = response.getNow().getText(); + dialogWeatherStateCode = Integer.parseInt(response.getNow().getIcon()); - tvOldTime.setText("最近更新时间:" + WeatherUtil.showTimeInfo(time) + time); - tvWindDirection.setText("风向 " + data.getNow().getWindDir());//风向 - tvWindPower.setText("风力 " + data.getNow().getWindScale() + "级");//风力 - wwBig.startRotate();//大风车开始转动 - wwSmall.startRotate();//小风车开始转动 + tvTemperature.setTypeface(typeface);//使用字体 + if (flag) { + ivLocation.setVisibility(View.VISIBLE);//显示定位图标 } else { - ToastUtils.showShortToast(context, "暂无实况天气数据"); + ivLocation.setVisibility(View.GONE);//显示定位图标 } + tvWeek.setText(DateUtils.getWeekOfDate(new Date()));//星期 + tvInfo.setText(response.getNow().getText());//天气状况 + + String time = DateUtils.updateTime(response.getUpdateTime());//截去前面的字符,保留后面所有的字符,就剩下 22:00 + + tvOldTime.setText("最近更新时间:" + WeatherUtil.showTimeInfo(time) + time); + tvWindDirection.setText("风向 " + response.getNow().getWindDir());//风向 + tvWindPower.setText("风力 " + response.getNow().getWindScale() + "级");//风力 + wwBig.startRotate();//大风车开始转动 + wwSmall.startRotate();//小风车开始转动 } else {//其他状态返回提示文字 - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -1147,16 +1148,16 @@ public void getNowResult(Response response) { * @param response */ @Override - public void getMinutePrecResult(Response response) { + public void getMinutePrecResult(MinutePrecResponse response) { dismissLoadingDialog();//关闭加载弹窗 - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - precStr = response.body().getSummary() + "。"; + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + precStr = response.getSummary() + "。"; - tvPrecipitation.setText(response.body().getSummary()); - dialogPrecipitation = response.body().getSummary();//弹窗降水预告 - if (response.body().getMinutely() != null && response.body().getMinutely().size() > 0) { + dialogPrecipitation = response.getSummary();//弹窗降水预告 + tvPrecipitation.setText(dialogPrecipitation); + if (response.getMinutely() != null && response.getMinutely().size() > 0) { minutelyList.clear(); - minutelyList.addAll(response.body().getMinutely()); + minutelyList.addAll(response.getMinutely()); mAdapterMinutePrec.notifyDataSetChanged(); checkAppVersion();//检查版本信息 @@ -1165,7 +1166,7 @@ public void getMinutePrecResult(Response response) { ToastUtils.showShortToast(context, "分钟级降水数据为空"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -1175,9 +1176,9 @@ public void getMinutePrecResult(Response response) { * @param response */ @Override - public void getHourlyResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getHourly(); + public void getHourlyResult(HourlyResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getHourly(); if (data != null && data.size() > 0) { hourlyListV7.clear(); hourlyListV7.addAll(data); @@ -1187,7 +1188,7 @@ public void getHourlyResult(Response response) { ToastUtils.showShortToast(context, "逐小时预报数据为空"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -1197,9 +1198,9 @@ public void getHourlyResult(Response response) { * @param response */ @Override - public void getDailyResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getDaily(); + public void getDailyResult(DailyResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getDaily(); //判空处理 if (data != null && data.size() > 0) { tvTempHeight.setText(data.get(0).getTempMax() + "℃"); @@ -1223,7 +1224,7 @@ public void getDailyResult(Response response) { ToastUtils.showShortToast(context, "天气预报数据为空"); } } else {//异常状态码返回 - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -1233,10 +1234,10 @@ public void getDailyResult(Response response) { * @param response */ @Override - public void getAirNowResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - AirNowResponse.NowBean data = response.body().getNow(); - if (response.body().getNow() != null) { + public void getAirNowResult(AirNowResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + AirNowResponse.NowBean data = response.getNow(); + if (response.getNow() != null) { airStr = "空气质量:" + data.getAqi() + ",空气" + data.getCategory() + "。"; @@ -1267,7 +1268,7 @@ public void getAirNowResult(Response response) { ToastUtils.showShortToast(context, "空气质量数据为空"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -1277,9 +1278,9 @@ public void getAirNowResult(Response response) { * @param response */ @Override - public void getLifestyleResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getDaily(); + public void getLifestyleResult(LifestyleResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getDaily(); for (int i = 0; i < data.size(); i++) { switch (data.get(i).getType()) { @@ -1318,7 +1319,7 @@ public void getLifestyleResult(Response response) { //图标显示 ivVoiceBroadcast.setVisibility(View.VISIBLE); } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -1328,11 +1329,11 @@ public void getLifestyleResult(Response response) { * @param response */ @Override - public void getNowWarnResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getWarning(); + public void getNowWarnResult(WarningResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getWarning(); if (data != null && data.size() > 0) { - warnBodyString = new Gson().toJson(response.body()); + warnBodyString = new Gson().toJson(response); //设置滚动标题和内容 tvWarn.setText(data.get(0).getTitle() + " " + data.get(0).getText()); tvWarn.setVisibility(View.VISIBLE);//当灾害预警有值时,显示这个TextView @@ -1343,7 +1344,7 @@ public void getNowWarnResult(Response response) { } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/NetworkRequiredInfo.java b/app/src/main/java/com/llw/goodweather/NetworkRequiredInfo.java new file mode 100644 index 0000000..b29c479 --- /dev/null +++ b/app/src/main/java/com/llw/goodweather/NetworkRequiredInfo.java @@ -0,0 +1,51 @@ +package com.llw.goodweather; + +import android.app.Application; + +import com.llw.mvplibrary.BuildConfig; +import com.llw.mvplibrary.newnet.INetworkRequiredInfo; + + +/** + * 网络访问信息 + * @author llw + */ +public class NetworkRequiredInfo implements INetworkRequiredInfo { + + private Application application; + + public NetworkRequiredInfo(Application application){ + this.application = application; + } + + /** + * 版本名 + */ + @Override + public String getAppVersionName() { + return BuildConfig.VERSION_NAME; + } + /** + * 版本号 + */ + @Override + public String getAppVersionCode() { + return String.valueOf(BuildConfig.VERSION_CODE); + } + + /** + * 是否为debug + */ + @Override + public boolean isDebug() { + return BuildConfig.DEBUG; + } + + /** + * 应用全局上下文 + */ + @Override + public Application getApplicationContext() { + return application; + } +} diff --git a/app/src/main/java/com/llw/goodweather/WeatherApplication.java b/app/src/main/java/com/llw/goodweather/WeatherApplication.java index 5b177b6..6180e44 100644 --- a/app/src/main/java/com/llw/goodweather/WeatherApplication.java +++ b/app/src/main/java/com/llw/goodweather/WeatherApplication.java @@ -13,6 +13,7 @@ import com.iflytek.cloud.SpeechUtility; import com.llw.goodweather.utils.GlideUtil; import com.llw.mvplibrary.BaseApplication; +import com.llw.mvplibrary.newnet.NetworkApi; import com.llw.mvplibrary.utils.ActivityManager; import com.scwang.smartrefresh.layout.SmartRefreshLayout; import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator; @@ -102,6 +103,9 @@ public void onActivityDestroyed(Activity activity) { } }); + //初始化网络框架 + NetworkApi.init(new NetworkRequiredInfo(this)); + //初始化数据库 LitePal.initialize(this); diff --git a/app/src/main/java/com/llw/goodweather/api/ApiService.java b/app/src/main/java/com/llw/goodweather/api/ApiService.java index 92bfa94..e95ad37 100644 --- a/app/src/main/java/com/llw/goodweather/api/ApiService.java +++ b/app/src/main/java/com/llw/goodweather/api/ApiService.java @@ -17,6 +17,7 @@ import com.llw.mvplibrary.bean.AppVersion; import com.llw.mvplibrary.bean.WallPaper; +import io.reactivex.Observable; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Path; @@ -42,13 +43,16 @@ public interface ApiService { * getTodayWeather是这个接口的方法名。这样说应该很清楚了吧 */ + + /** * 必应每日一图 * * @return BiYingImgResponse 必应壁纸返回 */ @GET("/HPImageArchive.aspx?format=js&idx=0&n=1") - Call biying(); + Observable biying(); +// Call biying(); /********** 以下为 V7版本API使用 **************/ @@ -59,7 +63,8 @@ public interface ApiService { * @return 返回实况天气数据 NowResponse */ @GET("/v7/weather/now?key=" + API_KEY + "&gzip=n") - Call nowWeather(@Query("location") String location); + Observable nowWeather(@Query("location") String location); + //Call nowWeather(@Query("location") String location); /** * 天气预报 因为是开发者所以最多可以获得15天的数据,但是如果你是普通用户,那么最多只能获得三天的数据 @@ -70,7 +75,8 @@ public interface ApiService { * @return 返回天气预报数据 DailyResponse */ @GET("/v7/weather/{type}?key=" + API_KEY) - Call dailyWeather(@Path("type") String type, @Query("location") String location); + Observable dailyWeather(@Path("type") String type, @Query("location") String location); + //Call dailyWeather(@Path("type") String type, @Query("location") String location); /** * 逐小时预报(未来24小时)之前是逐三小时预报 @@ -79,7 +85,8 @@ public interface ApiService { * @return 返回逐小时数据 MoreAirFiveResponse */ @GET("/v7/weather/24h?key=" + API_KEY) - Call hourlyWeather(@Query("location") String location); + Observable hourlyWeather(@Query("location") String location); + //Call hourlyWeather(@Query("location") String location); /** * 当天空气质量 @@ -88,7 +95,8 @@ public interface ApiService { * @return 返回当天空气质量数据 MoreAirFiveResponse */ @GET("/v7/air/now?key=" + API_KEY) - Call airNowWeather(@Query("location") String location); + Observable airNowWeather(@Query("location") String location); +// Call airNowWeather(@Query("location") String location); /** * 空气质量5天预报 @@ -97,7 +105,8 @@ public interface ApiService { * @return 返回空气质量5天预报数据 MoreAirFiveResponse */ @GET("/v7/air/5d?key=" + API_KEY) - Call airFiveWeather(@Query("location") String location); + Observable airFiveWeather(@Query("location") String location); +// Call airFiveWeather(@Query("location") String location); /** * 生活指数 @@ -110,8 +119,10 @@ public interface ApiService { * @return LifestyleResponse 生活指数数据返回 */ @GET("/v7/indices/1d?key=" + API_KEY) - Call lifestyle(@Query("type") String type, + Observable lifestyle(@Query("type") String type, @Query("location") String location); +// Call lifestyle(@Query("type") String type, +// @Query("location") String location); /** * 搜索城市 V7版本 模糊搜索,国内范围 返回10条数据 @@ -121,8 +132,10 @@ Call lifestyle(@Query("type") String type, * @return NewSearchCityResponse 搜索城市数据返回 */ @GET("/v2/city/lookup?key=" + API_KEY + "&range=cn") - Call newSearchCity(@Query("location") String location, + Observable newSearchCity(@Query("location") String location, @Query("mode") String mode); +// Call newSearchCity(@Query("location") String location, +// @Query("mode") String mode); /** * 世界城市 @@ -131,7 +144,8 @@ Call newSearchCity(@Query("location") String location, * @return WorldCityResponse 世界城市数据返回 */ @GET("/v2/city/top?key=" + API_KEY + "&number=20") - Call worldCity(@Query("range") String range); + Observable worldCity(@Query("range") String range); + //Call worldCity(@Query("range") String range); /** * 当前城市灾害预警 @@ -140,7 +154,8 @@ Call newSearchCity(@Query("location") String location, * @return WarningResponse 灾害预警返回 */ @GET("/v7/warning/now?key=" + API_KEY) - Call nowWarn(@Query("location") String location); + Observable nowWarn(@Query("location") String location); + //Call nowWarn(@Query("location") String location); /** * APP版本更新 @@ -148,7 +163,9 @@ Call newSearchCity(@Query("location") String location, * @return AppVersion 版本信息返回 */ @GET("/apps/latest/" + UPDATE_USER_ID + "?api_token=" + UPDATE_API_TOKEN) - Call getAppInfo(); + Observable getAppInfo(); +// @GET("/apps/latest/" + UPDATE_USER_ID + "?api_token=" + UPDATE_API_TOKEN) +// Call getAppInfo(); /** * 太阳和月亮 日出日落、月升月落 @@ -158,7 +175,8 @@ Call newSearchCity(@Query("location") String location, * @return SunMoonResponse 太阳和月亮数据返回 */ @GET("/v7/astronomy/sunmoon?key=" + API_KEY) - Call getSunMoon(@Query("location") String location, @Query("date") String date); + Observable getSunMoon(@Query("location") String location, @Query("date") String date); + //Call getSunMoon(@Query("location") String location, @Query("date") String date); /** * 手机壁纸API @@ -166,7 +184,8 @@ Call newSearchCity(@Query("location") String location, * @return WallPaperResponse 网络壁纸数据返回 */ @GET("/v1/vertical/vertical?limit=30&skip=180&adult=false&first=0&order=hot") - Call getWallPaper(); + Observable getWallPaper(); + //Call getWallPaper(); /** @@ -176,6 +195,7 @@ Call newSearchCity(@Query("location") String location, * @return */ @GET("/v7/minutely/5m?key=" + API_KEY) - Call getMinutePrec(@Query("location") String location); + Observable getMinutePrec(@Query("location") String location); + //Call getMinutePrec(@Query("location") String location); } diff --git a/app/src/main/java/com/llw/goodweather/contract/MapWeatherContract.java b/app/src/main/java/com/llw/goodweather/contract/MapWeatherContract.java index f6cf779..61580b4 100644 --- a/app/src/main/java/com/llw/goodweather/contract/MapWeatherContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/MapWeatherContract.java @@ -1,5 +1,7 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.AirNowResponse; import com.llw.goodweather.bean.DailyResponse; @@ -9,11 +11,8 @@ import com.llw.goodweather.bean.SunMoonResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 地图天气订阅器 @@ -30,23 +29,25 @@ public static class MapWeatherPresenter extends BasePresenter { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void searchCity(String location) {//注意这里的4表示新的搜索城市地址接口 - ApiService service = ServiceGenerator.createService(ApiService.class, 4);//指明访问的地址 - service.newSearchCity(location, "exact").enqueue(new NetCallBack() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getNewSearchCityResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 4);//指明访问的地址 + service.newSearchCity(location, "exact") + .compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(NewSearchCityResponse newSearchCityResponse) { + if (getView() != null) { + getView().getNewSearchCityResult(newSearchCityResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } @@ -55,23 +56,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void nowWeather(String location) {//这个3 表示使用新的V7API访问地址 - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.nowWeather(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.nowWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(NowResponse nowResponse) { if (getView() != null) { - getView().getNowResult(response); + getView().getNowResult(nowResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } /** @@ -79,23 +81,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void weatherHourly(String location) {//这个3 表示使用新的V7API访问地址 - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.hourlyWeather(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.hourlyWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(HourlyResponse hourlyResponse) { if (getView() != null) { - getView().getWeatherHourlyResult(response); + getView().getWeatherHourlyResult(hourlyResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } @@ -104,23 +107,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void dailyWeather(String location) {//这个3 表示使用新的V7API访问地址 - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.dailyWeather("7d", location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.dailyWeather("7d", location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(DailyResponse dailyResponse) { if (getView() != null) { - getView().getDailyResult(response); + getView().getDailyResult(dailyResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } /** @@ -128,23 +132,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void airNowWeather(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.airNowWeather(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.airNowWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(AirNowResponse airNowResponse) { if (getView() != null) { - getView().getAirNowResult(response); + getView().getAirNowResult(airNowResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } /** @@ -152,45 +157,46 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void getSunMoon(String location, String date) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.getSunMoon(location, date).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.getSunMoon(location, date).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(SunMoonResponse sunMoonResponse) { if (getView() != null) { - getView().getSunMoonResult(response); + getView().getSunMoonResult(sunMoonResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } } public interface IMapWeatherView extends BaseView { //搜索城市返回城市id 通过id才能查下面的数据,否则会提示400 V7 - void getNewSearchCityResult(Response response); + void getNewSearchCityResult(NewSearchCityResponse response); //实况天气 - void getNowResult(Response response); + void getNowResult(NowResponse response); //24小时天气预报 - void getWeatherHourlyResult(Response response); + void getWeatherHourlyResult(HourlyResponse response); //天气预报 7天 - void getDailyResult(Response response); + void getDailyResult(DailyResponse response); //空气质量 - void getAirNowResult(Response response); + void getAirNowResult(AirNowResponse response); //太阳和月亮 - void getSunMoonResult(Response response); + void getSunMoonResult(SunMoonResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/MoreAirContract.java b/app/src/main/java/com/llw/goodweather/contract/MoreAirContract.java index ae206f4..707be6e 100644 --- a/app/src/main/java/com/llw/goodweather/contract/MoreAirContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/MoreAirContract.java @@ -1,17 +1,15 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.AirNowResponse; -import com.llw.goodweather.bean.DailyResponse; import com.llw.goodweather.bean.MoreAirFiveResponse; import com.llw.goodweather.bean.NewSearchCityResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 更多空气质量数据订阅器 @@ -29,23 +27,25 @@ public static class MoreAirPresenter extends BasePresenter { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void searchCityId(String location) {//注意这里的4表示新的搜索城市地址接口 - ApiService service = ServiceGenerator.createService(ApiService.class, 4);//指明访问的地址 - service.newSearchCity(location, "exact").enqueue(new NetCallBack() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getSearchCityIdResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 4);//指明访问的地址 + service.newSearchCity(location, "exact") + .compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(NewSearchCityResponse newSearchCityResponse) { + if (getView() != null) { + getView().getSearchCityIdResult(newSearchCityResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } @@ -54,23 +54,24 @@ public void onFailed() { * * @param location 城市id */ + @SuppressLint("CheckResult") public void air(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.airNowWeather(location).enqueue(new NetCallBack() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getMoreAirResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.airNowWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(AirNowResponse airNowResponse) { + if (getView() != null) { + getView().getMoreAirResult(airNowResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } /** @@ -78,23 +79,25 @@ public void onFailed() { * * @param location 城市id */ + @SuppressLint("CheckResult") public void airFive(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.airFiveWeather(location).enqueue(new NetCallBack() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getMoreAirFiveResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.airFiveWeather(location) + .compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(MoreAirFiveResponse moreAirFiveResponse) { + if (getView() != null) { + getView().getMoreAirFiveResult(moreAirFiveResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } } @@ -102,13 +105,13 @@ public void onFailed() { public interface IMoreAirView extends BaseView { //搜索城市Id - void getSearchCityIdResult(Response response); + void getSearchCityIdResult(NewSearchCityResponse response); //空气质量返回数据 V7 - void getMoreAirResult(Response response); + void getMoreAirResult(AirNowResponse response); //五天空气质量数据返回 V7 - void getMoreAirFiveResult(Response response); + void getMoreAirFiveResult(MoreAirFiveResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/MoreDailyContract.java b/app/src/main/java/com/llw/goodweather/contract/MoreDailyContract.java index cbf204b..653d106 100644 --- a/app/src/main/java/com/llw/goodweather/contract/MoreDailyContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/MoreDailyContract.java @@ -1,15 +1,13 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.DailyResponse; -import com.llw.goodweather.bean.WorldCityResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 更多天气预报订阅器 @@ -25,23 +23,24 @@ public static class MoreDailyPresenter extends BasePresenter { * * @param location 城市id */ + @SuppressLint("CheckResult") public void dailyWeather(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.dailyWeather("15d", location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.dailyWeather("15d", location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(DailyResponse dailyResponse) { if (getView() != null) { - getView().getMoreDailyResult(response); + getView().getMoreDailyResult(dailyResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } } @@ -49,7 +48,7 @@ public void onFailed() { public interface IMoreDailyView extends BaseView { //更多天气预报返回数据 V7 - void getMoreDailyResult(Response response); + void getMoreDailyResult(DailyResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/MoreLifestyleContract.java b/app/src/main/java/com/llw/goodweather/contract/MoreLifestyleContract.java index 63b346a..14ea7a0 100644 --- a/app/src/main/java/com/llw/goodweather/contract/MoreLifestyleContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/MoreLifestyleContract.java @@ -1,15 +1,14 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; -import com.llw.goodweather.bean.DailyResponse; import com.llw.goodweather.bean.LifestyleResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; -import retrofit2.Call; -import retrofit2.Response; /** * 更多生活指数订阅器 @@ -25,23 +24,25 @@ public static class MoreLifestylePresenter extends BasePresenter() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getMoreLifestyleResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.lifestyle("0", location) + .compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(LifestyleResponse lifestyleResponse) { + if (getView() != null) { + getView().getMoreLifestyleResult(lifestyleResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } } @@ -49,7 +50,7 @@ public void onFailed() { public interface IMoreLifestyleView extends BaseView { //更多生活指数返回数据 V7 - void getMoreLifestyleResult(Response response); + void getMoreLifestyleResult(LifestyleResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/SearchCityContract.java b/app/src/main/java/com/llw/goodweather/contract/SearchCityContract.java index 6aabe54..db2ced2 100644 --- a/app/src/main/java/com/llw/goodweather/contract/SearchCityContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/SearchCityContract.java @@ -1,14 +1,13 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.NewSearchCityResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 搜索城市订阅器 V7 @@ -23,30 +22,32 @@ public static class SearchCityPresenter extends BasePresenter { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void newSearchCity(String location) {//注意这里的4表示新的搜索城市地址接口 - ApiService service = ServiceGenerator.createService(ApiService.class, 4);//指明访问的地址 - service.newSearchCity(location, "fuzzy").enqueue(new NetCallBack() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getNewSearchCityResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 4);//指明访问的地址 + service.newSearchCity(location, "exact") + .compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(NewSearchCityResponse newSearchCityResponse) { + if (getView() != null) { + getView().getNewSearchCityResult(newSearchCityResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } } public interface ISearchCityView extends BaseView { //搜索城市返回数据 V7 - void getNewSearchCityResult(Response response); + void getNewSearchCityResult(NewSearchCityResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/SplashContract.java b/app/src/main/java/com/llw/goodweather/contract/SplashContract.java index 525d2d4..98f8f3b 100644 --- a/app/src/main/java/com/llw/goodweather/contract/SplashContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/SplashContract.java @@ -1,17 +1,14 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.BiYingImgResponse; -import com.llw.goodweather.bean.NewSearchCityResponse; -import com.llw.goodweather.bean.NowResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; import com.llw.mvplibrary.bean.AppVersion; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 欢迎页订阅器 @@ -25,57 +22,59 @@ public static class SplashPresenter extends BasePresenter { /** * 获取最新的APP版本信息 */ + @SuppressLint("CheckResult") public void getAppInfo() {//注意这里的4表示新的搜索城市地址接口 - ApiService service = ServiceGenerator.createService(ApiService.class, 5); - service.getAppInfo().enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 5); + service.getAppInfo().compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(AppVersion appVersion) { if (getView() != null) { - getView().getAppInfoResult(response); + getView().getAppInfoResult(appVersion); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } /** * 获取必应 每日一图 */ + @SuppressLint("CheckResult") public void biying() { - ApiService service = ServiceGenerator.createService(ApiService.class, 1); - service.biying().enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 1); + service.biying().compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(BiYingImgResponse biYingImgResponse) { if (getView() != null) { - getView().getBiYingResult(response); + getView().getBiYingResult(biYingImgResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } } public interface ISplashView extends BaseView { //APP信息返回 - void getAppInfoResult(Response response); + void getAppInfoResult(AppVersion response); /** * 获取必应每日一图返回 * @param response BiYingImgResponse */ - void getBiYingResult(Response response); + void getBiYingResult(BiYingImgResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/WallPaperContract.java b/app/src/main/java/com/llw/goodweather/contract/WallPaperContract.java index b560067..11355de 100644 --- a/app/src/main/java/com/llw/goodweather/contract/WallPaperContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/WallPaperContract.java @@ -1,17 +1,14 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.BiYingImgResponse; import com.llw.goodweather.bean.WallPaperResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.bean.AppVersion; -import com.llw.mvplibrary.bean.WallPaper; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 壁纸订阅器 @@ -26,47 +23,49 @@ public static class WallPaperPresenter extends BasePresenter { /** * 获取必应 每日一图 */ + @SuppressLint("CheckResult") public void biying() { - ApiService service = ServiceGenerator.createService(ApiService.class, 1); - service.biying().enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 1); + service.biying().compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(BiYingImgResponse biYingImgResponse) { if (getView() != null) { - getView().getBiYingResult(response); + getView().getBiYingResult(biYingImgResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } /** * 获取壁纸数据 */ + @SuppressLint("CheckResult") public void getWallPaper() { // 6 表示访问网络壁纸接口 - ApiService service = ServiceGenerator.createService(ApiService.class, 6); - service.getWallPaper().enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 6); + service.getWallPaper().compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(WallPaperResponse wallPaperResponse) { if (getView() != null) { - getView().getWallPaperResult(response); + getView().getWallPaperResult(wallPaperResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } } @@ -76,13 +75,13 @@ public interface IWallPaperView extends BaseView { * 获取必应每日一图返回 * @param response BiYingImgResponse */ - void getBiYingResult(Response response); + void getBiYingResult(BiYingImgResponse response); /** * 壁纸数据返回 * @param response WallPaperResponse */ - void getWallPaperResult(Response response); + void getWallPaperResult(WallPaperResponse response); /** * 错误返回 diff --git a/app/src/main/java/com/llw/goodweather/contract/WeatherContract.java b/app/src/main/java/com/llw/goodweather/contract/WeatherContract.java index 6c6661a..4c306da 100644 --- a/app/src/main/java/com/llw/goodweather/contract/WeatherContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/WeatherContract.java @@ -1,10 +1,8 @@ package com.llw.goodweather.contract; -import android.content.Context; - +import android.annotation.SuppressLint; import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.AirNowResponse; -import com.llw.goodweather.bean.BiYingImgResponse; import com.llw.goodweather.bean.DailyResponse; import com.llw.goodweather.bean.HourlyResponse; import com.llw.goodweather.bean.LifestyleResponse; @@ -14,11 +12,8 @@ import com.llw.goodweather.bean.WarningResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 天气订阅器 @@ -36,23 +31,25 @@ public static class WeatherPresenter extends BasePresenter { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void newSearchCity(String location) {//注意这里的4表示新的搜索城市地址接口 - ApiService service = ServiceGenerator.createService(ApiService.class, 4);//指明访问的地址 - service.newSearchCity(location, "exact").enqueue(new NetCallBack() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getNewSearchCityResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 4);//指明访问的地址 + service.newSearchCity(location, "exact") + .compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(NewSearchCityResponse newSearchCityResponse) { + if (getView() != null) { + getView().getNewSearchCityResult(newSearchCityResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } @@ -61,23 +58,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void nowWeather(String location) {//这个3 表示使用新的V7API访问地址 - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.nowWeather(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.nowWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(NowResponse nowResponse) { if (getView() != null) { - getView().getNowResult(response); + getView().getNowResult(nowResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getWeatherDataFailed(); } } - }); + })); } /** @@ -85,23 +83,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void dailyWeather(String location) {//这个3 表示使用新的V7API访问地址 - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.dailyWeather("7d", location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.dailyWeather("7d", location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(DailyResponse dailyResponse) { if (getView() != null) { - getView().getDailyResult(response); + getView().getDailyResult(dailyResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getWeatherDataFailed(); } } - }); + })); } /** @@ -109,23 +108,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void hourlyWeather(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.hourlyWeather(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.hourlyWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(HourlyResponse hourlyResponse) { if (getView() != null) { - getView().getHourlyResult(response); + getView().getHourlyResult(hourlyResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getWeatherDataFailed(); } } - }); + })); } /** @@ -133,23 +133,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void airNowWeather(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.airNowWeather(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.airNowWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(AirNowResponse airNowResponse) { if (getView() != null) { - getView().getAirNowResult(response); + getView().getAirNowResult(airNowResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getWeatherDataFailed(); } } - }); + })); } /** @@ -157,23 +158,25 @@ public void onFailed() { * * @param location 城市名 type中的"1,2,3,5,6,8,9,10",表示只获取这8种类型的指数信息,同样是为了对应之前的界面UI */ + @SuppressLint("CheckResult") public void lifestyle(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.lifestyle("1,2,3,5,6,8,9,10", location).enqueue(new NetCallBack() { - @Override - public void onSuccess(Call call, Response response) { - if (getView() != null) { - getView().getLifestyleResult(response); - } - } - - @Override - public void onFailed() { - if (getView() != null) { - getView().getWeatherDataFailed(); - } - } - }); + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.lifestyle("0", location) + .compose(NetworkApi.applySchedulers(new BaseObserver() { + @Override + public void onSuccess(LifestyleResponse lifestyleResponse) { + if (getView() != null) { + getView().getLifestyleResult(lifestyleResponse); + } + } + + @Override + public void onFailure(Throwable e) { + if (getView() != null) { + getView().getDataFailed(); + } + } + })); } /** @@ -181,23 +184,24 @@ public void onFailed() { * * @param location 城市id */ + @SuppressLint("CheckResult") public void nowWarn(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.nowWarn(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.nowWarn(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(WarningResponse warningResponse) { if (getView() != null) { - getView().getNowWarnResult(response); + getView().getNowWarnResult(warningResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getWeatherDataFailed(); } } - }); + })); } /** @@ -205,23 +209,24 @@ public void onFailed() { * * @param location 经纬度拼接字符串,使用英文逗号分隔,经度在前纬度在后 */ + @SuppressLint("CheckResult") public void getMinutePrec(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.getMinutePrec(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.getMinutePrec(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(MinutePrecResponse minutePrecResponse) { if (getView() != null) { - getView().getMinutePrecResult(response); + getView().getMinutePrecResult(minutePrecResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getWeatherDataFailed(); } } - }); + })); } @@ -236,28 +241,28 @@ public interface IWeatherView extends BaseView { /* 以下为V7版本新增 */ //搜索城市返回城市id 通过id才能查下面的数据,否则会提示400 V7 - void getNewSearchCityResult(Response response); + void getNewSearchCityResult(NewSearchCityResponse response); //实况天气 - void getNowResult(Response response); + void getNowResult(NowResponse response); //天气预报 7天 - void getDailyResult(Response response); + void getDailyResult(DailyResponse response); //逐小时天气预报 - void getHourlyResult(Response response); + void getHourlyResult(HourlyResponse response); //空气质量 - void getAirNowResult(Response response); + void getAirNowResult(AirNowResponse response); //生活指数 - void getLifestyleResult(Response response); + void getLifestyleResult(LifestyleResponse response); //灾害预警 - void getNowWarnResult(Response response); + void getNowWarnResult(WarningResponse response); //分钟级降水 - void getMinutePrecResult(Response response); + void getMinutePrecResult(MinutePrecResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/WorldCityContract.java b/app/src/main/java/com/llw/goodweather/contract/WorldCityContract.java index 0296682..5affac9 100644 --- a/app/src/main/java/com/llw/goodweather/contract/WorldCityContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/WorldCityContract.java @@ -1,14 +1,13 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.WorldCityResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; -import retrofit2.Call; -import retrofit2.Response; /** * 世界城市订阅器 @@ -24,23 +23,24 @@ public static class WorldCityPresenter extends BasePresenter { * * @param range 类型 */ + @SuppressLint("CheckResult") public void worldCity(String range) { - ApiService service = ServiceGenerator.createService(ApiService.class, 4);//指明访问的地址 - service.worldCity(range).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 4);//指明访问的地址 + service.worldCity(range).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(WorldCityResponse worldCityResponse) { if (getView() != null) { - getView().getWorldCityResult(response); + getView().getWorldCityResult(worldCityResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } } @@ -48,7 +48,7 @@ public void onFailed() { public interface IWorldCityView extends BaseView { //热门城市返回数据 V7 - void getWorldCityResult(Response response); + void getWorldCityResult(WorldCityResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/contract/WorldCityWeatherContract.java b/app/src/main/java/com/llw/goodweather/contract/WorldCityWeatherContract.java index 367eea1..bc68b65 100644 --- a/app/src/main/java/com/llw/goodweather/contract/WorldCityWeatherContract.java +++ b/app/src/main/java/com/llw/goodweather/contract/WorldCityWeatherContract.java @@ -1,16 +1,15 @@ package com.llw.goodweather.contract; +import android.annotation.SuppressLint; + import com.llw.goodweather.api.ApiService; import com.llw.goodweather.bean.DailyResponse; import com.llw.goodweather.bean.HourlyResponse; import com.llw.goodweather.bean.NowResponse; import com.llw.mvplibrary.base.BasePresenter; import com.llw.mvplibrary.base.BaseView; -import com.llw.mvplibrary.net.NetCallBack; -import com.llw.mvplibrary.net.ServiceGenerator; - -import retrofit2.Call; -import retrofit2.Response; +import com.llw.mvplibrary.newnet.NetworkApi; +import com.llw.mvplibrary.newnet.observer.BaseObserver; /** * 世界城市天气订阅器 @@ -26,23 +25,24 @@ public static class WorldCityWeatherPresenter extends BasePresenter() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.nowWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(NowResponse nowResponse) { if (getView() != null) { - getView().getNowResult(response); + getView().getNowResult(nowResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } /** @@ -50,23 +50,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void dailyWeather(String location) {//这个3 表示使用新的V7API访问地址 - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.dailyWeather("7d", location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.dailyWeather("7d", location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(DailyResponse dailyResponse) { if (getView() != null) { - getView().getDailyResult(response); + getView().getDailyResult(dailyResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } /** @@ -74,23 +75,24 @@ public void onFailed() { * * @param location 城市名 */ + @SuppressLint("CheckResult") public void hourlyWeather(String location) { - ApiService service = ServiceGenerator.createService(ApiService.class, 3); - service.hourlyWeather(location).enqueue(new NetCallBack() { + ApiService service = NetworkApi.createService(ApiService.class, 3); + service.hourlyWeather(location).compose(NetworkApi.applySchedulers(new BaseObserver() { @Override - public void onSuccess(Call call, Response response) { + public void onSuccess(HourlyResponse hourlyResponse) { if (getView() != null) { - getView().getHourlyResult(response); + getView().getHourlyResult(hourlyResponse); } } @Override - public void onFailed() { + public void onFailure(Throwable e) { if (getView() != null) { getView().getDataFailed(); } } - }); + })); } } @@ -98,13 +100,13 @@ public void onFailed() { public interface IWorldCityWeatherView extends BaseView { /* 以下为V7版本新增 */ //实况天气 - void getNowResult(Response response); + void getNowResult(NowResponse response); //天气预报 7天 - void getDailyResult(Response response); + void getDailyResult(DailyResponse response); //逐小时天气预报 - void getHourlyResult(Response response); + void getHourlyResult(HourlyResponse response); //错误返回 void getDataFailed(); diff --git a/app/src/main/java/com/llw/goodweather/ui/CommonlyUsedCityActivity.java b/app/src/main/java/com/llw/goodweather/ui/CommonlyUsedCityActivity.java index a19e542..c61d7f1 100644 --- a/app/src/main/java/com/llw/goodweather/ui/CommonlyUsedCityActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/CommonlyUsedCityActivity.java @@ -225,14 +225,14 @@ protected SearchCityContract.SearchCityPresenter createPresent() { * @param response */ @Override - public void getNewSearchCityResult(Response response) { + public void getNewSearchCityResult(NewSearchCityResponse response) { dismissLoadingDialog(); - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getLocation(); + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getLocation(); if (data != null && data.size() > 0) { rvCommonlyUsed.setVisibility(View.GONE);//隐藏常用城市列表 mList.clear(); - mList.addAll(response.body().getLocation()); + mList.addAll(response.getLocation()); mAdapterAdd.notifyDataSetChanged(); rvSearch.setVisibility(View.VISIBLE);//显示搜索城市列表 layNormal.setVisibility(View.GONE); @@ -240,7 +240,7 @@ public void getNewSearchCityResult(Response response) { ToastUtils.showShortToast(context, "没有找到相关城市"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/ui/MapWeatherActivity.java b/app/src/main/java/com/llw/goodweather/ui/MapWeatherActivity.java index 1733732..af13237 100644 --- a/app/src/main/java/com/llw/goodweather/ui/MapWeatherActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/MapWeatherActivity.java @@ -415,7 +415,7 @@ public void onViewClicked(View view) { initClose(); break; case R.id.voice_search://语音搜索 - SpeechUtil.startDictation(cityName -> { + SpeechUtil.startDictation(this, cityName -> { if (cityName.isEmpty()) { return; } @@ -654,11 +654,11 @@ public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) * @param response */ @Override - public void getNewSearchCityResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - if (response.body().getLocation() != null && response.body().getLocation().size() > 0) { - tvCity.setText(response.body().getLocation().get(0).getName());//城市 - locationId = response.body().getLocation().get(0).getId();//城市Id + public void getNewSearchCityResult(NewSearchCityResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + if (response.getLocation() != null && response.getLocation().size() > 0) { + tvCity.setText(response.getLocation().get(0).getName());//城市 + locationId = response.getLocation().get(0).getId();//城市Id showLoadingDialog(); mPresent.nowWeather(locationId);//查询实况天气 mPresent.airNowWeather(locationId);//空气质量 @@ -670,7 +670,7 @@ public void getNewSearchCityResult(Response response) { } } else { tvCity.setText("查询城市失败"); - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -680,39 +680,34 @@ public void getNewSearchCityResult(Response response) { * @param response */ @Override - public void getNowResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) {//200则成功返回数据 - NowResponse data = response.body(); - if (data != null) { - Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Light.ttf"); - tvTemperature.setText(response.body().getNow().getTemp() + "°");//温度 - tvTemperature.setTypeface(typeface);//使用字体 - tvWeatherStateTv.setText(data.getNow().getText());//天气状态文字描述 - WeatherUtil.changeIcon(ivWeather, Integer.parseInt(data.getNow().getIcon())); - tvWindInfo.setText(data.getNow().getWindDir() + data.getNow().getWindScale() + "级"); - - tvHumidity.setText(data.getNow().getHumidity() + "%");//湿度 - tvPressure.setText(data.getNow().getPressure() + "hPa");//大气压 - - //今日详情 - todayDetailList.clear(); - todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_temp, data.getNow().getFeelsLike() + "°", "体感温度")); - todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_precip, data.getNow().getPrecip() + "mm", "降水量")); - todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_humidity, data.getNow().getHumidity() + "%", "湿度")); - todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_pressure, data.getNow().getPressure() + "hPa", "大气压强")); - todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_vis, data.getNow().getVis() + "KM", "能见度")); - todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_cloud, data.getNow().getCloud() + "%", "云量")); - - TodayDetailAdapter adapter = new TodayDetailAdapter(R.layout.item_today_detail, todayDetailList); - rvTodayDetail.setLayoutManager(new GridLayoutManager(context, 3)); - rvTodayDetail.setAdapter(adapter); - adapter.notifyDataSetChanged(); + public void getNowResult(NowResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) {//200则成功返回数据 + Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Light.ttf"); + tvTemperature.setText(response.getNow().getTemp() + "°");//温度 + tvTemperature.setTypeface(typeface);//使用字体 + tvWeatherStateTv.setText(response.getNow().getText());//天气状态文字描述 + WeatherUtil.changeIcon(ivWeather, Integer.parseInt(response.getNow().getIcon())); + tvWindInfo.setText(response.getNow().getWindDir() + response.getNow().getWindScale() + "级"); + + tvHumidity.setText(response.getNow().getHumidity() + "%");//湿度 + tvPressure.setText(response.getNow().getPressure() + "hPa");//大气压 + + //今日详情 + todayDetailList.clear(); + todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_temp, response.getNow().getFeelsLike() + "°", "体感温度")); + todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_precip, response.getNow().getPrecip() + "mm", "降水量")); + todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_humidity, response.getNow().getHumidity() + "%", "湿度")); + todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_pressure, response.getNow().getPressure() + "hPa", "大气压强")); + todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_vis, response.getNow().getVis() + "KM", "能见度")); + todayDetailList.add(new TodayDetailBean(R.mipmap.icon_today_cloud, response.getNow().getCloud() + "%", "云量")); + + TodayDetailAdapter adapter = new TodayDetailAdapter(R.layout.item_today_detail, todayDetailList); + rvTodayDetail.setLayoutManager(new GridLayoutManager(context, 3)); + rvTodayDetail.setAdapter(adapter); + adapter.notifyDataSetChanged(); - } else { - ToastUtils.showShortToast(context, "暂无实况天气数据"); - } } else {//其他状态返回提示文字 - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -722,9 +717,9 @@ public void getNowResult(Response response) { * @param response */ @Override - public void getWeatherHourlyResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List hourlyWeatherList = response.body().getHourly(); + public void getWeatherHourlyResult(HourlyResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List hourlyWeatherList = response.getHourly(); List data = new ArrayList<>(); if (hourlyWeatherList.size() > 23) { for (int i = 0; i < 24; i++) { @@ -771,7 +766,7 @@ public void getWeatherHourlyResult(Response response) { tvLineMaxTmp.setText(maxTmp + "°"); tvLineMinTmp.setText(minTmp + "°"); } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -781,9 +776,9 @@ public void getWeatherHourlyResult(Response response) { * @param response */ @Override - public void getDailyResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getDaily(); + public void getDailyResult(DailyResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getDaily(); if (data != null && data.size() > 0) {//判空处理 for (int i = 0; i < data.size(); i++) { @@ -800,7 +795,7 @@ public void getDailyResult(Response response) { ToastUtils.showShortToast(context, "天气预报数据为空"); } } else {//异常状态码返回 - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -810,10 +805,10 @@ public void getDailyResult(Response response) { * @param response */ @Override - public void getAirNowResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - AirNowResponse.NowBean data = response.body().getNow(); - if (response.body().getNow() != null) { + public void getAirNowResult(AirNowResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + AirNowResponse.NowBean data = response.getNow(); + if (response.getNow() != null) { dismissLoadingDialog(); tvAir.setText("AQI " + data.getCategory()); tvTodayInfo.setText("今天,白天" + dayInfo + ",晚上" + nightInfo + @@ -823,7 +818,7 @@ public void getAirNowResult(Response response) { ToastUtils.showShortToast(context, "空气质量数据为空"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -833,29 +828,23 @@ public void getAirNowResult(Response response) { * @param response */ @Override - public void getSunMoonResult(Response response) { - - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - - SunMoonResponse data = response.body(); - if (data != null) { - String sunRise = updateTime(data.getSunrise()); - String moonRise = updateTime(data.getMoonrise()); - String sunSet = updateTime(data.getSunset()); - String moonSet = updateTime(data.getMoonset()); - String currentTime = updateTime(null); - - sunView.setTimes(sunRise, sunSet, currentTime); - moonView.setTimes(moonRise, moonSet, currentTime); - if (data.getMoonPhase() != null && data.getMoonPhase().size() > 0) { - tvMoonState.setText(data.getMoonPhase().get(0).getName()); - } - - } else { - ToastUtils.showShortToast(context, "日出日落数据为空"); + public void getSunMoonResult(SunMoonResponse response) { + + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + String sunRise = updateTime(response.getSunrise()); + String moonRise = updateTime(response.getMoonrise()); + String sunSet = updateTime(response.getSunset()); + String moonSet = updateTime(response.getMoonset()); + String currentTime = updateTime(null); + + sunView.setTimes(sunRise, sunSet, currentTime); + moonView.setTimes(moonRise, moonSet, currentTime); + if (response.getMoonPhase() != null && response.getMoonPhase().size() > 0) { + tvMoonState.setText(response.getMoonPhase().get(0).getName()); } + } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/ui/MoreAirActivity.java b/app/src/main/java/com/llw/goodweather/ui/MoreAirActivity.java index 3700fc7..8d67bfc 100644 --- a/app/src/main/java/com/llw/goodweather/ui/MoreAirActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/MoreAirActivity.java @@ -102,11 +102,11 @@ protected MoreAirContract.MoreAirPresenter createPresent() { * @param response */ @Override - public void getSearchCityIdResult(Response response) { + public void getSearchCityIdResult(NewSearchCityResponse response) { dismissLoadingDialog(); - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { showLoadingDialog(); - List data = response.body().getLocation(); + List data = response.getLocation(); if (data != null && data.size() > 0) { mPresent.air(data.get(0).getId());//查询该站点的空气质量数据 mPresent.airFive(data.get(0).getId());//查询该站点的空气质量数据 @@ -115,7 +115,7 @@ public void getSearchCityIdResult(Response response) { } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -125,13 +125,13 @@ public void getSearchCityIdResult(Response response) { * @param response */ @Override - public void getMoreAirResult(Response response) { + public void getMoreAirResult(AirNowResponse response) { dismissLoadingDialog(); - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - AirNowResponse.NowBean data = response.body().getNow(); - List station = response.body().getStation(); - if (response.body().getNow() != null) { - String time = DateUtils.updateTime(response.body().getUpdateTime());//截去前面的字符,保留后面所有的字符,就剩下 22:00 + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + AirNowResponse.NowBean data = response.getNow(); + List station = response.getStation(); + if (response.getNow() != null) { + String time = DateUtils.updateTime(response.getUpdateTime());//截去前面的字符,保留后面所有的字符,就剩下 22:00 tvOldTime.setText("最近更新时间:" + WeatherUtil.showTimeInfo(time) + time); showAirBasicData(data);//展示基础数据 @@ -149,7 +149,7 @@ public void getMoreAirResult(Response response) { ToastUtils.showShortToast(context, "空气质量数据为空"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -159,9 +159,9 @@ public void getMoreAirResult(Response response) { * @param response */ @Override - public void getMoreAirFiveResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getDaily(); + public void getMoreAirFiveResult(MoreAirFiveResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getDaily(); if (data != null && data.size() > 0) { MoreAirFiveAdapter adapter = new MoreAirFiveAdapter(R.layout.item_more_air_five_list, data); LinearLayoutManager manager = new LinearLayoutManager(context); @@ -172,7 +172,7 @@ public void getMoreAirFiveResult(Response response) { ToastUtils.showShortToast(context, "未来5天空气质量数据为空"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/ui/MoreDailyActivity.java b/app/src/main/java/com/llw/goodweather/ui/MoreDailyActivity.java index 1fbfc0e..e8248be 100644 --- a/app/src/main/java/com/llw/goodweather/ui/MoreDailyActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/MoreDailyActivity.java @@ -91,10 +91,10 @@ protected MoreDailyContract.MoreDailyPresenter createPresent() { * @param response */ @Override - public void getMoreDailyResult(Response response) { + public void getMoreDailyResult(DailyResponse response) { dismissLoadingDialog(); - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getDaily(); + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getDaily(); //判空处理 if (data != null && data.size() > 0) { //添加数据之前先清除 @@ -115,7 +115,7 @@ public void getMoreDailyResult(Response response) { ToastUtils.showShortToast(context, "天气预报数据为空"); } } else {//异常状态码返回 - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/ui/MoreLifestyleActivity.java b/app/src/main/java/com/llw/goodweather/ui/MoreLifestyleActivity.java index bcfdc78..d10b536 100644 --- a/app/src/main/java/com/llw/goodweather/ui/MoreLifestyleActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/MoreLifestyleActivity.java @@ -67,10 +67,10 @@ protected MoreLifestyleContract.MoreLifestylePresenter createPresent() { * @param response */ @Override - public void getMoreLifestyleResult(Response response) { + public void getMoreLifestyleResult(LifestyleResponse response) { dismissLoadingDialog(); - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getDaily(); + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getDaily(); if (data != null && data.size() > 0) { MoreLifestyleAdapter adapter = new MoreLifestyleAdapter(R.layout.item_more_lifestyle_list, data); rv.setLayoutManager(new LinearLayoutManager(context)); @@ -80,7 +80,7 @@ public void getMoreLifestyleResult(Response response) { ToastUtils.showShortToast(context, "生活质量数据为空"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/ui/SearchCityActivity.java b/app/src/main/java/com/llw/goodweather/ui/SearchCityActivity.java index cd69b21..f0854c0 100644 --- a/app/src/main/java/com/llw/goodweather/ui/SearchCityActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/SearchCityActivity.java @@ -420,7 +420,7 @@ public void onViewClicked(View view) { break; //语音搜索 case R.id.voice_search: - SpeechUtil.startDictation(cityName -> { + SpeechUtil.startDictation(this, cityName -> { //判断字符串是否包含句号 if (!cityName.contains("。")) { @@ -454,15 +454,15 @@ public void onViewClicked(View view) { * @param response */ @Override - public void getNewSearchCityResult(Response response) { + public void getNewSearchCityResult(NewSearchCityResponse response) { dismissLoadingDialog(); - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { mList.clear(); - mList.addAll(response.body().getLocation()); + mList.addAll(response.getLocation()); mAdapter.notifyDataSetChanged(); runLayoutAnimation(rv); } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/ui/SplashActivity.java b/app/src/main/java/com/llw/goodweather/ui/SplashActivity.java index e95ca71..654796d 100644 --- a/app/src/main/java/com/llw/goodweather/ui/SplashActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/SplashActivity.java @@ -89,8 +89,6 @@ private void permissionsRequest() { .subscribe(granted -> { if (granted) {//申请成功 //得到权限可以进入APP - //加载世界国家数据到本地数据库,已有则不加载 - initCountryData(); //请求版本更新 mPresent.getAppInfo(); //获取必应壁纸 @@ -140,13 +138,10 @@ private void initCountryData() { * 进入主页面 */ private void goToMain() { - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - finish(); - Intent intent = new Intent(context, MainActivity.class); - startActivity(intent); - } + new Handler().postDelayed(() -> { + finish(); + Intent intent = new Intent(context, MainActivity.class); + startActivity(intent); }, 1000); } @@ -161,23 +156,23 @@ protected SplashContract.SplashPresenter createPresent() { * @param response */ @Override - public void getAppInfoResult(Response response) { - if (response.body() != null) { + public void getAppInfoResult(AppVersion response) { + if (response != null) { AppVersion appVersion = new AppVersion(); //应用名称 - appVersion.setName(response.body().getName()); + appVersion.setName(response.getName()); //应用版本 对应code - appVersion.setVersion(response.body().getVersion()); + appVersion.setVersion(response.getVersion()); //应用版本名 - appVersion.setVersionShort(response.body().getVersionShort()); + appVersion.setVersionShort(response.getVersionShort()); //更新日志 - appVersion.setChangelog(response.body().getChangelog()); + appVersion.setChangelog(response.getChangelog()); //更新地址 - appVersion.setUpdate_url(response.body().getUpdate_url()); + appVersion.setUpdate_url(response.getUpdate_url()); //安装地址 - appVersion.setInstall_url(response.body().getInstall_url()); + appVersion.setInstall_url(response.getInstall_url()); //APK大小 - appVersion.setAppSize(String.valueOf(response.body().getBinary().getFsize())); + appVersion.setAppSize(String.valueOf(response.getBinary().getFsize())); //添加数据前先判断是否已经有数据了 if (LitePal.find(AppVersion.class, 1) != null) { @@ -196,12 +191,14 @@ public void getAppInfoResult(Response response) { * @param response BiYingImgResponse */ @Override - public void getBiYingResult(Response response) { - if (response.body().getImages() != null) { + public void getBiYingResult(BiYingImgResponse response) { + if (response.getImages() != null) { //得到的图片地址是没有前缀的,所以加上前缀否则显示不出来 - String biyingUrl = "http://cn.bing.com" + response.body().getImages().get(0).getUrl(); + String biyingUrl = "http://cn.bing.com" + response.getImages().get(0).getUrl(); SPUtils.putString(Constant.EVERYDAY_TIP_IMG,biyingUrl,context); + //加载世界国家数据到本地数据库,已有则不加载 + initCountryData(); } else { ToastUtils.showShortToast(context, "未获取到必应的图片"); } diff --git a/app/src/main/java/com/llw/goodweather/ui/WallPaperActivity.java b/app/src/main/java/com/llw/goodweather/ui/WallPaperActivity.java index e5f2401..2239474 100644 --- a/app/src/main/java/com/llw/goodweather/ui/WallPaperActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/WallPaperActivity.java @@ -188,10 +188,10 @@ protected WallPaperContract.WallPaperPresenter createPresent() { * @param response BiYingImgResponse */ @Override - public void getBiYingResult(Response response) { - if (response.body().getImages() != null) { + public void getBiYingResult(BiYingImgResponse response) { + if (response.getImages() != null) { //得到的图片地址是没有前缀的,所以加上前缀否则显示不出来 - biyingUrl = "http://cn.bing.com" + response.body().getImages().get(0).getUrl(); + biyingUrl = "http://cn.bing.com" + response.getImages().get(0).getUrl(); Log.d("type-->", biyingUrl); } else { ToastUtils.showShortToast(context, "未获取到必应的图片"); @@ -205,10 +205,10 @@ public void getBiYingResult(Response response) { * @param response WallPaperResponse */ @Override - public void getWallPaperResult(Response response) { - if (response.body().getMsg().equals(Constant.SUCCESS)) { + public void getWallPaperResult(WallPaperResponse response) { + if (response.getMsg().equals(Constant.SUCCESS)) { - List data = response.body().getRes().getVertical(); + List data = response.getRes().getVertical(); //创建头部和底部的两个广告item的假数据 topBean = new WallPaperResponse.ResBean.VerticalBean(); @@ -240,11 +240,10 @@ public void getWallPaperResult(Response response) { wallPaper.setImgUrl(mList.get(i).getImg()); wallPaper.save(); } - dismissLoadingDialog(); } else { ToastUtils.showShortToast(context, "壁纸数据为空"); - dismissLoadingDialog(); } + dismissLoadingDialog(); } else { dismissLoadingDialog(); ToastUtils.showShortToast(context, "未获取到壁纸数据"); diff --git a/app/src/main/java/com/llw/goodweather/ui/WorldCityListActivity.java b/app/src/main/java/com/llw/goodweather/ui/WorldCityListActivity.java index 6153c88..7c25154 100644 --- a/app/src/main/java/com/llw/goodweather/ui/WorldCityListActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/WorldCityListActivity.java @@ -104,10 +104,10 @@ protected WorldCityContract.WorldCityPresenter createPresent() { * @param response */ @Override - public void getWorldCityResult(Response response) { + public void getWorldCityResult(WorldCityResponse response) { dismissLoadingDialog(); - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getTopCityList(); + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getTopCityList(); if (data != null && data.size() > 0) { mList.clear(); mList.addAll(data); @@ -117,7 +117,7 @@ public void getWorldCityResult(Response response) { } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/ui/WorldCityWeatherActivity.java b/app/src/main/java/com/llw/goodweather/ui/WorldCityWeatherActivity.java index 71a2c71..7ea9792 100644 --- a/app/src/main/java/com/llw/goodweather/ui/WorldCityWeatherActivity.java +++ b/app/src/main/java/com/llw/goodweather/ui/WorldCityWeatherActivity.java @@ -105,19 +105,19 @@ protected WorldCityWeatherContract.WorldCityWeatherPresenter createPresent() { * @param response */ @Override - public void getNowResult(Response response) { + public void getNowResult(NowResponse response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/GenJyuuGothic-ExtraLight.ttf"); - tvTemperature.setText(response.body().getNow().getTemp() + "°"); + tvTemperature.setText(response.getNow().getTemp() + "°"); tvTemperature.setTypeface(typeface);//使用字体 - int code = Integer.parseInt(response.body().getNow().getIcon());//获取天气状态码,根据状态码来显示图标 + int code = Integer.parseInt(response.getNow().getIcon());//获取天气状态码,根据状态码来显示图标 WeatherUtil.changeIcon(ivWeatherState, code);//调用工具类中写好的方法 - tvWeatherState.setText("当前:" + response.body().getNow().getText()); - tvWindState.setText(response.body().getNow().getWindDir() + " " + response.body().getNow().getWindScale() + "级"); + tvWeatherState.setText("当前:" + response.getNow().getText()); + tvWindState.setText(response.getNow().getWindDir() + " " + response.getNow().getWindScale() + "级"); } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -127,16 +127,16 @@ public void getNowResult(Response response) { * @param response */ @Override - public void getDailyResult(Response response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - if (response.body().getDaily() != null && response.body().getDaily().size() > 0) { - tvTemMax.setText(response.body().getDaily().get(0).getTempMax()); - tvTemMin.setText(" / " + response.body().getDaily().get(0).getTempMin()); + public void getDailyResult(DailyResponse response) { + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + if (response.getDaily() != null && response.getDaily().size() > 0) { + tvTemMax.setText(response.getDaily().get(0).getTempMax()); + tvTemMin.setText(" / " + response.getDaily().get(0).getTempMin()); } else { ToastUtils.showShortToast(context, "暂无天气预报数据"); } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } @@ -146,10 +146,10 @@ public void getDailyResult(Response response) { * @param response */ @Override - public void getHourlyResult(Response response) { + public void getHourlyResult(HourlyResponse response) { - if (response.body().getCode().equals(Constant.SUCCESS_CODE)) { - List data = response.body().getHourly(); + if (response.getCode().equals(Constant.SUCCESS_CODE)) { + List data = response.getHourly(); if (data != null && data.size() > 0) { mList.clear(); mList.addAll(data); @@ -160,7 +160,7 @@ public void getHourlyResult(Response response) { } } else { - ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode())); + ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.getCode())); } } diff --git a/app/src/main/java/com/llw/goodweather/utils/AppStartUpUtils.java b/app/src/main/java/com/llw/goodweather/utils/AppStartUpUtils.java index 7c8c329..d69e5d7 100644 --- a/app/src/main/java/com/llw/goodweather/utils/AppStartUpUtils.java +++ b/app/src/main/java/com/llw/goodweather/utils/AppStartUpUtils.java @@ -11,6 +11,7 @@ * @author llw */ public class AppStartUpUtils { + /** * 判断是否是首次启动 * @@ -35,7 +36,6 @@ public static boolean isFirstStartApp(Context context) { * @return */ public static boolean isTodayFirstStartApp(Context context) { - String saveDate = SPUtils.getString(Constant.START_UP_APP_TIME, "2020-08-27", context); String todayDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); //第一次打开 @@ -45,6 +45,5 @@ public static boolean isTodayFirstStartApp(Context context) { } else { return false; } - } } diff --git a/app/src/main/java/com/llw/goodweather/utils/SpeechUtil.java b/app/src/main/java/com/llw/goodweather/utils/SpeechUtil.java index f95887a..ef6e985 100644 --- a/app/src/main/java/com/llw/goodweather/utils/SpeechUtil.java +++ b/app/src/main/java/com/llw/goodweather/utils/SpeechUtil.java @@ -116,7 +116,6 @@ public static void init(Context context) { // 使用SpeechRecognizer对象,可根据回调消息自定义界面; mIat = SpeechRecognizer.createRecognizer(mContext, mInitListener); // 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源 - mIatDialog = new RecognizerDialog(mContext, mInitListener); mSharedPreferences = mContext.getSharedPreferences("ASR", Activity.MODE_PRIVATE); } @@ -390,7 +389,7 @@ public static void setDictationParam() { /** * 开始听写 */ - public static void startDictation(SpeechCallback speechCallback){ + public static void startDictation(Context context,SpeechCallback speechCallback){ mSpeechCallback = speechCallback; if( null == mIat ){ // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688 @@ -400,6 +399,7 @@ public static void startDictation(SpeechCallback speechCallback){ mIatResults.clear();//清除数据 setDictationParam(); // 设置参数 + mIatDialog = new RecognizerDialog(context, mInitListener); mIatDialog.setListener(mRecognizerDialogListener);//设置监听 mIatDialog.show();// 显示对话框 diff --git a/download/code.png b/download/code.png index d63d60f5e4fcd7b2695cb8646b59e1e2c141f499..b1625e247ad416c713516ca25e0cf3c71ef446d8 100644 GIT binary patch literal 50430 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 z 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 Uw}Iml@C+#iPgg&ebxsLQ00v*tH~;_u diff --git a/mvplibrary/build.gradle b/mvplibrary/build.gradle index d5f2b39..3e43b88 100644 --- a/mvplibrary/build.gradle +++ b/mvplibrary/build.gradle @@ -56,15 +56,24 @@ dependencies { annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0' //权限请求框架 api 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar' - api 'io.reactivex.rxjava2:rxandroid:2.0.2' - api "io.reactivex.rxjava2:rxjava:2.0.0" + //状态栏 api 'com.readystatesoftware.systembartint:systembartint:1.0.3' //支持okhttp api 'com.squareup.okhttp3:okhttp:3.8.1' - api 'com.squareup.retrofit2:retrofit:2.4.0' - api 'com.squareup.retrofit2:converter-gson:2.4.0' - api 'com.squareup.okhttp3:logging-interceptor:3.4.1' + + //retrofit2 + api 'com.squareup.retrofit2:retrofit:2.9.0' + //这里用api 是为了让其他模块也可以使用gson + api 'com.squareup.retrofit2:converter-gson:2.9.0' + //日志拦截器 + api 'com.squareup.okhttp3:logging-interceptor:3.10.0' + api 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' + //rxjava + api 'io.reactivex.rxjava2:rxandroid:2.1.1' + api 'io.reactivex.rxjava2:rxjava:2.2.12' + api 'androidx.preference:preference:1.0.0' + //阿里巴巴 FastJson api 'com.alibaba:fastjson:1.2.57' //下拉刷新框架 diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/net/NetCallBack.java b/mvplibrary/src/main/java/com/llw/mvplibrary/net/NetCallBack.java index 2c11024..349a9e1 100644 --- a/mvplibrary/src/main/java/com/llw/mvplibrary/net/NetCallBack.java +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/net/NetCallBack.java @@ -19,7 +19,7 @@ public abstract class NetCallBack implements Callback {//这里实现了re //访问成功回调 @Override public void onResponse(Call call, Response response) {//数据返回 - if (response != null && response.body() != null && response.isSuccessful()) { + if (response.body() != null && response.isSuccessful()) { onSuccess(call, response); diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/BaseResponse.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/BaseResponse.java new file mode 100644 index 0000000..995e486 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/BaseResponse.java @@ -0,0 +1,21 @@ +package com.llw.mvplibrary.newnet; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * 基础返回类 + * @author llw + */ +public class BaseResponse { + + //返回码 + @SerializedName("res_code") + @Expose + public Integer responseCode; + + //返回的错误信息 + @SerializedName("res_error") + @Expose + public String responseError; +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/INetworkRequiredInfo.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/INetworkRequiredInfo.java new file mode 100644 index 0000000..091085f --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/INetworkRequiredInfo.java @@ -0,0 +1,31 @@ +package com.llw.mvplibrary.newnet; + +import android.app.Application; + +/** + * App运行信息接口 + * @author llw + */ +public interface INetworkRequiredInfo { + + /** + * 获取App版本名 + */ + String getAppVersionName(); + + /** + * 获取App版本号 + */ + String getAppVersionCode(); + + /** + * 判断是否为Debug模式 + */ + boolean isDebug(); + + /** + * 获取全局上下文参数 + */ + Application getApplicationContext(); + +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkApi.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkApi.java new file mode 100644 index 0000000..15476e0 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkApi.java @@ -0,0 +1,222 @@ +package com.llw.mvplibrary.newnet; + +import com.llw.mvplibrary.newnet.environment.NetworkEnvironmentActivity; +import com.llw.mvplibrary.newnet.errorhandler.ExceptionHandle; +import com.llw.mvplibrary.newnet.errorhandler.HttpErrorHandler; +import com.llw.mvplibrary.newnet.interceptor.RequestInterceptor; +import com.llw.mvplibrary.newnet.interceptor.ResponseInterceptor; + +import java.util.HashMap; +import java.util.concurrent.TimeUnit; +import io.reactivex.Observable; +import io.reactivex.ObservableSource; +import io.reactivex.ObservableTransformer; +import io.reactivex.Observer; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; +import okhttp3.Cache; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import retrofit2.converter.gson.GsonConverterFactory; + +/** + * 网络API + * + * @author llw + */ +public class NetworkApi { + + //获取APP运行状态及版本信息,用于日志打印 + private static INetworkRequiredInfo iNetworkRequiredInfo; + //OkHttp客户端 + private static OkHttpClient okHttpClient; + //retrofitHashMap + private static HashMap retrofitHashMap = new HashMap<>(); + //API访问地址 + private static String mBaseUrl; + //是否为正式环境 + private static boolean isFormal = true; + + /** + * 初始化 + */ + public static void init(INetworkRequiredInfo networkRequiredInfo) { + iNetworkRequiredInfo = networkRequiredInfo; + //当初始化这个NetworkApi时,会判断当前App的网络环境 + isFormal = NetworkEnvironmentActivity.isFormalEnvironment(networkRequiredInfo.getApplicationContext()); + /*if (isFormal) { + //正式环境 + mBaseUrl = "http://api.tianapi.com"; + } else { + //测试环境 + mBaseUrl = "https://cn.bing.com"; + }*/ + } + + /** + * 创建serviceClass的实例 + */ + public static T createService(Class serviceClass,int type) { + getBaseUrl(type); + return getRetrofit(serviceClass).create(serviceClass); + } + + /** + * 修改访问地址 + * @param type + */ + private static void getBaseUrl(int type) { + switch (type) { + //和风天气 + case 0: + //S6版本接口地址 + mBaseUrl = "https://free-api.heweather.net"; + break; + //必应每日一图 + case 1: + mBaseUrl = "https://cn.bing.com"; + break; + //搜索城市 + case 2: + mBaseUrl = "https://search.heweather.net"; + break; + //和风天气 新增 + case 3: + //V7版本接口地址 + mBaseUrl = "https://devapi.qweather.net"; + break; + //搜索城市 新增 + case 4: + //V7版本下的搜索城市地址 + mBaseUrl = "https://geoapi.qweather.net"; + break; + //APP更新 分发平台更新接口 + case 5: + //Fr.im更新 + mBaseUrl = "http://api.bq04.com"; + break; + //随机手机壁纸 + case 6: + //网络手机壁纸返回地址 + mBaseUrl = "http://service.picasso.adesk.com"; + break; + default: + break; + } + } + + /** + * 配置OkHttp + * + * @return OkHttpClient + */ + private static OkHttpClient getOkHttpClient() { + //不为空则说明已经配置过了,直接返回即可。 + if (okHttpClient == null) { + //OkHttp构建器 + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + //设置缓存大小 + int cacheSize = 100 * 1024 * 1024; + //设置OkHttp网络缓存 + builder.cache(new Cache(iNetworkRequiredInfo.getApplicationContext().getCacheDir(), cacheSize)); + //设置网络请求超时时长,这里设置为10s + builder.connectTimeout(10, TimeUnit.SECONDS); + builder.readTimeout(20, TimeUnit.SECONDS).build(); + //添加请求拦截器,如果接口有请求头的话,可以放在这个拦截器里面 + builder.addInterceptor(new RequestInterceptor(iNetworkRequiredInfo)); + //添加返回拦截器,可用于查看接口的请求耗时,对于网络优化有帮助 + builder.addInterceptor(new ResponseInterceptor()); + //当程序在debug过程中则打印数据日志,方便调试用。 + if (iNetworkRequiredInfo != null && iNetworkRequiredInfo.isDebug()) { + //iNetworkRequiredInfo不为空且处于debug状态下则初始化日志拦截器 + HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); + //设置要打印日志的内容等级,BODY为主要内容,还有BASIC、HEADERS、NONE。 + httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + //将拦截器添加到OkHttp构建器中 + builder.addInterceptor(httpLoggingInterceptor); + } + //OkHttp配置完成 + okHttpClient = builder.build(); + } + return okHttpClient; + } + + /** + * 配置Retrofit + * + * @param serviceClass 服务类 + * @return Retrofit + */ + private static Retrofit getRetrofit(Class serviceClass) { + if (retrofitHashMap.get(mBaseUrl + serviceClass.getName()) != null) { + //刚才上面定义的Map中键是String,值是Retrofit,当键不为空时,必然有值,有值则直接返回。 + return retrofitHashMap.get(mBaseUrl + serviceClass.getName()); + } + //初始化Retrofit Retrofit是对OKHttp的封装,通常是对网络请求做处理,也可以处理返回数据。 + //Retrofit构建器 + Retrofit.Builder builder = new Retrofit.Builder(); + //设置访问地址 + builder.baseUrl(mBaseUrl); + //设置OkHttp客户端,传入上面写好的方法即可获得配置后的OkHttp客户端。 + builder.client(getOkHttpClient()); + //设置数据解析器 会自动把请求返回的结果(json字符串)通过Gson转化工厂自动转化成与其结构相符的实体Bean + builder.addConverterFactory(GsonConverterFactory.create()); + //设置请求回调,使用RxJava 对网络返回进行处理 + builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create()); + //retrofit配置完成 + Retrofit retrofit = builder.build(); + //放入Map中 + retrofitHashMap.put(mBaseUrl + serviceClass.getName(), retrofit); + //最后返回即可 + return retrofit; + } + + /** + * 配置RxJava 完成线程的切换,如果是Kotlin中完全可以直接使用协程 + * + * @param observer 这个observer要注意不要使用lifecycle中的Observer + * @param 泛型 + * @return Observable + */ + public static ObservableTransformer applySchedulers(final Observer observer) { + return new ObservableTransformer() { + @Override + public ObservableSource apply(Observable upstream) { + Observable observable = upstream + .subscribeOn(Schedulers.io())//线程订阅 + .observeOn(AndroidSchedulers.mainThread())//观察Android主线程 + .map(NetworkApi.getAppErrorHandler())//判断有没有500的错误,有则进入getAppErrorHandler + .onErrorResumeNext(new HttpErrorHandler());//判断有没有400的错误 + //这里还少了对异常 + //订阅观察者 + observable.subscribe(observer); + return observable; + } + }; + } + + /** + * 错误码处理 + */ + protected static Function getAppErrorHandler() { + return new Function() { + @Override + public T apply(T response) throws Exception { + //当response返回出现500之类的错误时 + if (response instanceof BaseResponse && ((BaseResponse) response).responseCode >= 500) { + //通过这个异常处理,得到用户可以知道的原因 + ExceptionHandle.ServerException exception = new ExceptionHandle.ServerException(); + exception.code = ((BaseResponse) response).responseCode; + exception.message = ((BaseResponse) response).responseError != null ? ((BaseResponse) response).responseError : ""; + throw exception; + } + return response; + } + }; + } + + +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkUtils.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkUtils.java new file mode 100644 index 0000000..666c0d1 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/NetworkUtils.java @@ -0,0 +1,120 @@ +package com.llw.mvplibrary.newnet; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.provider.Settings; + +/** + * 网络检测工具类 + */ +public class NetworkUtils { + + /** 网络不可用 */ + public static final int NO_NET_WORK = 0; + /** 是wifi连接 */ + public static final int WIFI = 1; + /** 不是wifi连接 */ + public static final int NO_WIFI = 2; + + + private NetworkUtils(){ + /* cannot be instantiated */ + throw new UnsupportedOperationException("cannot be instantiated"); + } + + /** + * 判断是否打开网络 + * @param context + * @return + */ + public static boolean isNetWorkAvailable(Context context){ + boolean isAvailable = false ; + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = cm.getActiveNetworkInfo(); + if(networkInfo!=null && networkInfo.isAvailable()){ + isAvailable = true; + } + return isAvailable; + } + + /** + * 获取网络类型 + * @param context + * @return + */ + public static int getNetWorkType(Context context) { + if (!isNetWorkAvailable(context)) { + return NetworkUtils.NO_NET_WORK; + } + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + // cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + if (cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting()) { + return NetworkUtils.WIFI; + } else { + return NetworkUtils.NO_WIFI; + } + } + + /** + * 判断当前网络是否为wifi + * @param context + * @return 如果为wifi返回true;否则返回false + */ + @SuppressWarnings("static-access") + public static boolean isWiFiConnected(Context context){ + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = manager.getActiveNetworkInfo(); + return networkInfo.getType() == manager.TYPE_WIFI ? true : false; + } + + /** + * 判断MOBILE网络是否可用 + * @param context + * @return + * @throws Exception + */ + public static boolean isMobileDataEnable(Context context){ + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + boolean isMobileDataEnable = false; + isMobileDataEnable = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnectedOrConnecting(); + return isMobileDataEnable; + } + + /** + * 判断wifi 是否可用 + * @param context + * @return + * @throws Exception + */ + public static boolean isWifiDataEnable(Context context){ + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + boolean isWifiDataEnable = false; + isWifiDataEnable = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting(); + return isWifiDataEnable; + } + + /** + * 跳转到网络设置页面 + * @param activity + */ + public static void GoSetting(Activity activity){ + Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); + activity.startActivity(intent); + } + + /** + * 打开网络设置界面 + */ + public static void openSetting(Activity activity) { + Intent intent = new Intent("/"); + ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.WirelessSettings"); + intent.setComponent(cn); + intent.setAction("android.intent.action.VIEW"); + activity.startActivityForResult(intent, 0); + } + +} \ No newline at end of file diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/environment/NetworkEnvironmentActivity.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/environment/NetworkEnvironmentActivity.java new file mode 100644 index 0000000..00a0581 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/environment/NetworkEnvironmentActivity.java @@ -0,0 +1,97 @@ +package com.llw.mvplibrary.newnet.environment; + +import android.app.Application; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceManager; + +import com.llw.mvplibrary.R; + + +/** + * 设置网络环境Activity + * + * @author llw + */ +public class NetworkEnvironmentActivity extends AppCompatActivity { + + //网络环境 + public static final String NETWORK_ENVIRONMENT = "network_environment"; + //当前网络环境 + private static String mCurrentNetworkEnvironment = ""; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_network_environment); + + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.content, new MyPreferenceFragment()) + .commit(); + //获取默认缓存 + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + //如果没有值就默认为 “1” 在这里 1 表示正式环境 + mCurrentNetworkEnvironment = preferences.getString(NETWORK_ENVIRONMENT,"1"); + } + + /** + * 内部缓存变化监听类 + */ + public static class MyPreferenceFragment extends PreferenceFragmentCompat + implements Preference.OnPreferenceChangeListener { + + //创建缓存 + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + //这个相当于Activity的setContentView,从资源文件中添Preferences ,选择的值将会自动保存到SharePreferences + addPreferencesFromResource(R.xml.environment_preference); + //设置缓存变化监听 , 通过键来设置监听 + findPreference(NETWORK_ENVIRONMENT).setOnPreferenceChangeListener(this); + } + + //缓存变化 + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (!mCurrentNetworkEnvironment.equalsIgnoreCase(String.valueOf(newValue))) { + //当前值与缓存中不一致时,说明切换了网络,这时提醒一下 + Toast.makeText(getContext(), R.string.network_change_tip, Toast.LENGTH_SHORT).show(); + } + return true; + } + } + + /** + * 页面返回 + */ + @Override + public void onBackPressed() { + //获取缓存对象 + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + //通过键获取缓存则,没有则使用默认值 + String value = preferences.getString(NETWORK_ENVIRONMENT, "1"); + if (!mCurrentNetworkEnvironment.equalsIgnoreCase(value)) { + //不一致.说明有修改,从操作系统中结束掉当前程序的进程 + android.os.Process.killProcess(android.os.Process.myPid()); + } else { + //一致 没有修改则关闭当前页面 + finish(); + } + } + + /** + * 是否为正式环境 + */ + public static boolean isFormalEnvironment(Application application) { + //获取当前应用的缓存 + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(application); + String networkEnvironment = preferences.getString(NETWORK_ENVIRONMENT, "1"); + return "1".equalsIgnoreCase(networkEnvironment); + } +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/ExceptionHandle.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/ExceptionHandle.java new file mode 100644 index 0000000..2066091 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/ExceptionHandle.java @@ -0,0 +1,145 @@ +package com.llw.mvplibrary.newnet.errorhandler; + +import android.net.ParseException; + +import com.google.gson.JsonParseException; + +import org.apache.http.conn.ConnectTimeoutException; +import org.json.JSONException; + +import java.net.ConnectException; + +import retrofit2.HttpException; + +/** + * 异常处理 + * @author llw + */ +public class ExceptionHandle { + //未授权 + private static final int UNAUTHORIZED = 401; + //禁止的 + private static final int FORBIDDEN = 403; + //未找到 + private static final int NOT_FOUND = 404; + //请求超时 + private static final int REQUEST_TIMEOUT = 408; + //内部服务器错误 + private static final int INTERNAL_SERVER_ERROR = 500; + //错误网关 + private static final int BAD_GATEWAY = 502; + //暂停服务 + private static final int SERVICE_UNAVAILABLE = 503; + //网关超时 + private static final int GATEWAY_TIMEOUT = 504; + + /** + * 处理异常 + * @param throwable + * @return + */ + public static ResponseThrowable handleException(Throwable throwable) { + //返回时抛出异常 + ResponseThrowable responseThrowable; + if (throwable instanceof HttpException) { + HttpException httpException = (HttpException) throwable; + responseThrowable = new ResponseThrowable(throwable, ERROR.HTTP_ERROR); + switch (httpException.code()) { + case UNAUTHORIZED: + case FORBIDDEN: + case NOT_FOUND: + case REQUEST_TIMEOUT: + case GATEWAY_TIMEOUT: + case INTERNAL_SERVER_ERROR: + case BAD_GATEWAY: + case SERVICE_UNAVAILABLE: + default: + responseThrowable.message = "网络错误"; + break; + } + return responseThrowable; + } else if (throwable instanceof ServerException) { + //服务器异常 + ServerException resultException = (ServerException) throwable; + responseThrowable = new ResponseThrowable(resultException, resultException.code); + responseThrowable.message = resultException.message; + return responseThrowable; + } else if (throwable instanceof JsonParseException + || throwable instanceof JSONException + || throwable instanceof ParseException) { + responseThrowable = new ResponseThrowable(throwable, ERROR.PARSE_ERROR); + responseThrowable.message = "解析错误"; + return responseThrowable; + } else if (throwable instanceof ConnectException) { + responseThrowable = new ResponseThrowable(throwable, ERROR.NETWORK_ERROR); + responseThrowable.message = "连接失败"; + return responseThrowable; + } else if (throwable instanceof javax.net.ssl.SSLHandshakeException) { + responseThrowable = new ResponseThrowable(throwable, ERROR.SSL_ERROR); + responseThrowable.message = "证书验证失败"; + return responseThrowable; + } else if (throwable instanceof ConnectTimeoutException){ + responseThrowable = new ResponseThrowable(throwable, ERROR.TIMEOUT_ERROR); + responseThrowable.message = "连接超时"; + return responseThrowable; + } else if (throwable instanceof java.net.SocketTimeoutException) { + responseThrowable = new ResponseThrowable(throwable, ERROR.TIMEOUT_ERROR); + responseThrowable.message = "连接超时"; + return responseThrowable; + } + else { + responseThrowable = new ResponseThrowable(throwable, ERROR.UNKNOWN); + responseThrowable.message = "未知错误"; + return responseThrowable; + } + } + + + /** + * 约定异常 + */ + public class ERROR { + /** + * 未知错误 + */ + public static final int UNKNOWN = 1000; + /** + * 解析错误 + */ + public static final int PARSE_ERROR = 1001; + /** + * 网络错误 + */ + public static final int NETWORK_ERROR = 1002; + /** + * 协议出错 + */ + public static final int HTTP_ERROR = 1003; + + /** + * 证书出错 + */ + public static final int SSL_ERROR = 1005; + + /** + * 连接超时 + */ + public static final int TIMEOUT_ERROR = 1006; + } + + public static class ResponseThrowable extends Exception { + public int code; + public String message; + + public ResponseThrowable(Throwable throwable, int code) { + super(throwable); + this.code = code; + } + } + + public static class ServerException extends RuntimeException { + public int code; + public String message; + } +} + diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/HttpErrorHandler.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/HttpErrorHandler.java new file mode 100644 index 0000000..1065bac --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/errorhandler/HttpErrorHandler.java @@ -0,0 +1,22 @@ +package com.llw.mvplibrary.newnet.errorhandler; + +import io.reactivex.Observable; +import io.reactivex.functions.Function; + +/** + * 网络错误处理 + * @author llw + */ +public class HttpErrorHandler implements Function> { + + /** + * 处理以下两类网络错误: + * 1、http请求相关的错误,例如:404,403,socket timeout等等; + * 2、应用数据的错误会抛RuntimeException,最后也会走到这个函数来统一处理; + */ + @Override + public Observable apply(Throwable throwable) throws Exception { + //通过这个异常处理,得到用户可以知道的原因 + return Observable.error(ExceptionHandle.handleException(throwable)); + } +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/RequestInterceptor.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/RequestInterceptor.java new file mode 100644 index 0000000..c6891a2 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/RequestInterceptor.java @@ -0,0 +1,45 @@ +package com.llw.mvplibrary.newnet.interceptor; + +import com.llw.mvplibrary.newnet.INetworkRequiredInfo; +import com.llw.mvplibrary.newnet.utils.DateUtil; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +/** + * 请求拦截器 + * @author llw + */ +public class RequestInterceptor implements Interceptor { + /** + * 网络请求信息 + */ + private INetworkRequiredInfo iNetworkRequiredInfo; + + public RequestInterceptor(INetworkRequiredInfo iNetworkRequiredInfo){ + this.iNetworkRequiredInfo = iNetworkRequiredInfo; + } + + /** + * 拦截 + */ + @Override + public Response intercept(Chain chain) throws IOException { + String nowDateTime = DateUtil.getNowDateTime(); + //构建器 + Request.Builder builder = chain.request().newBuilder(); + //添加使用环境 + builder.addHeader("os","android"); + //添加版本号 + builder.addHeader("appVersionCode",this.iNetworkRequiredInfo.getAppVersionCode()); + //添加版本名 + builder.addHeader("appVersionName",this.iNetworkRequiredInfo.getAppVersionName()); + //添加日期时间 + builder.addHeader("datetime",nowDateTime); + //返回 + return chain.proceed(builder.build()); + } +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/ResponseInterceptor.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/ResponseInterceptor.java new file mode 100644 index 0000000..e307a8b --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/interceptor/ResponseInterceptor.java @@ -0,0 +1,28 @@ +package com.llw.mvplibrary.newnet.interceptor; + +import com.llw.mvplibrary.newnet.utils.KLog; + +import java.io.IOException; +import okhttp3.Interceptor; +import okhttp3.Response; + +/** + * 返回拦截器(响应拦截器) + * + * @author llw + */ +public class ResponseInterceptor implements Interceptor { + + private static final String TAG = "ResponseInterceptor"; + + /** + * 拦截 + */ + @Override + public Response intercept(Chain chain) throws IOException { + long requestTime = System.currentTimeMillis(); + Response response = chain.proceed(chain.request()); + KLog.i(TAG, "requestSpendTime=" + (System.currentTimeMillis() - requestTime) + "ms"); + return response; + } +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/BaseObserver.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/BaseObserver.java new file mode 100644 index 0000000..08b9f7b --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/BaseObserver.java @@ -0,0 +1,42 @@ +package com.llw.mvplibrary.newnet.observer; + +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +/** + * 自定义Observer + * + * @author llw + */ +public abstract class BaseObserver implements Observer { + + //开始 + @Override + public void onSubscribe(Disposable d) { + + } + + //继续 + @Override + public void onNext(T t) { + onSuccess(t); + } + + //异常 + @Override + public void onError(Throwable e) { + onFailure(e); + } + + //完成 + @Override + public void onComplete() { + + } + + //成功 + public abstract void onSuccess(T t); + + //失败 + public abstract void onFailure(Throwable e); +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/NetObserver.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/NetObserver.java new file mode 100644 index 0000000..7ab1144 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/observer/NetObserver.java @@ -0,0 +1,6 @@ +package com.llw.mvplibrary.newnet.observer; + +public abstract class NetObserver extends BaseObserver { + + +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/DateUtil.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/DateUtil.java new file mode 100644 index 0000000..0ff5e4a --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/DateUtil.java @@ -0,0 +1,171 @@ +package com.llw.mvplibrary.newnet.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; + +public class DateUtil { + //获取当前完整的日期和时间 + public static String getNowDateTime() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + return sdf.format(new Date()); + } + + //获取当前的日期和时间 + public static String getDateTime() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return sdf.format(new Date()); + } + + //获取当前日期 + public static String getNowDate() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return sdf.format(new Date()); + } + + //前一天 + public static String getYesterday(Date date) { + String tomorrow = ""; + Calendar calendar = new GregorianCalendar(); + calendar.setTime(date); + calendar.add(Calendar.DATE, -1); + date = calendar.getTime(); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + tomorrow = formatter.format(date); + return tomorrow; + } + + //后一天 + public static String getTomorrow(Date date) { + String tomorrow = ""; + Calendar calendar = new GregorianCalendar(); + calendar.setTime(date); + calendar.add(Calendar.DATE, +1); + date = calendar.getTime(); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + tomorrow = formatter.format(date); + return tomorrow; + } + + //获取当前时间 + public static String getNowTime() { + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); + return sdf.format(new Date()); + } + + //获取当前日期(精确到毫秒) + public static String getNowTimeDetail() { + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); + return sdf.format(new Date()); + } + + //获取今天是星期几 + public static String getWeekOfDate(Date date) { + String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}; + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + int w = cal.get(Calendar.DAY_OF_WEEK) - 1; + if (w < 0) { + } + w = 0; + return weekDays[w]; + } + + //计算星期几 + private static int getDayOfWeek(String dateTime) { + + Calendar cal = Calendar.getInstance(); + if (dateTime.equals("")) { + cal.setTime(new Date(System.currentTimeMillis())); + } else { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); + Date date; + try { + date = sdf.parse(dateTime); + } catch (ParseException e) { + date = null; + e.printStackTrace(); + } + if (date != null) { + cal.setTime(new Date(date.getTime())); + } + } + return cal.get(Calendar.DAY_OF_WEEK); + } + + //根据年月日计算是星期几并与当前日期判断 非昨天、今天、明天 则以星期显示 + public static String Week(String dateTime) { + String week = ""; + String yesterday = ""; + String today = ""; + String tomorrow = ""; + yesterday = getYesterday(new Date()); + today = getNowDate(); + tomorrow = getTomorrow(new Date()); + + if (dateTime.equals(yesterday)) { + week = "昨天"; + } else if (dateTime.equals(today)) { + week = "今天"; + } else if (dateTime.equals(tomorrow)) { + week = "明天"; + } else { + switch (getDayOfWeek(dateTime)) { + case 1: + week = "星期日"; + break; + case 2: + week = "星期一"; + break; + case 3: + week = "星期二"; + break; + case 4: + week = "星期三"; + break; + case 5: + week = "星期四"; + break; + case 6: + week = "星期五"; + break; + case 7: + week = "星期六"; + break; + } + + } + + + return week; + } + + //将时间戳转化为对应的时间(10位或者13位都可以) + public static String formatTime(long time) { + String times = null; + if (String.valueOf(time).length() > 10) {// 10位的秒级别的时间戳 + times = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time * 1000)); + } else {// 13位的秒级别的时间戳 + times = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time); + } + return times; + } + + //将时间字符串转为时间戳字符串 + public static String getStringTimestamp(String time) { + String timestamp = null; + + try { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Long longTime = sdf.parse(time).getTime() / 1000; + timestamp = Long.toString(longTime); + + } catch (ParseException e) { + e.printStackTrace(); + } + return timestamp; + } +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/KLog.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/KLog.java new file mode 100644 index 0000000..bcccbae --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/KLog.java @@ -0,0 +1,205 @@ +package com.llw.mvplibrary.newnet.utils; + +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * 自定义日志类 + */ +public final class KLog { + + private static boolean IS_SHOW_LOG = true; + + private static final String DEFAULT_MESSAGE = "execute"; + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private static final int JSON_INDENT = 4; + + private static final int V = 0x1; + private static final int D = 0x2; + private static final int I = 0x3; + private static final int W = 0x4; + private static final int E = 0x5; + private static final int A = 0x6; + private static final int JSON = 0x7; + + public static void init(boolean isShowLog) { + IS_SHOW_LOG = isShowLog; + } + + public static void v() { + printLog(V, null, DEFAULT_MESSAGE); + } + + public static void v(String msg) { + printLog(V, null, msg); + } + + public static void v(String tag, String msg) { + printLog(V, tag, msg); + } + + public static void d() { + printLog(D, null, DEFAULT_MESSAGE); + } + + public static void d(String msg) { + printLog(D, null, msg); + } + + public static void d(String tag, String msg) { + printLog(D, tag, msg); + } + + public static void i() { + printLog(I, null, DEFAULT_MESSAGE); + } + + public static void i(String msg) { + printLog(I, null, msg); + } + + public static void i(String tag, String msg) { + printLog(I, tag, msg); + } + + public static void w() { + printLog(W, null, DEFAULT_MESSAGE); + } + + public static void w(String msg) { + printLog(W, null, msg); + } + + public static void w(String tag, String msg) { + printLog(W, tag, msg); + } + + public static void e() { + printLog(E, null, DEFAULT_MESSAGE); + } + + public static void e(String msg) { + printLog(E, null, msg); + } + + public static void e(String tag, String msg) { + printLog(E, tag, msg); + } + + public static void a() { + printLog(A, null, DEFAULT_MESSAGE); + } + + public static void a(String msg) { + printLog(A, null, msg); + } + + public static void a(String tag, String msg) { + printLog(A, tag, msg); + } + + + public static void json(String jsonFormat) { + printLog(JSON, null, jsonFormat); + } + + public static void json(String tag, String jsonFormat) { + printLog(JSON, tag, jsonFormat); + } + + + private static void printLog(int type, String tagStr, String msg) { + + if (!IS_SHOW_LOG) { + return; + } + + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + + int index = 4; + String className = stackTrace[index].getFileName(); + String methodName = stackTrace[index].getMethodName(); + int lineNumber = stackTrace[index].getLineNumber(); + + String tag = (tagStr == null ? className : tagStr); + methodName = methodName.substring(0, 1).toUpperCase() + methodName.substring(1); + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("[ (").append(className).append(":").append(lineNumber).append(")#").append(methodName).append(" ] "); + + if (msg != null && type != JSON) { + stringBuilder.append(msg); + } + + String logStr = stringBuilder.toString(); + + switch (type) { + case V: + Log.v(tag, logStr); + break; + case D: + Log.d(tag, logStr); + break; + case I: + Log.i(tag, logStr); + break; + case W: + Log.w(tag, logStr); + break; + case E: + Log.e(tag, logStr); + break; + case A: + Log.wtf(tag, logStr); + break; + case JSON: { + + if (TextUtils.isEmpty(msg)) { + Log.d(tag, "Empty or Null json content"); + return; + } + + String message = null; + + try { + if (msg.startsWith("{")) { + JSONObject jsonObject = new JSONObject(msg); + message = jsonObject.toString(JSON_INDENT); + } else if (msg.startsWith("[")) { + JSONArray jsonArray = new JSONArray(msg); + message = jsonArray.toString(JSON_INDENT); + } + } catch (JSONException e) { + e(tag, e.getCause().getMessage() + "\n" + msg); + return; + } + + printLine(tag, true); + message = logStr + LINE_SEPARATOR + message; + String[] lines = message.split(LINE_SEPARATOR); + StringBuilder jsonContent = new StringBuilder(); + for (String line : lines) { + jsonContent.append("║ ").append(line).append(LINE_SEPARATOR); + } + Log.d(tag, jsonContent.toString()); + printLine(tag, false); + } + break; + default: + break; + } + + } + + private static void printLine(String tag, boolean isTop) { + if (isTop) { + Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════"); + } else { + Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════"); + } + } +} diff --git a/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/StatusBarUtil.java b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/StatusBarUtil.java new file mode 100644 index 0000000..523d357 --- /dev/null +++ b/mvplibrary/src/main/java/com/llw/mvplibrary/newnet/utils/StatusBarUtil.java @@ -0,0 +1,189 @@ +package com.llw.mvplibrary.newnet.utils; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.graphics.Color; +import android.os.Build; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import androidx.appcompat.app.AppCompatActivity; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * 状态栏工具类 + */ +public class StatusBarUtil { + + /** + * 修改状态栏为全透明 + * + * @param activity + */ + @TargetApi(19) + public static void transparencyBar(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(Color.TRANSPARENT); + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + Window window = activity.getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, + WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + } + + + /** + * 状态栏亮色模式,设置状态栏黑色文字、图标, + * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android + * + * @param activity + * @return 1:MIUUI 2:Flyme 3:android6.0 + */ + public static int StatusBarLightMode(Activity activity) { + int result = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (MIUISetStatusBarLightMode(activity, true)) { + result = 1; + } else if (FlymeSetStatusBarLightMode(activity.getWindow(), true)) { + result = 2; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + result = 3; + } + } + return result; + } + + /** + * 修改状态栏颜色,支持4.4以上版本 + * + * @param activity + * @param colorId + */ + public static void setStatusBarColor(AppCompatActivity activity, int colorId) { + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + window.setStatusBarColor(activity.getResources().getColor(colorId)); + } + } + + /** + * 已知系统类型时,设置状态栏黑色文字、图标。 + * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android + * + * @param activity + * @param type 1:MIUUI 2:Flyme 3:android6.0 + */ + public static void StatusBarLightMode(Activity activity, int type) { + if (type == 1) { + MIUISetStatusBarLightMode(activity, true); + } else if (type == 2) { + FlymeSetStatusBarLightMode(activity.getWindow(), true); + } else if (type == 3) { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + + } + + /** + * 状态栏暗色模式,清除MIUI、flyme或6.0以上版本状态栏黑色文字、图标 + */ + public static void StatusBarDarkMode(Activity activity, int type) { + if (type == 1) { + MIUISetStatusBarLightMode(activity, false); + } else if (type == 2) { + FlymeSetStatusBarLightMode(activity.getWindow(), false); + } else if (type == 3) { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); + } + + } + + + /** + * 设置状态栏图标为深色和魅族特定的文字风格 + * 可以用来判断是否为Flyme用户 + * + * @param window 需要设置的窗口 + * @param dark 是否把状态栏文字及图标颜色设置为深色 + * @return boolean 成功执行返回true + */ + public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) { + boolean result = false; + if (window != null) { + try { + WindowManager.LayoutParams lp = window.getAttributes(); + Field darkFlag = WindowManager.LayoutParams.class + .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); + Field meizuFlags = WindowManager.LayoutParams.class + .getDeclaredField("meizuFlags"); + darkFlag.setAccessible(true); + meizuFlags.setAccessible(true); + int bit = darkFlag.getInt(null); + int value = meizuFlags.getInt(lp); + if (dark) { + value |= bit; + } else { + value &= ~bit; + } + meizuFlags.setInt(lp, value); + window.setAttributes(lp); + result = true; + } catch (Exception e) { + + } + } + return result; + } + + /** + * 需要MIUIV6以上 + * + * @param activity + * @param dark 是否把状态栏文字及图标颜色设置为深色 + * @return boolean 成功执行返回true + */ + public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) { + boolean result = false; + Window window = activity.getWindow(); + if (window != null) { + Class clazz = window.getClass(); + try { + int darkModeFlag = 0; + Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams"); + Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE"); + darkModeFlag = field.getInt(layoutParams); + Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class); + if (dark) { + extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体 + } else { + extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体 + } + result = true; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上 + if (dark) { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } else { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); + } + } + } catch (Exception e) { + + } + } + return result; + } + +} diff --git a/mvplibrary/src/main/res/drawable/ic_network_settings.xml b/mvplibrary/src/main/res/drawable/ic_network_settings.xml new file mode 100644 index 0000000..31d2181 --- /dev/null +++ b/mvplibrary/src/main/res/drawable/ic_network_settings.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/mvplibrary/src/main/res/layout/activity_network_environment.xml b/mvplibrary/src/main/res/layout/activity_network_environment.xml new file mode 100644 index 0000000..7dc8ef9 --- /dev/null +++ b/mvplibrary/src/main/res/layout/activity_network_environment.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/mvplibrary/src/main/res/values/network_array.xml b/mvplibrary/src/main/res/values/network_array.xml new file mode 100644 index 0000000..a2ea2ec --- /dev/null +++ b/mvplibrary/src/main/res/values/network_array.xml @@ -0,0 +1,12 @@ + + + + 正式 + 测试 + + + + 1 + 2 + + \ No newline at end of file diff --git a/mvplibrary/src/main/res/values/strings.xml b/mvplibrary/src/main/res/values/strings.xml index 7d0377a..2b86f80 100644 --- a/mvplibrary/src/main/res/values/strings.xml +++ b/mvplibrary/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ MVP Library + 网络环境设置 + 您已经更改了网络环境,在您退出当前页面的时候APP将会重启切换环境! diff --git a/mvplibrary/src/main/res/xml/environment_preference.xml b/mvplibrary/src/main/res/xml/environment_preference.xml new file mode 100644 index 0000000..3ed6166 --- /dev/null +++ b/mvplibrary/src/main/res/xml/environment_preference.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/mvplibrary/src/main/res/xml/network_security_config.xml b/mvplibrary/src/main/res/xml/network_security_config.xml new file mode 100644 index 0000000..dca93c0 --- /dev/null +++ b/mvplibrary/src/main/res/xml/network_security_config.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file