// synchronize for safe: check downloading, check resume, update data, execute runnable public synchronized void start( final String url, final String path, final boolean pathAsDirectory, final int callbackProgressTimes, final int callbackProgressMinIntervalMillis, final int autoRetryTimes, final boolean forceReDownload, final FileDownloadHeader header) { final int id = FileDownloadUtils.generateId(url, path, pathAsDirectory); FileDownloadModel model = mHelper.find(id); if (!pathAsDirectory && model == null) { // try dir data. final int dirCaseId = FileDownloadUtils.generateId(url, FileDownloadUtils.getParent(path), true); model = mHelper.find(dirCaseId); if (model != null && path.equals(model.getTargetFilePath())) { if (FileDownloadLog.NEED_LOG) { FileDownloadLog.d(this, "task[%d] find model by dirCaseId[%d]", id, dirCaseId); } } } if (FileDownloadHelper.inspectAndInflowDownloading(id, model, this)) { if (FileDownloadLog.NEED_LOG) { FileDownloadLog.d(this, "has already started download %d", id); } return; } final String targetFilePath = model != null ? model.getTargetFilePath() : FileDownloadUtils.getTargetFilePath(path, pathAsDirectory, null); if (FileDownloadHelper.inspectAndInflowDownloaded(id, targetFilePath, forceReDownload)) { if (FileDownloadLog.NEED_LOG) { FileDownloadLog.d(this, "has already completed downloading %d", id); } return; } // real start // - create model boolean needUpdate2DB; if (model != null && (model.getStatus() == FileDownloadStatus.paused || model.getStatus() == FileDownloadStatus.error) // FileDownloadRunnable invoke // #isBreakpointAvailable to determine whether it is really invalid. ) { if (model.getId() != id) { // in try dir case. mHelper.remove(model.getId()); model.setId(id); model.setPath(path, pathAsDirectory); needUpdate2DB = true; } else { needUpdate2DB = false; } } else { if (model == null) { model = new FileDownloadModel(); } model.setUrl(url); model.setPath(path, pathAsDirectory); model.setId(id); model.setSoFar(0); model.setTotal(0); model.setStatus(FileDownloadStatus.pending); needUpdate2DB = true; } // - update model to db if (needUpdate2DB) { mHelper.update(model); } // - execute mThreadPool.execute( new FileDownloadRunnable( client, this, model, mHelper, autoRetryTimes, header, callbackProgressMinIntervalMillis, callbackProgressTimes, forceReDownload)); }