Series articles
Tip: go to the Android learning column and watch more!
Click me directly – > Android learning column
In this project, pay attention to the modification of the package name prefix and change it to your own. My package name is:
com.example.coolweather, otherwise an error will be reported.
preface
This sub topic: automatic weather update in the background
Project practice inherits the previous articles.
The function of automatically updating the weather in the background can ensure that users see the latest weather information every time they open the software.
Realization effect
Project structure
There are several packages under the com.coolweather.android package
- The db package is used to store the code related to the database model
- The gson package is used to store the code related to the gson model
- The service package is used to store service related code
- The util package is used to store tool related code.
1. Create a scheduled task that runs in the background for a long time
1.1 create AutoUpdateService
First, create a New service under the service package. Right click com.example.coolweather.service → New → service → service to create an AutoUpdateService
In the onStartCommand() method, we first call the updateWeather() method to update the weather, then call the updateBingPic() method to update the background image. Here, we can store the updated data directly into the SharedPreferences file, because the data will be read from the SharedPreferences cache first when opening WeatherActivity.
In order to ensure that the software will not consume too much traffic, the time interval is set to 8 hours. After 8 hours, the onStartCommand() method of AutoUpdateReceiver will be re executed, so as to realize the function of background regular update.
Code in AutoUpdateService:
package com.example.coolweather.service; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.content.SharedPreferences; import android.os.IBinder; import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.Log; import com.example.coolweather.gson.Weather; import com.example.coolweather.util.HttpUtil; import com.example.coolweather.util.Utility; import java.io.IOException; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; public class AutoUpdateService extends Service { public AutoUpdateService(){} @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. Log.i("AutoUpdateService.java", "onBind method..................."); throw new UnsupportedOperationException("Not yet implemented"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("AutoUpdateService.java", "onStartCommand method..................."); updateWeather(); updateBingPic(); AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE); int anHour = 8 * 60 * 1000; // This is the number of milliseconds in 8 hours long triggerAtTime = SystemClock.elapsedRealtime() + anHour; Intent i = new Intent(this, AutoUpdateService.class); PendingIntent pi = PendingIntent.getService(this, 0, i, 0); manager.cancel(pi); manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi); return super.onStartCommand(intent, flags, startId); } /** * Update weather information */ private void updateWeather() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); String weatherString = prefs.getString("weather", null); if(weatherString != null) { // Directly parse weather data when there is cache Weather weather = Utility.handleWeatherResponse(weatherString); String weatherId = weather.basic.weatherId; String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=a38f3ed5101a49f6af55d5c163bf542d"; HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { String responseText = response.body().string(); Weather weather = Utility.handleWeatherResponse(responseText); if(weather != null && "ok".equals(weather.status)) { SharedPreferences.Editor editor = PreferenceManager. getDefaultSharedPreferences(AutoUpdateService.this).edit(); editor.putString("weather", responseText); editor.apply(); } } }); } } /** * Update Bing daily chart */ private void updateBingPic() { String requestBingPic = "http://guolin.tech/api/bing_pic"; HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { String bingPic = response.body().string(); SharedPreferences.Editor editor = PreferenceManager. getDefaultSharedPreferences(AutoUpdateService.this).edit(); editor.putString("bing_pic", bingPic); editor.apply(); } }); } }
1.2 activate AutoUpdateService service
Activate the AutoUpdateService service somewhere in the code. Modify the code in WeatherActivity:
Add the code to start AutoUpdateService at the end of showWeatherInfo() method, so that once a city is selected and the weather is successfully updated, AutoUpdateService will always run in the background and ensure that the weather is updated every 8 hours.
package com.example.coolweather; import androidx.appcompat.app.AppCompatActivity; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.example.coolweather.gson.Forecast; import com.example.coolweather.gson.Weather; import com.example.coolweather.service.AutoUpdateService; import com.example.coolweather.util.HttpUtil; import com.example.coolweather.util.Utility; import java.io.IOException; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; public class WeatherActivity extends AppCompatActivity { private ScrollView weatherLayout; private TextView titleCity; private TextView titleUpdateTime; private TextView degreeText; private TextView weatherInfoText; private LinearLayout forecastLayout; private TextView aqiText; private TextView pm25Text; private TextView comfortText; private TextView carWashText; private TextView sportText; private ImageView bingPicImg; public SwipeRefreshLayout swipeRefresh; private String mWeatherId; // To add the logical processing of sliding menu in WeatherActivity public DrawerLayout drawerLayout; private Button navButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT >= 21) { View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); getWindow().setStatusBarColor(Color.TRANSPARENT); } setContentView(R.layout.activity_weather); // Initialize each control weatherLayout = (ScrollView) findViewById(R.id.weather_layout); titleCity = (TextView) findViewById(R.id.title_city); titleUpdateTime = (TextView) findViewById(R.id.title_update_time); degreeText = (TextView) findViewById(R.id.degree_text); weatherInfoText = (TextView) findViewById(R.id.weather_info_text); forecastLayout = (LinearLayout) findViewById(R.id.forecast_layout); aqiText = (TextView) findViewById(R.id.aqi_text); pm25Text = (TextView) findViewById(R.id.pm25_text); comfortText = (TextView) findViewById(R.id.comfort_text); carWashText = (TextView) findViewById(R.id.car_wash_text); sportText = (TextView) findViewById(R.id.sport_text); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences (this); String weatherString = prefs.getString("weather", null); drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); navButton = (Button) findViewById(R.id.nav_button); swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); swipeRefresh.setColorSchemeResources(R.color.colorPrimary); if (weatherString != null) { // Directly parse weather data when there is cache Weather weather = Utility.handleWeatherResponse(weatherString); mWeatherId = weather.basic.weatherId; showWeatherInfo(weather); } else { // Go to the server to query the weather when there is no cache mWeatherId = getIntent().getStringExtra("weather_id"); weatherLayout.setVisibility(View.INVISIBLE); requestWeather(mWeatherId); } swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout. OnRefreshListener() { @Override public void onRefresh() { requestWeather(mWeatherId); } }); bingPicImg = (ImageView) findViewById(R.id.bing_pic_img); String bingPic = prefs.getString("bing_pic", null); if (bingPic != null) { Glide.with(this).load(bingPic).into(bingPicImg); } else { loadBingPic(); } navButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { drawerLayout.openDrawer(GravityCompat.START); } }); } /** * Request city weather information according to weather id */ public void requestWeather(final String weatherId) { String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=bc0418b57b2d4918819d3974ac1285d9"; HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() { @Override public void onResponse(Call call, Response response) throws IOException { final String responseText = response.body().string(); final Weather weather = Utility.handleWeatherResponse(responseText); runOnUiThread(new Runnable() { @Override public void run() { if (weather != null && "ok".equals(weather.status)) { SharedPreferences.Editor editor = PreferenceManager. getDefaultSharedPreferences(WeatherActivity. this).edit(); editor.putString("weather", responseText); editor.apply(); mWeatherId = weather.basic.weatherId; showWeatherInfo(weather); } else { Toast.makeText(WeatherActivity.this, "Failed to get weather information", Toast.LENGTH_SHORT).show(); } swipeRefresh.setRefreshing(false); } }); } @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(WeatherActivity.this, "Failed to get weather information", Toast.LENGTH_SHORT).show(); swipeRefresh.setRefreshing(false); } }); } }); } /** * Loading Bing daily chart */ private void loadBingPic() { String requestBingPic = "http://guolin.tech/api/bing_pic"; HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() { @Override public void onResponse(Call call, Response response) throws IOException { final String bingPic = response.body().string(); SharedPreferences.Editor editor = PreferenceManager. getDefaultSharedPreferences(WeatherActivity.this).edit(); editor.putString("bing_pic", bingPic); editor.apply(); runOnUiThread(new Runnable() { @Override public void run() { Glide.with(WeatherActivity.this).load(bingPic).into (bingPicImg); } }); } @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } }); } /** * Process and display the data in the Weather entity class */ private void showWeatherInfo(Weather weather) { String cityName = weather.basic.cityName; String updateTime = weather.basic.update.updateTime.split(" ")[1]; String degree = weather.now.temperature + "℃"; String weatherInfo = weather.now.more.info; titleCity.setText(cityName); titleUpdateTime.setText(updateTime); degreeText.setText(degree); weatherInfoText.setText(weatherInfo); forecastLayout.removeAllViews(); for (Forecast forecast : weather.forecastList) { View view = LayoutInflater.from(this).inflate(R.layout.forecast_item, forecastLayout, false); TextView dateText = (TextView) view.findViewById(R.id.date_text); TextView infoText = (TextView) view.findViewById(R.id.info_text); TextView maxText = (TextView) view.findViewById(R.id.max_text); TextView minText = (TextView) view.findViewById(R.id.min_text); dateText.setText(forecast.date); infoText.setText(forecast.more.info); maxText.setText(forecast.temperature.max); minText.setText(forecast.temperature.min); forecastLayout.addView(view); } if (weather.aqi != null) { aqiText.setText(weather.aqi.city.aqi); pm25Text.setText(weather.aqi.city.pm25); } String comfort = "Comfort:" + weather.suggestion.comfort.info; String carWash = "Car wash index:" + weather.suggestion.carWash.info; String sport = "Exercise suggestions:" + weather.suggestion.sport.info; comfortText.setText(comfort); carWashText.setText(carWash); sportText.setText(sport); weatherLayout.setVisibility(View.VISIBLE); Intent intent = new Intent(this, AutoUpdateService.class); startService(intent); } }
Appendix. References
The first line of code 14.7 automatically updates the weather in the background
Download resources
gitee address
https://gitee.com/miao-zehao/cool-weather
summary
If you like, give me a 👍, Pay attention! Continue to share with you the problems encountered in the process of typing code!