java - How to end android service after ASyncTask it spun off completes? -
i have downloader service loads list of downloads run database.
it creates asynctask run downloads in background thread.
this works well, problem don't have way tell service downloader has completed. somehow have send service message asynctask's onpostexecute function (which runs on uithread).
i can't close service remotely because service has work when asynctask completes.
i've considered registering listener service , calling in onpostexecute, think cause problems closing service before task complete or threadlocking issues.
how can send message (like broadcast intent) downloader service asynctask?
edit
here's code of confused doing.
downloadservice.java (important bits):
public class downloadservice extends service implements onprogresslistener { /** downloads. */ private list<download> mdownloads = new arraylist<download>(10); private downloadtask mdownloadtask; /** intent receiver handles broadcasts. */ private broadcastreceiver mintentreceiver = new broadcastreceiver() { @override public void onreceive(context context, intent intent) { debuglog.i(tag, "onrecieve" +intent.tostring()); handlecommand(intent); } }; /* (non-javadoc) * @see android.app.service#oncreate() */ @override public void oncreate() { debuglog.i(tag, "oncreate"); mnm = (notificationmanager)getsystemservice(notification_service); intentfilter commandfilter = new intentfilter(); commandfilter.addaction(action_pause_downloads); commandfilter.addaction(action_start_downloads); registerreceiver(mintentreceiver, commandfilter); } /* (non-javadoc) * @see android.app.service#ondestroy() */ @override public void ondestroy(){ debuglog.i(tag, "ondestroy"); //make sure downloads saved , stopped pausealldownloads(); //unregister command receiver unregisterreceiver(mintentreceiver); //cancel notifications closenotification(); } /* (non-javadoc) * @see android.app.service#onstartcommand(android.content.intent, int, int) */a @override public int onstartcommand(intent intent, int flags, int startid) { handlecommand(intent); // want service continue running until explicitly // stopped, return sticky. return start_sticky; } /** * handle command sent via intent. * <strong>warning, function shouldn't heavy lifting. * run in ui thread , should spin off asynctasks work.</strong> * * @param intent intent */ private void handlecommand(intent intent) { if(intent != null){ string action = intent.getaction(); uri data = intent.getdata(); if(action.equals(action_start_downloads)) { updatedownloads();//fetch list of downloads database startdownloads();//run downloads }else if(action.equals(action_pause_downloads)){ pausealldownloads(); } } } /** * start downloads in list (in order). */ private void startdownloads() { pausealldownloads();//make sure don't have download task running mdownloadtask = new downloadtask(); mdownloadtask.setonprogresslistener(this); download[] downloads = new download[mdownloads.size()]; for(int = 0; i<mdownloads.size(); i++) { download d = mdownloads.get(i); if(d.getstatus() != download.complete) { downloads[i] = mdownloads.get(i); } } //must called on ui thread mdownloadtask.execute(downloads); } /** * pause downloads. */ private void pausealldownloads() { if(mdownloadtask == null) { //done. nothing downloading. return; } //cancel download task first doesn't start downloading next if(mdownloadtask.cancel(true)) { //task has been canceled. pause active download. download activedownload = mdownloadtask.getactivedownload(); if(activedownload != null) { activedownload.pause(); } }else { if(mdownloadtask.getstatus() == asynctask.status.finished) { debuglog.w(tag, "download task finished"); }else{ //task not stopped debuglog.w(tag, "download task not stopped"); } } } @override public void onprogress(download download) { //download progress reported here downloadtask } }
downloadtask:
/** * class downloadtask. */ public class downloadtask extends asynctask<download, download, void> { /** on progress listener. */ private onprogresslistener monprogresslistener; /** * listener interface receiving onprogress events. * class interested in processing onprogress * event implements interface , registers component. * */ public static interface onprogresslistener { /** * on progress update. * * @param download download */ public void onprogress(download download); } private download mcurrent; /** * sets on progress listener. * * @param listener new on progress listener */ public void setonprogresslistener(onprogresslistener listener) { monprogresslistener = listener; } /** * gets active download. * * @return active download */ public download getactivedownload() { return mcurrent; } /* (non-javadoc) * @see android.os.asynctask#doinbackground(params[]) */ @override protected void doinbackground(download... params) { int count = params.length; (int = 0; < count; i++) { mcurrent = params[i]; if(mcurrent == null) { continue; } mcurrent.setdownloadprogresslistener(new download.ondownloadprogresslistener() { @override public void ondownloadprogress(download download, int bytesdownloaded, int bytestotal) { publishprogress(download); } }); mcurrent.setonstatuschangedlistener(new download.onstatuschangedlistener() { @override public void onstatuschanged(download download, int status) { publishprogress(download); } }); mcurrent.download(); //publishprogress(mcurrent); redundant call if(this.iscancelled()) break; } return null; } /* (non-javadoc) * @see android.os.asynctask#onpostexecute(java.lang.object) */ public void onpostexecute(void v) { //todo notify completion. } /* (non-javadoc) * @see android.os.asynctask#onprogressupdate(progress[]) */ @override protected void onprogressupdate(download... progress) { if(monprogresslistener != null) { for(download d:progress) { monprogresslistener.onprogress(d); } } } }
i have downloader service loads list of downloads run database. creates asynctask run downloads in background thread.
why not use intentservice
, considering has background thread you? here sample project demonstrating using intentservice
downloads.
i don't have way tell service downloader has completed.
call stopself()
onpostexecute()
. better yet, use intentservice
, automatically shut down when there no more work done.
Comments
Post a Comment