Java 在android服务分拆完成后,如何结束该服务?

Java 在android服务分拆完成后,如何结束该服务?,java,android,service,android-intent,android-asynctask,Java,Android,Service,Android Intent,Android Asynctask,我有一个下载服务,可以从我的数据库中加载下载列表 然后创建一个异步任务,在后台线程中运行下载 这一切都很好,但问题是我目前没有办法告诉服务下载程序已经完成。我不得不从ASyncTask的函数(在UIThread上运行)向服务发送一条消息 我不能简单地远程关闭服务,因为当异步任务完成时,服务还有一些工作要做 我考虑过从服务中注册一个侦听器并在onPostExecute中调用它,但我认为这会导致一些问题,比如在任务完成之前关闭服务,或者出现一些线程锁定问题 如何从ASyncTask向Download

我有一个下载服务,可以从我的数据库中加载下载列表

然后创建一个异步任务,在后台线程中运行下载

这一切都很好,但问题是我目前没有办法告诉服务下载程序已经完成。我不得不从ASyncTask的函数(在UIThread上运行)向服务发送一条消息

我不能简单地远程关闭服务,因为当异步任务完成时,服务还有一些工作要做

我考虑过从服务中注册一个侦听器并在onPostExecute中调用它,但我认为这会导致一些问题,比如在任务完成之前关闭服务,或者出现一些线程锁定问题

如何从ASyncTask向Downloader服务发送消息(如广播意图)

编辑
下面是一些代码,供你们中对我所做的感到困惑的人使用

DownloadService.java(重要位):

