Android: How to use JobFinished of JobService

徘徊边缘 提交于 2019-12-09 03:36:41

问题


I didn't see example of using jobFinshed of JobService, seems like we have to track changes when some condition meet we have to call jobFinished() method, am I right?


回答1:


The difficulty of calling jobFinished() from another class like an IntentService seems to be getting an instance of your class that extends JobService to use to call jobFinished(). You can get info on the scheduled job, but not on the JobService (at least, I can't find a way). I can think of 3 ways to call jobFinished().

If you don't care if your work is successful or not, or if your work takes very little time.

In one of my JobService classes, I'm doing periodic work. I'm not worried about handling failures. The task will execute again soon enough. If this is the case, you can do this.

    public boolean onStartJob(JobParameters params) {
        startService(new Intent(this, MyIntentServiceThatDoesTheWork.class));

        // job not really finished here but we assume success & prevent backoff procedures, wakelocking, etc.
        jobFinished(params, false);
        return true;
    }

This is also the way you want to do it if your work is short enough it's no problem to do it on the UI thread. In this case, do all your work in onStartJob() then return false.

Use a BroadcastReceiver to send a message from the IntentService to the JobService (a separate file for each class).

    // common Strings
    public static final String IS_SUCCESS = "isSuccess";
    public static final String MY_BC_RCVR = "MyBroadcastRcvr";

Your JobService

    public class MyJobService extends JobService {
        JobParameters mParams;

        public boolean onStartJob(JobParameters params) {
            mParams = params;
            LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
                    new IntentFilter(MY_BC_RCVR));
            startService(new Intent(this, MyIntentServiceThatDoesTheWork.class));
            return true;
        }

        private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                boolean isSuccess = false;
                if(intent.hasExtra(IS_SUCCESS)) {
                    isSuccess = intent.getBooleanExtra(IS_SUCCESS, false);
                }
                LocalBroadcastManager.getInstance(context).unregisterReceiver(this);
                jobFinished(mParams, !isSuccess);
            }
        };
    }

& your IntentService

    public class MyIntentServiceThatDoesTheWork extends IntentService {
        @Override
        protected void onHandleIntent(Intent intent) {

            boolean isSuccess = methodToDoAllMyWork();
            Intent bcIntent = new Intent(MY_BC_RCVR);
            bcIntent.putExtra(IS_SUCCESS, isSuccess);
            LocalBroadcastManager.getInstance(this).sendBroadcast(bcIntent);
        }
    }

Nest your worker thread class in the JobService class.

I've given an example of an AsyncTask based on this Medium post (also referenced by Arseny Levin) from a Google Developer Advocate but it should also be possible to use an IntentService (see this SO post for nesting IntentService).

    public class MyJobService extends JobService {
        JobParameters mParams;

        public boolean onStartJob(JobParameters params) {
            mParams = params;
            new MyAsyncTaskThatDoesTheWork().execute();
            return true;
        }

        private class MyAsyncTaskThatDoesTheWork extends AsyncTask<Void, Void, Boolean> {
            @Override
            protected Boolean doInBackground(Void... params) {
                return methodToDoAllMyWork();
            }

            @Override
            protected void onPostExecute(Boolean isSuccess) {
                if(mParams != null) {
                    jobFinished(mParams, !isSuccess);
                }
            }
        }
    }



回答2:


If your onStartJob() method returns true, that means that you are doing work in the background in support of this job. That background thread needs to call jobFinished() when that work has been completed or if the job needs to be rescheduled.




回答3:


As @CommonsWare explained - inside onStartJob you'll decide if further work is required on a background thread. Only if that's the case, then you should call jobFinished from that background thread. Just to answer your specific question - no condition tracking is required on your behalf. JobService will call onStopJob if the conditions you asked are no longer true.

Example of jobFinished can be found here: https://medium.com/google-developers/scheduling-jobs-like-a-pro-with-jobscheduler-286ef8510129




回答4:


A simple approach is to start a new thread from onStartJob as shown below:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MyJobService extends JobService {
    @Override
    public boolean onStartJob(final JobParameters params) {
      new Thread(new Runnable() {
        @Override
        public void run() {

            // do your job here

            jobFinished(params, true);
        }
      }).start();

      return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
      return true;
    }
}


来源:https://stackoverflow.com/questions/44554256/android-how-to-use-jobfinished-of-jobservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!