diff --git a/F-Droid/res/values/strings.xml b/F-Droid/res/values/strings.xml
index 5617be28b..25e9ded61 100644
--- a/F-Droid/res/values/strings.xml
+++ b/F-Droid/res/values/strings.xml
@@ -344,6 +344,7 @@
Do you want to replace this app with the factory version?
Do you want to uninstall this app?
Download completed, tap to install
+ Download unsuccessful
New:
Provided by %1$s.
diff --git a/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloaderFromAndroid.java b/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloaderFromAndroid.java
index 8350fb226..5e06f8fc7 100644
--- a/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloaderFromAndroid.java
+++ b/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloaderFromAndroid.java
@@ -12,7 +12,9 @@ import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
+import android.util.Log;
+import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils;
import java.io.File;
@@ -68,9 +70,22 @@ public class AsyncDownloaderFromAndroid implements AsyncDownloader {
public void download() {
isCancelled = false;
+ // check if download failed
+ if (downloadManagerId >= 0) {
+ int status = validDownload(context, downloadManagerId);
+ if (status > 0) {
+ // error downloading
+ dm.remove(downloadManagerId);
+ if (listener != null) {
+ listener.onErrorDownloading(context.getString(R.string.download_error));
+ }
+ return;
+ }
+ }
+
// Check if the download is complete
if ((downloadManagerId = isDownloadComplete(context, uniqueDownloadId)) > 0) {
- // clear the notification
+ // clear the download
dm.remove(downloadManagerId);
try {
@@ -313,6 +328,35 @@ public class AsyncDownloaderFromAndroid implements AsyncDownloader {
return -1;
}
+
+ /**
+ * Check if download was valid, see issue
+ * http://code.google.com/p/android/issues/detail?id=18462
+ * From http://stackoverflow.com/questions/8937817/downloadmanager-action-download-complete-broadcast-receiver-receiving-same-downl
+ * @return 0 if successful, -1 if download doesn't exist, else the DownloadManager.ERROR_... code
+ */
+ public static int validDownload(Context context, long downloadId) {
+ //Verify if download is a success
+ DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
+ Cursor c = dm.query(new DownloadManager.Query().setFilterById(downloadId));
+
+ try {
+ if (c.moveToFirst()) {
+ int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
+
+ if (status == DownloadManager.STATUS_SUCCESSFUL) {
+ return 0; //Download is valid, celebrate
+ } else {
+ return c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON));
+ }
+ }
+ } finally {
+ c.close();
+ }
+
+ return -1; // download doesn't exist
+ }
+
/**
* Broadcast receiver to listen for ACTION_DOWNLOAD_COMPLETE broadcasts
*/
diff --git a/F-Droid/src/org/fdroid/fdroid/receiver/DownloadManagerReceiver.java b/F-Droid/src/org/fdroid/fdroid/receiver/DownloadManagerReceiver.java
index 3c50edf00..52aa51b1a 100644
--- a/F-Droid/src/org/fdroid/fdroid/receiver/DownloadManagerReceiver.java
+++ b/F-Droid/src/org/fdroid/fdroid/receiver/DownloadManagerReceiver.java
@@ -1,5 +1,6 @@
package org.fdroid.fdroid.receiver;
+import android.annotation.TargetApi;
import android.app.DownloadManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -7,16 +8,20 @@ import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.database.Cursor;
+import android.support.annotation.StringRes;
import android.support.v4.app.NotificationCompat;
import org.fdroid.fdroid.AppDetails;
import org.fdroid.fdroid.R;
+import org.fdroid.fdroid.net.AsyncDownloader;
import org.fdroid.fdroid.net.AsyncDownloaderFromAndroid;
/**
* Receive notifications from the Android DownloadManager and pass them onto the
* AppDetails activity
*/
+@TargetApi(9)
public class DownloadManagerReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -30,28 +35,18 @@ public class DownloadManagerReceiver extends BroadcastReceiver {
}
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
- // show a notification the user can click to install the app
- Intent appDetails = new Intent(context, AppDetails.class);
- appDetails.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- appDetails.setAction(intent.getAction());
- appDetails.putExtras(intent.getExtras());
- appDetails.putExtra(AppDetails.EXTRA_APPID, appId);
+ int status = AsyncDownloaderFromAndroid.validDownload(context, downloadId);
+ if (status == 0) {
+ // successful download
+ showNotification(context, appId, intent, downloadId, R.string.tap_to_install);
+ } else {
+ // download failed!
+ showNotification(context, appId, intent, downloadId, R.string.download_error);
- PendingIntent pi = PendingIntent.getActivity(
- context, 1, appDetails, PendingIntent.FLAG_ONE_SHOT);
-
- // launch LocalRepoActivity if the user selects this notification
- String downloadTitle = AsyncDownloaderFromAndroid.getDownloadTitle(context, downloadId);
- Notification notif = new NotificationCompat.Builder(context)
- .setContentTitle(downloadTitle)
- .setContentText(context.getString(R.string.tap_to_install))
- .setSmallIcon(R.drawable.ic_stat_notify)
- .setContentIntent(pi)
- .setAutoCancel(true)
- .build();
-
- NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- nm.notify((int)downloadId, notif);
+ // clear the download to allow user to download again
+ DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
+ dm.remove(downloadId);
+ }
} else if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(intent.getAction())) {
// pass the notification click onto the AppDetails screen and let it handle it
Intent appDetails = new Intent(context, AppDetails.class);
@@ -62,4 +57,30 @@ public class DownloadManagerReceiver extends BroadcastReceiver {
context.startActivity(appDetails);
}
}
+
+ private void showNotification(Context context, String appId, Intent intent, long downloadId,
+ @StringRes int messageResId) {
+ // show a notification the user can click to install the app
+ Intent appDetails = new Intent(context, AppDetails.class);
+ appDetails.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ appDetails.setAction(intent.getAction());
+ appDetails.putExtras(intent.getExtras());
+ appDetails.putExtra(AppDetails.EXTRA_APPID, appId);
+
+ PendingIntent pi = PendingIntent.getActivity(
+ context, 1, appDetails, PendingIntent.FLAG_ONE_SHOT);
+
+ // launch LocalRepoActivity if the user selects this notification
+ String downloadTitle = AsyncDownloaderFromAndroid.getDownloadTitle(context, downloadId);
+ Notification notif = new NotificationCompat.Builder(context)
+ .setContentTitle(downloadTitle)
+ .setContentText(context.getString(messageResId))
+ .setSmallIcon(R.drawable.ic_stat_notify)
+ .setContentIntent(pi)
+ .setAutoCancel(true)
+ .build();
+
+ NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notify((int)downloadId, notif);
+ }
}