公共类下载服务扩展了ProgressListener上的服务实现{
/**下载*/
私有列表mDownloads=newarraylist(10);
私有下载任务mDownloadTask;
/**处理广播的目的接收器*/
private BroadcastReceiver mIntentReceiver=新的BroadcastReceiver()
{
@凌驾
公共void onReceive(上下文、意图){
i(标记“onreceive”+intent.toString());
handleCommand(意图);
}
};
/*(非Javadoc)
*@see android.app.Service#onCreate()
*/
@凌驾
public void onCreate(){
DebugLog.i(标记“onCreate”);
mNM=(NotificationManager)getSystemService(通知服务);
IntentFilter commandFilter=新建IntentFilter();
addAction(操作\暂停\下载);
addAction(操作开始下载);
registerReceiver(MinentReceiver、commandFilter);
}
/*(非Javadoc)
*@see android.app.Service#onDestroy()
*/
@凌驾
公共空间{
DebugLog.i(标记“onDestroy”);
//确保保存并停止所有下载
pauseAllDownloads();
//取消注册命令接收器
未注册接收人(mIntentReceiver);
//取消通知
closeNotification();
}
/*(非Javadoc)
*@see android.app.Service#onStartCommand(android.content.Intent,int,int)
*/a
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
handleCommand(意图);
//我们希望此服务继续运行,直到显式恢复
//停止,所以返回粘性。
返回开始时间;
}
/**
*Handle通过intent发送的命令。
*警告,此功能不应执行任何重载操作。
*这将在UI线程中运行,并应派生异步任务来完成工作。
*
*@param意图-意图
*/
私有无效handleCommand(意向){
if(intent!=null){
String action=intent.getAction();
Uri data=intent.getData();
if(action.equals(action\u START\u下载))
{
updateDownloads();//从数据库获取要执行的下载列表
startDownloads();//运行下载
}else if(action.equals(action\u PAUSE\u DOWNLOADS)){
pauseAllDownloads();
}
}
}
/**
*启动列表中当前的所有下载(按顺序)。
*/
私有void startDownloads()
{
pauseAllDownloads();//确保我们没有运行下载任务
mDownloadTask=new DownloadTask();
mDownloadTask.setOnProgressListener(此);
Download[]downloads=新下载[mDownloads.size()];
对于(int i=0;i
我有一个下载服务,可以从我的数据库中加载下载列表。
然后创建一个异步任务,在后台线程中运行下载

为什么不直接使用
IntentService
,因为它已经为您提供了一个后台线程?演示如何使用
IntentService
进行下载

我目前没有办法告诉服务下载程序已经完成

onPostExecute()
调用
stopSelf()
。最好使用
IntentService
,当没有更多工作要做时,它会自动关闭

我有一个下载服务,可以从我的数据库中加载下载列表。 然后创建一个异步任务,在后台线程中运行下载

为什么不直接使用
IntentService
,因为它已经为您提供了一个后台线程?演示如何使用
IntentService
进行下载

我目前没有办法告诉服务下载程序已经完成


onPostExecute()调用
stopSelf()
。更好的方法是使用
IntentService
,当没有更多的工作要做时,它会自动关闭。

你能发布一些示例代码吗。不太清楚服务和AsyncTask是如何协同工作的。通常你需要一个或另一个,但不是两者都需要。我稍后会发布代码,但为了回答你的问题,我的服务人员对下载的内容进行老化,而不需要在前台进行活动,而ASyncTask实际上在后台完成繁重的工作(因为服务不会自动完成)。我本可以从服务中分离出一个线程上的可运行线程,但ASyncTask更容易管理线程。ASyncTask的onPostExecute在doInBackground之后运行,因此相对顺序得到了保证。但我也不明白为什么需要在服务中使用ASyncTask。你能解释更多吗?@Heiko Rupp@Robby Pond a服务不是separate线程。要进行繁重的网络通信,我需要从我的服务中剥离另一个线程来完成这项工作,否则UI将锁定,我将得到一个ANR。ASyncTask提供了一种创建和管理此新线程的简单方法。为什么不向服务发送一个意图,通知它下载
public class DownloadService extends Service implements OnProgressListener {

/** The Downloads. */
private List<Download> mDownloads = new ArrayList<Download>(10);

private DownloadTask mDownloadTask;

/** The Intent receiver that 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 all downloads are saved and 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);
    // We want this service to continue running until it is explicitly
    // stopped, so return sticky.
    return START_STICKY;
}
/**
 * Handle command sent via intent.
 * <strong>Warning, this function shouldn't do any heavy lifting.  
 * This will be run in UI thread and should spin off ASyncTasks to do work.</strong>
 *
 * @param intent the 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 to do from database
            startDownloads();//run downloads
        }else if(action.equals(ACTION_PAUSE_DOWNLOADS)){
            pauseAllDownloads();
        }
    }
}

/**
 * Start all downloads currently in list (in order).
 */
private void startDownloads()
{
    pauseAllDownloads();//make sure we don't have a download task running
    mDownloadTask = new DownloadTask();
    mDownloadTask.setOnProgressListener(this);
    Download[] downloads = new Download[mDownloads.size()];
    for(int i = 0; i<mDownloads.size(); i++)
    {
        Download d = mDownloads.get(i);
        if(d.getStatus() != Download.COMPLETE)
        {
            downloads[i] = mDownloads.get(i);   
        }
    }
    //must be called on UI thread
    mDownloadTask.execute(downloads);
}

/**
 * Pause downloads.
 */
private void pauseAllDownloads()
{
    if(mDownloadTask == null)
    {
        //Done.  Nothing is downloading.
        return;
    }

    //Cancel download task first so that it doesn't start downloading next
    if(mDownloadTask.cancel(true))
    {
        //Task has been canceled.  Pause the active download.
        Download activeDownload = mDownloadTask.getActiveDownload();
        if(activeDownload != null)
        {
            activeDownload.pause();
        }
    }else
    {
        if(mDownloadTask.getStatus() == AsyncTask.Status.FINISHED)
        {
            DebugLog.w(TAG, "Download Task Already Finished");
        }else{
            //Task could not be stopped
            DebugLog.w(TAG, "Download Task Could Not Be Stopped");
        }
    }
}

@Override
public void onProgress(Download download) {
    //download progress is reported here from DownloadTask
}
}
/**
 * The Class DownloadTask.
 */
public class DownloadTask extends AsyncTask<Download, Download, Void> {

/** The On progress listener. */
private OnProgressListener mOnProgressListener;

/**
 * The listener interface for receiving onProgress events.
 * The class that is interested in processing a onProgress
 * event implements this interface and registers it with the component.
 *
 */
public static interface OnProgressListener
{

    /**
     * On progress update.
     *
     * @param download the download
     */
    public void onProgress(Download download);
}

private Download mCurrent;

/**
 * Sets the on progress listener.
 *
 * @param listener the new on progress listener
 */
public void setOnProgressListener(OnProgressListener listener)
{
    mOnProgressListener = listener;
}

/**
 * Gets the active download.
 *
 * @return the 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;
    for (int i = 0; i < 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);
        }
    }
}

}