/// <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; }
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)); } } }