问题
I have a jobscheduler that triggers onStartjob of Jobservice. In onStartJob, I start an intentservice to do the work. After the work is done, I want intentservice to do a callback to jobservice so that onjobfinished can be called. How can I do a callback to JobService?
回答1:
You can create BroadcastReceiver and register it in your Jobservice
, in onStartJob()
method, using some ACTION constant (for example ACTION_DOWNLOAD_FINISHED
). This receiver will delegate all work to onJobFinished()
method:
public static final String ACTION_DOWLOAD_FINISHED = "actionDownloadFinished";
private BroadcastReceiver downloadFinishedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(this); //Unregister receiver to avoid receiver leaks exception
onJobFinished();
}
};
public void onStartJob() {
IntentFilter filter = new IntentFilter(ACTION_DOWNLOAD_FINISHED);
//Use LocalBroadcastManager to catch the intents only from your app
LocalBroadcastManager.getInstance(this).registerReceiver(downloadFinishedReceiver , filter);
//other job starting stuff...
}
Then, after the intent service has ended it's work, you can send broadcasting intent with ACTION_DOWNLOAD_FINISHED
action from it:
// ...downloading stuff
Intent downloadFinishedIntent = new Intent(Jobservice.ACTION_DOWNLOAD_FINISHED);
//Use LocalBroadcastManager to broadcast intent only within your app
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
When the job of the intent service is finished, it sends broadcasting intent that is catched by the receiver registered in the Jobservice. Receiver then invokes the onJobFinished() method.
You can find the details there: https://developer.android.com/training/run-background-service/report-status.html
回答2:
I am doing the same thing (JobService that starts an IntentService) and here is what I did:
The short story is that I used a Handler with a Handler.Callback that I could pass to my IntentService as a Messenger so that the IntentService could send a Message to Handler.Callback to finish the job. The Handler.Callback has visibility into my JobService so it can call finishJob(...).
public class MyJobService extends JobService implements Handler.Callback {
private Handler mHandler = new Handler(this);
public static final String BNDL_MESSENGER = "messenger";
public static final String BNDL_PARAMS = "params";
public static final int FINISH_JOB_MESSAGE = 100;
public static final int NEEDS_RESCHEDULE_TRUE = 0;
public static final int NEEDS_RESCHEDULE_FALSE = 1;
public boolean handleMessage(Message msg) {
int msgType = msg.what;
if (msgType == FINISH_JOB_MESSAGE) {
int jobId = msg.arg1;
JobParameters params = (JobParameters)msg.obj;
boolean needsReschedule = (msg.arg2 == NEEDS_RESCHEDULE_TRUE);
Log.i(TAG, "Finishing Job ID: " + jobId);
jobFinished(params, needsReschedule);
} else {
Log.e(TAG, "Message type not supported: " + msgType);
}
}
@Override
public boolean onStartJob(JobParameters params) {
Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra(BNDL_MESSENGER, new Messenger(mHandler));
intent.putExtra(BNDL_PARAMS, params);
startService(intent);
}
}
Then your IntentService sends a Message back:
public class MyIntentService extends IntentService {
@Override
public void onHandleIntent(Intent intent) {
Messenger messenger = (Messenger)intent.getParcelableExtra(MyJobService.BNDL_MESSENGER);
JobParameters params = (JobParameters)intent.getParcelableExtra(MyJobService.BNDL_PARAMS);
if (messenger != null) {
Message msg = Message.obtain();
msg.what = MyJobService.FINISH_JOB_MESSAGE;
msg.arg1 = params.getJobId();
msg.arg2 = MyJobService.NEEDS_RESCHEDULE_TRUE;
msg.obj = params;
try {
messenger.send(msg);
} catch (RemoteException re) {
Log.e(TAG, "Couldn't send message to finish job!", re);
}
}
}
}
来源:https://stackoverflow.com/questions/38647733/callback-to-jobservice-from-intentservcie