package com.novoda.downloadmanager.lib; import android.content.ContentResolver; import android.content.ContentValues; import android.os.SystemClock; import com.novoda.downloadmanager.notifications.DownloadNotifier; import static com.novoda.downloadmanager.lib.DownloadContract.Downloads.COLUMN_CURRENT_BYTES; class NotifierWriter implements DataWriter { private final ContentResolver contentResolver; private final DataWriter dataWriter; private final DownloadNotifier downloadNotifier; private final FileDownloadInfo downloadInfo; private final WriteChunkListener writeChunkListener; private final ContentValues values = new ContentValues(); public NotifierWriter(ContentResolver contentResolver, DataWriter dataWriter, DownloadNotifier downloadNotifier, FileDownloadInfo downloadInfo, WriteChunkListener writeChunkListener) { this.contentResolver = contentResolver; this.dataWriter = dataWriter; this.downloadNotifier = downloadNotifier; this.downloadInfo = downloadInfo; this.writeChunkListener = writeChunkListener; } @Override public DownloadTask.State write(DownloadTask.State state, byte[] buffer, int count) throws StopRequestException { DownloadTask.State localState = state; localState = dataWriter.write(localState, buffer, count); localState = reportProgress(localState); writeChunkListener.chunkWritten(downloadInfo); return localState; } private DownloadTask.State reportProgress(DownloadTask.State state) { final long now = SystemClock.elapsedRealtime(); final long sampleDelta = now - state.speedSampleStart; if (sampleDelta > 500) { final long sampleSpeed = ((state.currentBytes - state.speedSampleBytes) * 1000) / sampleDelta; if (state.speed == 0) { state.speed = sampleSpeed; } else { state.speed = ((state.speed * 3) + sampleSpeed) / 4; } // Only notify once we have a full sample window if (state.speedSampleStart != 0) { downloadNotifier.notifyDownloadSpeed(downloadInfo.getId(), state.speed); } state.speedSampleStart = now; state.speedSampleBytes = state.currentBytes; } if (state.currentBytes - state.bytesNotified > Constants.MIN_PROGRESS_STEP && now - state.timeLastNotification > Constants.MIN_PROGRESS_TIME) { updateCurrentBytesValues(state); contentResolver.update(downloadInfo.getAllDownloadsUri(), values, null, null); state.bytesNotified = state.currentBytes; state.timeLastNotification = now; } return state; } private void updateCurrentBytesValues(DownloadTask.State state) { values.put(COLUMN_CURRENT_BYTES, state.currentBytes); } public interface WriteChunkListener { void chunkWritten(FileDownloadInfo downloadInfo) throws StopRequestException; } }