1 /* 2 * Copyright 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.jobscheduler 18 19 import android.app.Service 20 import android.app.job.JobParameters 21 import android.app.job.JobService 22 import android.content.Intent 23 import android.os.Handler 24 import android.os.Message 25 import android.os.Messenger 26 import android.os.RemoteException 27 import android.util.Log 28 29 /** 30 * Service to handle callbacks from the JobScheduler. Requests scheduled with the JobScheduler 31 * ultimately land on this service's "onStartJob" method. It runs jobs for a specific amount of time 32 * and finishes them. It keeps the activity updated with changes via a Messenger. 33 */ 34 class MyJobService : JobService() { 35 36 private var activityMessenger: Messenger? = null 37 38 /** 39 * When the app's MainActivity is created, it starts this service. This is so that the 40 * activity and this service can communicate back and forth. See "setUiCallback()" 41 */ 42 override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { 43 activityMessenger = intent.getParcelableExtra(MESSENGER_INTENT_KEY) 44 return Service.START_NOT_STICKY 45 } 46 47 override fun onStartJob(params: JobParameters): Boolean { 48 // The work that this service "does" is simply wait for a certain duration and finish 49 // the job (on another thread). 50 sendMessage(MSG_COLOR_START, params.jobId) 51 52 // Uses a Handler to delay the execution of jobFinished(). 53 val duration = params.extras.getLong(WORK_DURATION_KEY) 54 Handler().postDelayed({ 55 sendMessage(MSG_COLOR_STOP, params.jobId) 56 jobFinished(params, false) 57 }, duration) 58 Log.i(TAG, "on start job: ${params.jobId}") 59 60 // Return true as there's more work to be done with this job. 61 return true 62 } 63 64 override fun onStopJob(params: JobParameters): Boolean { 65 // Stop tracking these job parameters, as we've 'finished' executing. 66 sendMessage(MSG_COLOR_STOP, params.jobId) 67 Log.i(TAG, "on stop job: ${params.jobId}") 68 69 // Return false to drop the job. 70 return false 71 } 72 73 private fun sendMessage(messageID: Int, params: Any?) { 74 // If this service is launched by the JobScheduler, there's no callback Messenger. It 75 // only exists when the MainActivity calls startService() with the callback in the Intent. 76 if (activityMessenger == null) { 77 Log.d(TAG, "Service is bound, not started. There's no callback to send a message to.") 78 return 79 } 80 val message = Message.obtain() 81 message.run { 82 what = messageID 83 obj = params 84 } 85 try { 86 activityMessenger?.send(message) 87 } catch (e: RemoteException) { 88 Log.e(TAG, "Error passing service object back to activity.") 89 } 90 } 91 92 companion object { 93 private val TAG = "MyJobService" 94 } 95 } 96