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);
            }
        });


    }