private void resetAndValidateRequest(DownloadRequest request) { // Reset download request request.setLength(0); request.setAvailableLength(0); request.setDownloadStatus(DownloadStatus.None); // Validate download request if (request.getDownloadPriority() == DownloadPriority.None) { throw new IllegalArgumentException("request.DownloadPriority"); } if (request.getLocale() == null || request.getLocale().length() == 0) { throw new IllegalArgumentException("request.Locale"); } if (request.getName() == null || request.getName().length() == 0) { throw new IllegalArgumentException("request.Name"); } if (request.getOverridePermittedNetworkTypes() != null && request.getOverridePermittedNetworkTypes().contains(NetworkTypes.None)) { throw new IllegalArgumentException("request.OverridePermittedNetworkTypes"); } if (request.getUrl() == null || request.getUrl().length() == 0) { throw new IllegalArgumentException("request.Url"); } if (request.getFileName() == null || request.getFileName().length() == 0) { throw new IllegalArgumentException("request.FileName"); } if (_downloadQueue.getDownloadRequest(request.getUrl()) != null) { throw new IllegalArgumentException( "A download request already exists with the specified request's URL."); } }
/// <summary> /// Gets download progress information for the DownloadRequest by the specified URL. /// </summary> /// <param name="url"></param> /// <returns></returns> public DownloadInformation getDownloadInformation(String url) { Log.d(LCAT, "getDownloadInformation " + url); // Get download information DownloadInformation downloadInformation = _completedDownloadCatalog.getDownloadInformation(url); if (downloadInformation == null) { Log.d(LCAT, "NOT in completed catalog check queue"); // If no download information is available for a completed download, // create it from any matching queued download request DownloadRequest request = _downloadQueue.getDownloadRequest(url); if (request != null) { Log.d(LCAT, "Found in queue"); downloadInformation = new DownloadInformation(); downloadInformation.setUrl(request.getUrl()); downloadInformation.setName(request.getName()); downloadInformation.setLocale(request.getLocale()); downloadInformation.setFilePath(request.getFilePath()); downloadInformation.setLength(request.getLength()); downloadInformation.setMediaBitsPerSecond(request.getMediaBitsPerSecond()); downloadInformation.setAvailableLength(request.getAvailableLength()); downloadInformation.setCreationUtc(request.getCreationUtc()); downloadInformation.setLastWriteUtc(request.getLastWriteUtc()); downloadInformation.setLastDownloadBitsPerSecond(request.getLastDownloadBitsPerSecond()); downloadInformation.setDownloadPriority(request.getDownloadPriority()); downloadInformation.setIsReadyForPlayback(request.getIsReadyForPlayback()); downloadInformation.setPermittedNetworkTypes(request.getFinalPermittedNetworkTypes()); downloadInformation.setStorageLocation(request.getFinalStorageLocation()); } } // Return result return downloadInformation; }
/// <summary> /// Restarts download of the in-progress or completed item with the specified URL, beginning at // the specified byte offset. /// </summary> /// <param name="url"></param> /// <param name="byteOffset"></param> public void restart(String url, long byteOffset) { // Locals DownloadRequest downloadRequest; DownloadInformation downloadInformation; // Get download information downloadRequest = _downloadQueue.getDownloadRequest(url); if (downloadRequest == null) { downloadInformation = _completedDownloadCatalog.getDownloadInformation(url); if (downloadInformation == null) { return; } downloadRequest = new DownloadRequest(); downloadRequest.setUrl(downloadInformation.getUrl()); downloadRequest.setName(downloadInformation.getName()); downloadRequest.setLocale(downloadInformation.getLocale()); downloadRequest.setOverrideStorageLocation(downloadInformation.getStorageLocation()); downloadRequest.setDownloadPriority(downloadInformation.getDownloadPriority()); downloadRequest.setOverridePermittedNetworkTypes( downloadInformation.getPermittedNetworkTypes()); if (byteOffset == OFFSET_ZERO) { delete(downloadInformation.getUrl()); } else { downloadRequest.setAvailableLength(byteOffset); } } else { downloadRequest = new DownloadRequest(); downloadRequest.setUrl(downloadRequest.getUrl()); downloadRequest.setName(downloadRequest.getName()); downloadRequest.setLocale(downloadRequest.getLocale()); downloadRequest.setOverrideStorageLocation(downloadRequest.getOverrideStorageLocation()); downloadRequest.setDownloadPriority(downloadRequest.getDownloadPriority()); downloadRequest.setOverridePermittedNetworkTypes( downloadRequest.getOverridePermittedNetworkTypes()); } // Restart download information _downloadQueue.add(downloadRequest, _defaultStorageLocation, _permittedNetworkTypes); }
public void run() { Log.d(LCAT, "Download thread started"); // Locals HttpClient webRequest1; DownloadRequest downloadRequest; DownloadInformation downloadInformation; DownloadBatchRequest downloadBatchRequest; DownloadBatchInformation downloadBatchInformation; DownloadPriority priority; // Initialize downloadInformation = null; downloadBatchInformation = null; downloadRequest = this.request; downloadBatchRequest = downloadRequest.getDownloadBatchRequestId() == null ? null : _downloadQueue.getDownloadBatchRequest(downloadRequest.getDownloadBatchRequestId()); priority = downloadRequest.getDownloadPriority(); try { // Initialize download information to report progress downloadInformation = new DownloadInformation(); downloadInformation.setUrl(downloadRequest.getUrl()); downloadInformation.setName(downloadRequest.getName()); downloadInformation.setLocale(downloadRequest.getLocale()); downloadInformation.setFilePath(downloadRequest.getFilePath()); downloadInformation.setLength(downloadRequest.getLength()); downloadInformation.setMediaBitsPerSecond(downloadRequest.getMediaBitsPerSecond()); downloadInformation.setAvailableLength(downloadRequest.getAvailableLength()); downloadInformation.setCreationUtc(downloadRequest.getCreationUtc()); downloadInformation.setLastWriteUtc(downloadRequest.getLastWriteUtc()); downloadInformation.setLastDownloadBitsPerSecond( downloadRequest.getLastDownloadBitsPerSecond()); downloadInformation.setDownloadPriority(downloadRequest.getDownloadPriority()); downloadInformation.setIsReadyForPlayback(downloadRequest.getIsReadyForPlayback()); downloadInformation.setPermittedNetworkTypes( downloadRequest.getFinalPermittedNetworkTypes()); downloadInformation.setStorageLocation(downloadRequest.getFinalStorageLocation()); if (downloadBatchRequest != null) { // Get or create batch download information synchronized (_downloadBatchInformationLock) { downloadBatchInformation = _downloadBatchInformationById.get(downloadBatchRequest.getDownloadBatchRequestId()); if (downloadBatchInformation == null) { downloadBatchInformation = new DownloadBatchInformation(); downloadBatchInformation.setDownloadBatchRequestId( downloadBatchRequest.getDownloadBatchRequestId()); downloadBatchInformation.setName(downloadBatchRequest.getName()); downloadBatchInformation.setLocale(downloadBatchRequest.getLocale()); downloadBatchInformation.setOverrideStorageLocation( downloadBatchRequest.getOverrideStorageLocation()); downloadBatchInformation.setDownloadPriority( downloadBatchRequest.getDownloadPriority()); _downloadBatchInformationById.put( downloadBatchRequest.downloadBatchRequestId, downloadBatchInformation); } // Add this download's information to the batch's collection of download informations downloadBatchInformation.getDownloadInformations().add(downloadInformation); } } // Locals int byteCount; byte[] buffer; FileOutputStream fileStream; long bpsTrackingSpan; Date bpsTrackingStart; int trackBpsIterationCount; int bytesForBps; int fireProgressEventCount; boolean downloadBatchRequestIsComplete; // Initialize fileStream = null; fireProgressEventCount = 0; trackBpsIterationCount = 0; bpsTrackingSpan = 0; bytesForBps = 0; InputStream responseStream = null; try { // Open output file and seek to next write position String filePath = downloadRequest.getFilePath(); if (filePath.startsWith("file://")) { filePath = filePath.substring(7); } String message = "resume"; Log.d(LCAT, "Creating file for writing: " + filePath); File file = new File(filePath); if (file.exists() == false) { message = "start"; boolean createRet = file.createNewFile(); Log.d(LCAT, "file.createNewFile returned " + createRet); } downloadInformation.setMessage(message); DownloadStarted.fireEvent(new DownloadEvent(this, downloadInformation, null)); Log.d( LCAT, "File length: " + file.length() + " available length: " + downloadRequest.getAvailableLength()); if (file.length() != downloadRequest.getAvailableLength()) { Log.d(LCAT, "File length and available length were different so using file length"); downloadRequest.setAvailableLength(file.length()); } webRequest1 = new DefaultHttpClient(); HttpGet request = new HttpGet(); request.setURI(new URI(downloadRequest.getUrl())); if (downloadRequest.getAvailableLength() > OFFSET_ZERO) { request.setHeader( "Range", "bytes=" + downloadRequest.getAvailableLength() + '-' + downloadRequest.getLength()); // Start downloading after already-downloaded bytes // webRequest1.AddRange(downloadRequest.getAvailableLength()); } // webRequest1.AutomaticDecompression = DecompressionMethods.GZip | // DecompressionMethods.Deflate; HttpResponse response = webRequest1.execute(request); responseStream = response.getEntity().getContent(); FileOutputStream outputStream; // Get response if (response.containsHeader(HTTP_RESPONSE_HEADER_ACCEPT_RANGES) == true && response.getFirstHeader(HTTP_RESPONSE_HEADER_ACCEPT_RANGES).getValue() == HTTP_RESPONSE_HEADER_ACCEPT_RANGES_NONE) { // Response is for entire file, or server does not support byte ranges, so reset // available length to 0 Log.d(LCAT, "Resetting available length"); downloadRequest.setAvailableLength(0); downloadInformation.setAvailableLength(0); outputStream = new FileOutputStream(file, false); } else { outputStream = new FileOutputStream(file, true); } // On first download downloadInformation for file, set length of downloadRequest if (downloadRequest.getLength() == 0 || downloadRequest.getAvailableLength() == 0) { long contentLength = Long.parseLong(response.getFirstHeader("content-length").getValue()); Log.d(LCAT, "Setting length to " + contentLength); downloadRequest.setLength(contentLength); downloadInformation.setLength(contentLength); } // FileOutputStream outputStream = new FileOutputStream(file, true); outputStream.flush(); // Receive and store bytes long loopCount = 0; buffer = new byte[DOWNLOAD_BUFFER_SIZE]; bpsTrackingStart = new Date(); while (_downloadRequestUrlsThatMayProceed.containsKey(downloadRequest.getUrl()) == true && (byteCount = responseStream.read(buffer, 0, DOWNLOAD_BUFFER_SIZE)) > 0) { if (priority == DownloadPriority.Low) { Thread.yield(); } else if (priority == DownloadPriority.Normal && (loopCount % 4) == 0) { Thread.yield(); } ++loopCount; bytesForBps += byteCount; // Update status of downloadRequest if (downloadRequest.getDownloadStatus() == DownloadStatus.None) { downloadRequest.setDownloadStatus(DownloadStatus.InProgress); } if (downloadBatchRequest != null && downloadBatchRequest.getDownloadStatus() == DownloadStatus.None) { downloadBatchRequest.setDownloadStatus(DownloadStatus.InProgress); } // Store bytes outputStream.write(buffer, 0, byteCount); outputStream.flush(); // Update statistics downloadRequest.setAvailableLength(downloadRequest.getAvailableLength() + byteCount); downloadRequest.setLastWriteUtc(new Date()); downloadInformation.setLastWriteUtc(downloadRequest.getLastWriteUtc()); downloadInformation.setAvailableLength(downloadRequest.getAvailableLength()); // Track bits/second (every n iterations through loop) trackBpsIterationCount++; if (trackBpsIterationCount == TRACK_BPS_ON_ITERATION_NUMBER) { Date now = new Date(); bpsTrackingSpan = now.getTime() - bpsTrackingStart.getTime(); if (bpsTrackingSpan != 0) { downloadRequest.setLastDownloadBitsPerSecond( (int) ((8.0 * // bits per byte bytesForBps) / // bytes downloaded in timespan (bpsTrackingSpan / 1000.0))); // Seconds in timespan downloadInformation.setLastDownloadBitsPerSecond( downloadRequest.getLastDownloadBitsPerSecond()); } } // Fire progress event (every n iterations through loop) fireProgressEventCount++; if (fireProgressEventCount == FIRE_PROGRESS_EVENT_ON_ITERATION_NUMBER) { fireProgressEventCount = 0; DownloadProgress.fireEvent( new DownloadEvent(this, downloadInformation, downloadBatchInformation)); } // Reset tracking of bits/second (every n iterations through loop) if (trackBpsIterationCount == TRACK_BPS_ON_ITERATION_NUMBER) { trackBpsIterationCount = 0; if (bpsTrackingSpan != 0) { bytesForBps = 0; bpsTrackingStart = new Date(); } } } // Did the download complete? if (_downloadRequestUrlsThatMayProceed.containsKey(downloadRequest.getUrl()) == true) { // The download succeeded // Close file if (outputStream != null) { outputStream.close(); outputStream.flush(); outputStream = null; } // Remove download request from queue _downloadQueue.remove(downloadRequest.getUrl()); downloadRequest.setDownloadStatus( DownloadStatus .Complete); // This must come after removing the request from the queue to avoid // re-downloading // Update batch download status if (downloadBatchRequest != null) { boolean isInProgress = false; for (DownloadRequest dr : downloadBatchRequest.getDownloadRequests()) { if (dr.getDownloadStatus() == DownloadStatus.InProgress) { isInProgress = true; break; } } downloadBatchRequest.setDownloadStatus( isInProgress ? DownloadStatus.InProgress : DownloadStatus.None); } // Close response if (responseStream != null) { responseStream.close(); responseStream = null; } // Remove download tracking _downloadRequestUrlsThatMayProceed.remove(downloadRequest.getUrl()); // Cleanup batch request? if (downloadBatchRequest == null) { downloadBatchRequestIsComplete = false; } else { downloadBatchRequestIsComplete = _downloadQueue.downloadBatchRequestIsComplete( downloadBatchRequest.getDownloadBatchRequestId()); if (downloadBatchRequestIsComplete == true) { // Remove batch request from queue _downloadQueue.remove(downloadBatchRequest.getDownloadBatchRequestId()); // Synchronize synchronized (_downloadBatchInformationLock) { // Remove batch's download information (if any) if (_downloadBatchInformationById.containsKey( downloadBatchRequest.getDownloadBatchRequestId()) == true) { _downloadBatchInformationById.remove( downloadBatchRequest.getDownloadBatchRequestId()); } } } } // Create record for completed item if (downloadRequest.getAvailableLength() >= downloadRequest.getLength()) { _completedDownloadCatalog.addCompletedDownload(downloadInformation); } // Fire downloadInformation completed event DownloadCompleted.fireEvent(new DownloadEvent(this, downloadInformation, null)); // Batch completed? if (downloadBatchInformation != null && downloadBatchRequestIsComplete == true) { // Create record for completed batch _completedDownloadCatalog.addCompletedBatchDownload(downloadBatchInformation); // Fire batch completed event? DownloadBatchCompleted.fireEvent( new DownloadEvent(this, null, downloadBatchInformation)); } } else { // The download was cancelled or paused // Reset status of download request in download queue if (downloadRequest.getDownloadStatus() == DownloadStatus.InProgress) { downloadRequest.setDownloadStatus(DownloadStatus.None); } if (downloadBatchRequest != null) { boolean isInProgress = false; for (DownloadRequest dr : downloadBatchRequest.getDownloadRequests()) { if (dr.getDownloadStatus() == DownloadStatus.InProgress) { isInProgress = true; break; } } downloadBatchRequest.setDownloadStatus( isInProgress ? DownloadStatus.InProgress : DownloadStatus.None); } } } catch (Exception e) { Log.d(LCAT, "Download thread exception " + e.toString()); // Cancel the entire batch? if (downloadBatchRequest != null) { cancel(downloadBatchRequest.getDownloadBatchRequestId()); } // Fire download failed events DownloadFailed.fireEvent(new DownloadEvent(this, downloadInformation, null)); if (downloadBatchRequest != null) { DownloadBatchFailed.fireEvent(new DownloadEvent(this, null, downloadBatchInformation)); } } finally { // Close file if necessary if (fileStream != null) { fileStream.flush(); fileStream.close(); fileStream = null; } // Close response if necessary if (responseStream != null) { responseStream.close(); responseStream = null; } } } catch (Exception e) { // Cleanup Log.d(LCAT, "Download thread exception " + e.toString()); downloadRequest.setDownloadStatus(DownloadStatus.None); if (downloadBatchRequest != null) { boolean isInProgress = false; for (DownloadRequest dr : downloadBatchRequest.getDownloadRequests()) { if (dr.getDownloadStatus() == DownloadStatus.InProgress) { isInProgress = true; break; } } downloadBatchRequest.setDownloadStatus( isInProgress ? DownloadStatus.InProgress : DownloadStatus.None); } _downloadRequestUrlsThatMayProceed.remove(downloadRequest.getUrl()); // Cancel the entire batch? if (downloadBatchRequest != null) { cancel(downloadBatchRequest.getDownloadBatchRequestId()); } // Fire download failed events DownloadFailed.fireEvent(new DownloadEvent(this, downloadInformation, null)); if (downloadBatchRequest != null) { DownloadBatchFailed.fireEvent(new DownloadEvent(this, null, downloadBatchInformation)); } } }
public void run() { // Locals Thread downloadThread; DownloadRequest request; // Initialize _status = ProgressiveDownloaderStatus.Started; // Perform initial wait try { Thread.sleep(_waitMsUponStart); Log.d(LCAT, "Download Queue Count: " + _downloadQueue.getDownloadRequestCount()); // Loop while (_timeToStopControllerThread == false) { // Has the maximum simultaneous downloads been reached? if (_downloadQueue.getDownloadRequestCount() != 0 && _downloadRequestUrlsThatMayProceed.size() < _maximumSimultaneousDownloads) { ArrayList<String> removeUrls = new ArrayList<String>(); EnumSet<NetworkTypes> network = getNetworkTypes(); for (Entry<String, EnumSet<NetworkTypes>> entry : _downloadRequestUrlsThatMayProceed.entrySet()) { if (entry.getValue().containsAll(network) == false) { removeUrls.add(entry.getKey()); } } for (String url : removeUrls) { _downloadRequestUrlsThatMayProceed.remove(url); request = _downloadQueue.getDownloadRequest(url); if (request != null) { request.setDownloadStatus(DownloadStatus.None); } } // Log.d(LCAT, "Need to download item?"); // Anything to download? request = _downloadQueue.getNextDownloadCandidate(network); if (request != null && _downloadRequestUrlsThatMayProceed.containsKey(request.getUrl()) == false) { // Log.d(LCAT, "Found item to download start download thread?"); // Initialize download thread downloadThread = new DownloadThread(request); if (request.getDownloadPriority() == DownloadPriority.Low) { downloadThread.setPriority(DOWNLOAD_THREAD_PRIORITY_LOW); } else if (request.getDownloadPriority() == DownloadPriority.High) { downloadThread.setPriority(DOWNLOAD_THREAD_PRIORITY_HIGH); } else { downloadThread.setPriority(DOWNLOAD_THREAD_PRIORITY_NORMAL); } downloadThread.setName(DOWNLOAD_THREAD_NAME_PREFACE + request.getName()); _downloadRequestUrlsThatMayProceed.put( request.getUrl(), request.getFinalPermittedNetworkTypes()); // Update status of download request if (request.getDownloadStatus() == DownloadStatus.None) { request.setDownloadStatus(DownloadStatus.InProgress); } // Begin download thread Log.d(LCAT, "Controller thread starting download thread"); downloadThread.start(); } } // Wait between loops Thread.sleep(WAIT_MS_BETWEEN_QUEUED_REQUEST_CHECKS); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }