为了让天气软件更加只能,我们可以加入后台自动更新天气的功能,这样就可以尽可能保证用户每次打开软件时看到的都是最新的天气信息。

    想要实现上诉功能,就需要创建一个长期在后台运行的定时任务。首先在service包下新建一个服务,右击com.coolweather.android.service-New-Service-Service,创建一个AutoUpdateService,并将Exported和Enabled这两个属性都勾中。然后修改AutoUpdateService中的代码,如下所示:



1 public class AutoUpdateService extends Service {
 2 
 3     @Override
 4     public IBinder onBind(Intent intent) {
 5         return null;
 6     }
 7 
 8     @Override
 9     public int onStartCommand(Intent intent, int flags, int startId) {
10         updateWeather();
11         updateBingPic();
12         AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
13         int anHour = 8 * 60 * 60 * 1000; // 这是8小时的毫秒数
14         long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
15         Intent i = new Intent(this, AutoUpdateService.class);
16         PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
17         manager.cancel(pi);
18         manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
19         return super.onStartCommand(intent, flags, startId);
20     }
21 
22     /**
23      * 更新天气信息。
24      */
25     private void updateWeather(){
26         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
27         String weatherString = prefs.getString("weather", null);
28         if (weatherString != null) {
29             // 有缓存时直接解析天气数据
30             Weather weather = Utility.handleWeatherResponse(weatherString);
31             String weatherId = weather.basic.weatherId;
32             String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=bc0418b57b2d4918819d3974ac1285d9";
33             HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
34                 @Override
35                 public void onResponse(Call call, Response response) throws IOException {
36                     String responseText = response.body().string();
37                     Weather weather = Utility.handleWeatherResponse(responseText);
38                     if (weather != null && "ok".equals(weather.status)) {
39                         SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(AutoUpdateService.this).edit();
40                         editor.putString("weather", responseText);
41                         editor.apply();
42                     }
43                 }
44 
45                 @Override
46                 public void onFailure(Call call, IOException e) {
47                     e.printStackTrace();
48                 }
49             });
50         }
51     }
52 
53     /**
54      * 更新必应每日一图
55      */
56     private void updateBingPic() {
57         String requestBingPic = "http://guolin.tech/api/bing_pic";
58         HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {
59             @Override
60             public void onResponse(Call call, Response response) throws IOException {
61                 String bingPic = response.body().string();
62                 SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(AutoUpdateService.this).edit();
63                 editor.putString("bing_pic", bingPic);
64                 editor.apply();
65             }
66 
67             @Override
68             public void onFailure(Call call, IOException e) {
69                 e.printStackTrace();
70             }
71         });
72     }
73 
74 }



    可以看到,在onStartCommand()方法中先是调用了updateWeather()方法来更新天气,然后调用了updateBingPic()方法来更新背景图片。这里我们将更新后的数据直接存储到SharedPreferences文件中就可以了,因为打开WeatherActivity的时候都会优先从SharedPreferences缓存中读取数据。

    之后就是创建定时任务的技巧了,为了保证软件不会消耗太多的流量,这里将时间间隔设置为8小时,8小时后AutoUpdateReceiver的onStartCommand()方法就会重新执行,这样也就实现后台定时更新的功能了。

    我们还需要在代码某处去激活AutoUpdateService这个服务才行。修改WeatherActivity中的代码,如下所示:

 



1 public class WeatherActivity extends AppCompatActivity{
 2     ...
 3     /**
 4      * 处理并展示Weather实体类中的数据
 5      */
 6     private void showWeatherInfo(Weather weather){
 7         if(weather != null&& "ok".equals(weather.status)){
 8             ...
 9             Intent intent = new Intent(this,AutoUpdateService.class);
10             startService(intent);
11         }else{
12             Toast.makeText(WeatherActivity.this,"获取天气信息失败",Toast.LENGTH_SHORT).show();
13         }
14     }
15 }



    这里可以看到,在showWeather()方法的最后加入启动AutoUpdateService这个服务的代码,这样只要一旦选中了某个城市并成功更新天气之后,AutoUpdateService就会一直在后台运行,并保证每8小时跟新一次天气。

    截至此,天气软件的主体功能都已经实现了。但我们还可以为它做更多的完善,比如修改图标和名称,或增加设置选项,让用户选择是否允许后台自动更新天气,以及设定更新的频率等等。

    通过这个软件的开发,本人熟悉了UI、网络、数据存储、服务等技术并且加强了综合应用的能力。