26.11 挑战练习:在 Lollipop 设备上使用 JobService 请创建另一个 PollService 实现版本。新的 PollService 应该继承 JobService 并使用 JobScheduler 来运行。在 PollService 启动代码中,检查系统版本是否为Lollipop:如果是,就 使用 JobScheduler 计划运行 JobService ;如果不是,依然使用 AlarmManager 实现。
JobService类:
1 package com.bignerdranch.android.photogallery;
2
3 import android.app.Notification;
4 import android.app.PendingIntent;
5 import android.app.job.JobInfo;
6 import android.app.job.JobParameters;
7 import android.app.job.JobScheduler;
8 import android.content.ComponentName;
9 import android.content.Context;
10 import android.content.Intent;
11 import android.content.res.Resources;
12 import android.os.AsyncTask;
13 import android.support.v4.app.NotificationCompat;
14 import android.support.v4.app.NotificationManagerCompat;
15 import android.util.Log;
16
17 import java.util.List;
18
19 /**
20 * Created by Leo on 2017/7/22.
21 */
22
23 public class JobService extends android.app.job.JobService {
24
25 private static final String TAG = "PollService";
26
27 private PollTask mCurrentTask;
28
29 @Override
30 public boolean onStartJob(JobParameters parms){ //服务启动后执行
31 mCurrentTask = new PollTask();
32 mCurrentTask.execute(parms); //开启AsyncTask
33 return true;
34 }
35
36 @Override
37 public boolean onStopJob(JobParameters params) {
38 if(mCurrentTask != null){
39 mCurrentTask.cancel(true);
40 }
41 return false;
42 }
43
44
45 public static void setServiceAlarm(Context context,Boolean shouldStartAlarm){ //Fragment中启动服务需要调用的方法.用于在Fragment启动JobService
46 final int JOB_ID = 1;
47 JobScheduler scheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
48 if(shouldStartAlarm){
49 scheduler.cancel(JOB_ID);
50 }else{
51 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, new ComponentName(context, JobService.class))
52 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
53 .setPeriodic(1000 * 60)
54 .setPersisted(true)
55 .build();
56 scheduler.schedule(jobInfo);
57 }
58
59 }
60
61 //判断是否已经计划好了任务
62 public static boolean isHasBeenScheduled(Context context){
63
64 final int JOB_ID = 1;
65
66 JobScheduler scheduler = (JobScheduler)context.getSystemService(JOB_SCHEDULER_SERVICE);
67
68 boolean hasBeenScheduled = false;
69
70 for (JobInfo jobInfo : scheduler.getAllPendingJobs()) {
71 if (jobInfo.getId() == JOB_ID) {
72 hasBeenScheduled = true;
73 }
74 }
75
76 return hasBeenScheduled;
77 }
78
79 public JobService(){
80 super();
81 }
82
83
84 //用于执行
85 private class PollTask extends AsyncTask<JobParameters,Void ,List<GalleryItem>> {
86 //在doInBackground()方法中获取到最新的结果集。
87 @Override
88 protected List<GalleryItem> doInBackground(JobParameters... params) {
89 JobParameters jobParams = params[0];
90
91 //不需要手动判断网络连接状态了
92
93 String query = QueryPreferences.getStoredQuery(JobService.this); //获取查询值
94
95 List<GalleryItem> items;
96
97 //获取最新结果集
98 if(query == null){
99 items = new FlickrFetcher().fetchRecentPhotos();
100 }else{
101 items = new FlickrFetcher().searchPhotos(query);
102 }
103
104 jobFinished(jobParams,false);
105
106 return items; //将items返回出去, onPostExcute()方法会接受到
107 }
108
109 @Override
110 protected void onPostExecute(List<GalleryItem> items) {
111 String lastResultId = QueryPreferences.getLastResultId(JobService.this);
112 //获取第一条结果
113 String resultId = items.get(0).getId();
114 //确认是否不同于上一次结果ID ,不同的话弹出Notification。
115 if(resultId.equals(lastResultId)){
116 Log.i(TAG, "Got a old result" + resultId);
117 }else{
118 Log.i(TAG, "Got a new result" + resultId);
119
120 Resources resources = getResources();
121 Intent i = PhotoGalleryActivity.newIntent(JobService.this);
122 PendingIntent pi = PendingIntent.getActivity(JobService.this,0,i,0);
123
124 Notification notification = new NotificationCompat.Builder(JobService.this)
125 .setTicker(resources.getString(R.string.new_pictures_title))
126 .setSmallIcon(android.R.drawable.ic_menu_report_image)
127 .setContentTitle(resources.getString(R.string.new_pictures_title))
128 .setContentText(resources.getString(R.string.new_pictures_text))
129 .setContentIntent(pi)
130 .setAutoCancel(true)
131 .build();
132
133 NotificationManagerCompat notificationManager = NotificationManagerCompat.from(JobService.this);
134 notificationManager.notify(0,notification);
135 }
136 //将第一条结果存入SharedPreferences
137 QueryPreferences.setLastResultId(JobService.this,resultId);
138 }
139 }
140 }
PhotoGalleryFragment类:
onOptionsSelected()方法:
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case R.id.menu_item_clear:
QueryPreferences.setStoredQuery(getActivity(),null);
updateItems();
return true;
case R.id.menu_item_toggle_polling:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
boolean shouldStartAlarm = JobService.isHasBeenScheduled(getActivity()); //启动服务
JobService.setServiceAlarm(getActivity(),shouldStartAlarm);
getActivity().invalidateOptionsMenu();
}else{
boolean shouldStartAlarm = !PollService.isServiceAlarmOn(getActivity());
PollService.setServiceAlarm(getActivity(),shouldStartAlarm);
getActivity().invalidateOptionsMenu(); //刷新菜单项
}
return true;
default:
return super.onOptionsItemSelected(item);
}
onCreateOptionsMenu()方法:
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater){
super.onCreateOptionsMenu(menu,menuInflater);
menuInflater.inflate(R.menu.fragment_photo_gallery,menu);
MenuItem searchItem = menu.findItem(R.id.menu_item_search); //将MenuItem取出并保存在searchItem变量中。
mSearchView = (SearchView)searchItem.getActionView(); //取出SearchView对象。
//设置监听器
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {//提交搜索查询时。这个方法执行。
Log.d(TAG, "onQueryTextSubmit: "+ s);
QueryPreferences.setStoredQuery(getActivity(),s); //存储用户提交的查询信息。
updateItems();
hintSoftInputAndSearchField(); //隐藏键盘的方法
return true;
}
@Override
public boolean onQueryTextChange(String s) { //搜索框的文字有变化时,这个方法执行。
Log.d(TAG, "onQueryTextChange: " + s);
return false;
}
});
MenuItem toggleItem = menu.findItem(R.id.menu_item_toggle_polling);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
if(JobService.isHasBeenScheduled(getActivity())){
toggleItem.setTitle(R.string.stop_polling);
}else {
toggleItem.setTitle(R.string.start_polling);
}
}else{
if (PollService.isServiceAlarmOn(getActivity())) {
toggleItem.setTitle(R.string.stop_polling);
} else {
toggleItem.setTitle(R.string.start_polling);
}
}
mSearchView.setOnSearchClickListener(new View.OnClickListener() { //设置点击按钮时,显示之前搜索过的值
@Override
public void onClick(View v) {
String query = QueryPreferences.getStoredQuery(getActivity());
mSearchView.setQuery(query,false);
}
});
}