*/
@Override
public void onReceive(Context context, Intent intent) {
- Log.i(LOG_TAG, "Received Notification:");
if (intent.getAction().equalsIgnoreCase(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
synchronized(this) {
- ++mNumDownloadsCompleted;
- Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
- intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
- Bundle extras = intent.getExtras();
- downloadIds.add(new Long(extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID)));
+ long id = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
+ Log.i(LOG_TAG, "Received Notification for download: " + id);
+ if (!downloadIds.contains(id)) {
+ ++mNumDownloadsCompleted;
+ Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
+ intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
+ downloadIds.add(id);
+
+ DownloadManager dm = (DownloadManager)context.getSystemService(
+ Context.DOWNLOAD_SERVICE);
+
+ Cursor cursor = dm.query(new Query().setFilterById(id));
+ try {
+ if (cursor.moveToFirst()) {
+ int status = cursor.getInt(cursor.getColumnIndex(
+ DownloadManager.COLUMN_STATUS));
+ Log.i(LOG_TAG, "Download status is: " + status);
+ } else {
+ fail("No status found for completed download!");
+ }
+ } finally {
+ cursor.close();
+ }
+ } else {
+ Log.i(LOG_TAG, "Notification for id: " + id + " has already been made.");
+ }
}
}
}
/**
* Helper to wait for a particular download to finish, or else a timeout to occur
*
+ * Does not wait for a receiver notification of the download.
+ *
* @param id The download id to query on (wait for)
*/
- protected void waitForDownloadOrTimeout(long id) throws TimeoutException,
+ protected void waitForDownloadOrTimeout_skipNotification(long id) throws TimeoutException,
InterruptedException {
waitForDownloadOrTimeout(id, WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
}
/**
* Helper to wait for a particular download to finish, or else a timeout to occur
*
+ * Also guarantees a notification has been posted for the download.
+ *
+ * @param id The download id to query on (wait for)
+ */
+ protected void waitForDownloadOrTimeout(long id) throws TimeoutException,
+ InterruptedException {
+ waitForDownloadOrTimeout_skipNotification(id);
+ waitForReceiverNotifications(1);
+ }
+
+ /**
+ * Helper to wait for a particular download to finish, or else a timeout to occur
+ *
+ * Also guarantees a notification has been posted for the download.
+ *
* @param id The download id to query on (wait for)
* @param poll The amount of time to wait
* @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
protected void waitForDownloadOrTimeout(long id, long poll, long timeoutMillis)
throws TimeoutException, InterruptedException {
doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
+ waitForReceiverNotifications(1);
}
/**
* Helper to wait for all downloads to finish, or else a specified timeout to occur
*
+ * Makes no guaranee that notifications have been posted for all downloads.
+ *
* @param poll The amount of time to wait
* @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
*/
/**
* Helper to wait for all downloads to finish, or else a timeout to occur, but does not throw
*
+ * Also guarantees a notification has been posted for the download.
+ *
* @param id The id of the download to query against
* @param poll The amount of time to wait
* @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
protected boolean waitForDownloadOrTimeoutNoThrow(long id, long poll, long timeoutMillis) {
try {
doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
+ waitForReceiverNotifications(1);
} catch (TimeoutException e) {
return false;
}
Cursor cursor = mDownloadManager.query(query);
try {
- // @TODO: there may be a little cleaner way to check for success, perhaps
- // via STATUS_SUCCESSFUL and/or STATUS_FAILED
- if (cursor.getCount() == 0 && mReceiver.numDownloadsCompleted() > 0) {
+ if (cursor.getCount() == 0) {
+ Log.i(LOG_TAG, "All downloads should be done...");
break;
}
currentWaitTime = timeoutWait(currentWaitTime, poll, timeoutMillis,
}
/**
+ * Convenience function to wait for just 1 notification of a download.
+ *
+ * @throws Exception if timed out while waiting
+ */
+ protected void waitForReceiverNotification() throws Exception {
+ waitForReceiverNotifications(1);
+ }
+
+ /**
+ * Synchronously waits for our receiver to receive notification for a given number of
+ * downloads.
+ *
+ * @param targetNumber The number of notifications for unique downloads to wait for; pass in
+ * -1 to not wait for notification.
+ * @throws Exception if timed out while waiting
+ */
+ protected void waitForReceiverNotifications(int targetNumber) throws TimeoutException {
+ int count = mReceiver.numDownloadsCompleted();
+ int currentWaitTime = 0;
+
+ while (count < targetNumber) {
+ Log.i(LOG_TAG, "Waiting for notification of downloads...");
+ currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
+ MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download notifications!"
+ + " Received " + count + "notifications.");
+ count = mReceiver.numDownloadsCompleted();
+ }
+ }
+
+ /**
* Synchronously waits for a file to increase in size (such as to monitor that a download is
* progressing).
*
public void testMultipleDownloads() throws Exception {
// need to be sure all current downloads have stopped first
removeAllCurrentDownloads();
- int NUM_FILES = 50;
+ int NUM_FILES = 10;
int MAX_FILE_SIZE = 500 * 1024; // 500 kb
Random r = new LoggingRng();
int size = r.nextInt(MAX_FILE_SIZE);
byte[] blobData = generateData(size, DataType.TEXT);
- Uri uri = getServerUri(DEFAULT_FILENAME);
+ Uri uri = getServerUri(DEFAULT_FILENAME + i);
Request request = new Request(uri);
- request.setTitle(String.format("%s--%d", DEFAULT_FILENAME, i));
+ request.setTitle(String.format("%s--%d", DEFAULT_FILENAME + i, i));
// Prepare the mock server with a standard response
enqueueResponse(HTTP_OK, blobData);
- Log.i(LOG_TAG, "request: " + i);
- mDownloadManager.enqueue(request);
+ long requestID = mDownloadManager.enqueue(request);
+ Log.i(LOG_TAG, "request: " + i + " -- requestID: " + requestID);
}
waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
assertEquals(NUM_FILES, mReceiver.numDownloadsCompleted());
} finally {
+ Log.i(LOG_TAG, "All download IDs: " + mReceiver.getDownloadIds().toString());
+ Log.i(LOG_TAG, "Total downloads completed: " + mReceiver.getDownloadIds().size());
cursor.close();
}
}
protected static long DOWNLOAD_500K_FILESIZE = 570927;
protected static String DOWNLOAD_1MB_FILENAME = "External1mb.apk";
protected static long DOWNLOAD_1MB_FILESIZE = 1041262;
+ protected static String DOWNLOAD_5MB_FILENAME = "External5mb.apk";
+ protected static long DOWNLOAD_5MB_FILESIZE = 5138700;
protected static String DOWNLOAD_10MB_FILENAME = "External10mb.apk";
protected static long DOWNLOAD_10MB_FILESIZE = 10258741;
* @throws Exception if unsuccessful
*/
public void initiateDownload() throws Exception {
- String filename = DOWNLOAD_1MB_FILENAME;
+ String filename = DOWNLOAD_5MB_FILENAME;
mContext.deleteFile(DOWNLOAD_STARTED_FLAG);
FileOutputStream fileOutput = mContext.openFileOutput(DOWNLOAD_STARTED_FLAG, 0);
DataOutputStream outputFile = null;
* @throws Exception if unsuccessful
*/
public void verifyFileDownloadSucceeded() throws Exception {
- String filename = DOWNLOAD_1MB_FILENAME;
- long filesize = DOWNLOAD_1MB_FILESIZE;
+ String filename = DOWNLOAD_5MB_FILENAME;
+ long filesize = DOWNLOAD_5MB_FILESIZE;
long dlRequest = -1;
boolean rebootMarkerValid = false;
DataInputStream dataInputFile = null;
int status = cursor.getInt(columnIndex);
int currentWaitTime = 0;
- // Wait until the download finishes
+ // Wait until the download finishes; don't wait for a notification b/c
+ // the download may well have been completed before the last reboot.
waitForDownloadOrTimeout(dlRequest);
Log.i(LOG_TAG, "Verifying download information...");