Added 'title' and 'reasonDetailed' attributes to DownloadStatus

This commit is contained in:
daniel oeh
2012-09-20 19:03:21 +02:00
parent f78bb0be13
commit 82db128a66
10 changed files with 153 additions and 87 deletions

View File

@ -16,43 +16,57 @@ public class DownloadStatus {
return completionDate; return completionDate;
} }
// ----------------------------------- ATTRIBUTES STORED IN DB
/** Unique id for storing the object in database. */ /** Unique id for storing the object in database. */
protected long id; protected long id;
/**
* A human-readable string which is shown to the user so that he can
* identify the download. Should be the title of the item/feed/media or the
* URL if the download has no other title.
*/
protected String title;
protected int reason;
/**
* A message which can be presented to the user to give more information.
* Should be null if Download was successful.
*/
protected String reasonDetailed;
protected boolean successful;
protected Date completionDate;
/** Used by DownloadService to check if the status has been updated. */ // ------------------------------------ NOT STORED IN DB
protected volatile boolean updateAvailable;
protected FeedFile feedfile; protected FeedFile feedfile;
protected int progressPercent; protected int progressPercent;
protected long soFar; protected long soFar;
protected long size; protected long size;
protected int statusMsg; protected int statusMsg;
protected int reason;
protected boolean successful;
protected boolean done; protected boolean done;
protected Date completionDate;
public DownloadStatus(FeedFile feedfile) { public DownloadStatus(FeedFile feedfile) {
this.feedfile = feedfile; this.feedfile = feedfile;
} }
/** Constructor for restoring Download status entries from DB. */ /** Constructor for restoring Download status entries from DB. */
public DownloadStatus(long id, FeedFile feedfile, boolean successful, public DownloadStatus(long id, String title, FeedFile feedfile,
int reason, Date completionDate) { boolean successful, int reason, Date completionDate,
this.id = id; String reasonDetailed) {
this.feedfile = feedfile;
progressPercent = 100; progressPercent = 100;
soFar = 0; soFar = 0;
size = 0; size = 0;
this.id = id;
this.title = title;
this.done = true;
this.feedfile = feedfile;
this.reason = reason; this.reason = reason;
this.successful = successful; this.successful = successful;
this.done = true;
this.completionDate = completionDate; this.completionDate = completionDate;
} }
/** Constructor for creating new completed downloads. */ /** Constructor for creating new completed downloads. */
public DownloadStatus(FeedFile feedfile, int reason, boolean successful) { public DownloadStatus(FeedFile feedfile, String title, int reason,
this(0, feedfile, successful, reason, new Date()); boolean successful, String reasonDetailed) {
this(0, title, feedfile, successful, reason, new Date(), reasonDetailed);
} }
public FeedFile getFeedFile() { public FeedFile getFeedFile() {
@ -131,12 +145,20 @@ public class DownloadStatus {
this.completionDate = completionDate; this.completionDate = completionDate;
} }
public boolean isUpdateAvailable() { public String getReasonDetailed() {
return updateAvailable; return reasonDetailed;
} }
public void setUpdateAvailable(boolean updateAvailable) { public void setReasonDetailed(String reasonDetailed) {
this.updateAvailable = updateAvailable; this.reasonDetailed = reasonDetailed;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
} }
} }

View File

@ -134,6 +134,15 @@ public class Feed extends FeedFile {
} }
} }
@Override
public String getHumanReadableIdentifier() {
if (title != null) {
return title;
} else {
return download_url;
}
}
public String getTitle() { public String getTitle() {
return title; return title;
} }

View File

@ -17,6 +17,12 @@ public abstract class FeedFile extends FeedComponent {
this(null, null, false); this(null, null, false);
} }
/**
* Should return a non-null, human-readable String so that the item can be
* identified by the user. Can be title, download-url, etc.
*/
public abstract String getHumanReadableIdentifier();
public String getFile_url() { public String getFile_url() {
return file_url; return file_url;
} }

View File

@ -17,6 +17,15 @@ public class FeedImage extends FeedFile {
this.title = title; this.title = title;
} }
@Override
public String getHumanReadableIdentifier() {
if (feed != null && feed.getTitle() != null) {
return feed.getTitle();
} else {
return download_url;
}
}
public FeedImage() { public FeedImage() {
super(); super();
} }

View File

@ -950,32 +950,34 @@ public class FeedManager {
if (logCursor.moveToFirst()) { if (logCursor.moveToFirst()) {
do { do {
long id = logCursor.getLong(PodDBAdapter.KEY_ID_INDEX); long id = logCursor.getLong(PodDBAdapter.KEY_ID_INDEX);
FeedFile feedfile = null;
long feedfileId = logCursor long feedfileId = logCursor
.getLong(PodDBAdapter.KEY_FEEDFILE_INDEX); .getLong(PodDBAdapter.KEY_FEEDFILE_INDEX);
int feedfileType = logCursor if (feedfileId != 0) {
.getInt(PodDBAdapter.KEY_FEEDFILETYPE_INDEX); int feedfileType = logCursor
FeedFile feedfile = null; .getInt(PodDBAdapter.KEY_FEEDFILETYPE_INDEX);
switch (feedfileType) { switch (feedfileType) {
case PodDBAdapter.FEEDFILETYPE_FEED: case PodDBAdapter.FEEDFILETYPE_FEED:
feedfile = getFeed(feedfileId); feedfile = getFeed(feedfileId);
break; break;
case PodDBAdapter.FEEDFILETYPE_FEEDIMAGE: case PodDBAdapter.FEEDFILETYPE_FEEDIMAGE:
feedfile = getFeedImage(feedfileId); feedfile = getFeedImage(feedfileId);
break; break;
case PodDBAdapter.FEEDFILETYPE_FEEDMEDIA: case PodDBAdapter.FEEDFILETYPE_FEEDMEDIA:
feedfile = getFeedMedia(feedfileId); feedfile = getFeedMedia(feedfileId);
} }
if (feedfile != null) { // otherwise ignore status
boolean successful = logCursor
.getInt(PodDBAdapter.KEY_SUCCESSFUL_INDEX) > 0;
int reason = logCursor
.getInt(PodDBAdapter.KEY_REASON_INDEX);
Date completionDate = new Date(
logCursor
.getLong(PodDBAdapter.KEY_COMPLETION_DATE_INDEX));
downloadLog.add(new DownloadStatus(id, feedfile,
successful, reason, completionDate));
} }
boolean successful = logCursor
.getInt(PodDBAdapter.KEY_SUCCESSFUL_INDEX) > 0;
int reason = logCursor.getInt(PodDBAdapter.KEY_REASON_INDEX);
String reasonDetailed = logCursor.getString(PodDBAdapter.KEY_REASON_DETAILED_INDEX);
String title = logCursor.getString(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE_INDEX);
Date completionDate = new Date(
logCursor
.getLong(PodDBAdapter.KEY_COMPLETION_DATE_INDEX));
downloadLog.add(new DownloadStatus(id, title, feedfile, successful,
reason, completionDate, reasonDetailed));
} while (logCursor.moveToNext()); } while (logCursor.moveToNext());
} }

View File

@ -1,21 +1,23 @@
package de.danoeh.antennapod.feed; package de.danoeh.antennapod.feed;
public class FeedMedia extends FeedFile{ public class FeedMedia extends FeedFile {
private int duration; private int duration;
private int position; // Current position in file private int position; // Current position in file
private long size; // File size in Byte private long size; // File size in Byte
private String mime_type; private String mime_type;
private FeedItem item; private FeedItem item;
public FeedMedia(FeedItem i, String download_url, long size, String mime_type) { public FeedMedia(FeedItem i, String download_url, long size,
String mime_type) {
super(null, download_url, false); super(null, download_url, false);
this.item = i; this.item = i;
this.size = size; this.size = size;
this.mime_type = mime_type; this.mime_type = mime_type;
} }
public FeedMedia(long id, FeedItem item, int duration, int position, long size, String mime_type, public FeedMedia(long id, FeedItem item, int duration, int position,
String file_url, String download_url, boolean downloaded) { long size, String mime_type, String file_url, String download_url,
boolean downloaded) {
super(file_url, download_url, downloaded); super(file_url, download_url, downloaded);
this.id = id; this.id = id;
this.item = item; this.item = item;
@ -24,15 +26,22 @@ public class FeedMedia extends FeedFile{
this.size = size; this.size = size;
this.mime_type = mime_type; this.mime_type = mime_type;
} }
public FeedMedia(long id,FeedItem item) { public FeedMedia(long id, FeedItem item) {
super(); super();
this.id = id; this.id = id;
this.item = item; this.item = item;
} }
@Override
public String getHumanReadableIdentifier() {
if (item != null && item.getTitle() != null) {
return item.getTitle();
} else {
return download_url;
}
}
public int getDuration() { public int getDuration() {
return duration; return duration;
} }
@ -72,10 +81,5 @@ public class FeedMedia extends FeedFile{
public void setItem(FeedItem item) { public void setItem(FeedItem item) {
this.item = item; this.item = item;
} }
} }

View File

@ -101,7 +101,6 @@ public class DownloadService extends Service {
private NotificationCompat.Builder notificationBuilder; private NotificationCompat.Builder notificationBuilder;
private int NOTIFICATION_ID = 2; private int NOTIFICATION_ID = 2;
private int REPORT_ID = 3; private int REPORT_ID = 3;
private List<Downloader> downloads; private List<Downloader> downloads;
@ -543,6 +542,7 @@ public class DownloadService extends Service {
public void run() { public void run() {
Feed savedFeed = null; Feed savedFeed = null;
reason = 0; reason = 0;
String reasonDetailed = null;
successful = true; successful = true;
FeedManager manager = FeedManager.getInstance(); FeedManager manager = FeedManager.getInstance();
FeedHandler handler = new FeedHandler(); FeedHandler handler = new FeedHandler();
@ -571,22 +571,27 @@ public class DownloadService extends Service {
successful = false; successful = false;
e.printStackTrace(); e.printStackTrace();
reason = DownloadError.ERROR_PARSER_EXCEPTION; reason = DownloadError.ERROR_PARSER_EXCEPTION;
reasonDetailed = e.getMessage();
} catch (IOException e) { } catch (IOException e) {
successful = false; successful = false;
e.printStackTrace(); e.printStackTrace();
reason = DownloadError.ERROR_PARSER_EXCEPTION; reason = DownloadError.ERROR_PARSER_EXCEPTION;
reasonDetailed = e.getMessage();
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
successful = false; successful = false;
e.printStackTrace(); e.printStackTrace();
reason = DownloadError.ERROR_PARSER_EXCEPTION; reason = DownloadError.ERROR_PARSER_EXCEPTION;
reasonDetailed = e.getMessage();
} catch (UnsupportedFeedtypeException e) { } catch (UnsupportedFeedtypeException e) {
e.printStackTrace(); e.printStackTrace();
successful = false; successful = false;
reason = DownloadError.ERROR_UNSUPPORTED_TYPE; reason = DownloadError.ERROR_UNSUPPORTED_TYPE;
reasonDetailed = e.getMessage();
} catch (InvalidFeedException e) { } catch (InvalidFeedException e) {
e.printStackTrace(); e.printStackTrace();
successful = false; successful = false;
reason = DownloadError.ERROR_PARSER_EXCEPTION; reason = DownloadError.ERROR_PARSER_EXCEPTION;
reasonDetailed = e.getMessage();
} }
// cleanup(); // cleanup();
@ -594,7 +599,9 @@ public class DownloadService extends Service {
savedFeed = feed; savedFeed = feed;
} }
saveDownloadStatus(new DownloadStatus(savedFeed, reason, successful)); saveDownloadStatus(new DownloadStatus(savedFeed,
savedFeed.getHumanReadableIdentifier(), reason, successful,
reasonDetailed));
sendDownloadHandledIntent(DOWNLOAD_TYPE_FEED); sendDownloadHandledIntent(DOWNLOAD_TYPE_FEED);
downloadsBeingHandled -= 1; downloadsBeingHandled -= 1;
queryDownloads(); queryDownloads();
@ -684,7 +691,7 @@ public class DownloadService extends Service {
} finally { } finally {
mediaplayer.release(); mediaplayer.release();
} }
saveDownloadStatus(status); saveDownloadStatus(status);
sendDownloadHandledIntent(DOWNLOAD_TYPE_MEDIA); sendDownloadHandledIntent(DOWNLOAD_TYPE_MEDIA);
manager.setFeedMedia(DownloadService.this, media); manager.setFeedMedia(DownloadService.this, media);

View File

@ -43,10 +43,6 @@ public abstract class Downloader extends Thread {
} }
} }
protected void publishProgress() {
status.setUpdateAvailable(true);
}
protected abstract void download(); protected abstract void download();
@Override @Override

View File

@ -35,7 +35,6 @@ public class HttpDownloader extends Downloader {
OutputStream out = null; OutputStream out = null;
try { try {
status.setStatusMsg(R.string.download_pending); status.setStatusMsg(R.string.download_pending);
publishProgress();
URL url = new URL(status.getFeedFile().getDownload_url()); URL url = new URL(status.getFeedFile().getDownload_url());
connection = (HttpURLConnection) url.openConnection(); connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(CONNECTION_TIMEOUT); connection.setConnectTimeout(CONNECTION_TIMEOUT);
@ -66,7 +65,6 @@ public class HttpDownloader extends Downloader {
Log.d(TAG, "Free space is " + freeSpace); Log.d(TAG, "Free space is " + freeSpace);
if (status.getSize() == DownloadStatus.SIZE_UNKNOWN if (status.getSize() == DownloadStatus.SIZE_UNKNOWN
|| status.getSize() <= freeSpace) { || status.getSize() <= freeSpace) {
publishProgress();
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Starting download"); Log.d(TAG, "Starting download");
while (!cancelled && (count = in.read(buffer)) != -1) { while (!cancelled && (count = in.read(buffer)) != -1) {
@ -81,23 +79,23 @@ public class HttpDownloader extends Downloader {
onSuccess(); onSuccess();
} }
} else { } else {
onFail(DownloadError.ERROR_NOT_ENOUGH_SPACE); onFail(DownloadError.ERROR_NOT_ENOUGH_SPACE, null);
} }
} else { } else {
onFail(DownloadError.ERROR_FILE_EXISTS); onFail(DownloadError.ERROR_FILE_EXISTS, null);
} }
} else { } else {
onFail(DownloadError.ERROR_DEVICE_NOT_FOUND); onFail(DownloadError.ERROR_DEVICE_NOT_FOUND, null);
} }
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
e.printStackTrace(); e.printStackTrace();
onFail(DownloadError.ERROR_MALFORMED_URL); onFail(DownloadError.ERROR_MALFORMED_URL, e.getMessage());
} catch (SocketTimeoutException e) { } catch (SocketTimeoutException e) {
e.printStackTrace(); e.printStackTrace();
onFail(DownloadError.ERROR_CONNECTION_ERROR); onFail(DownloadError.ERROR_CONNECTION_ERROR, e.getMessage());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
onFail(DownloadError.ERROR_IO_ERROR); onFail(DownloadError.ERROR_IO_ERROR, e.getMessage());
} finally { } finally {
if (connection != null) { if (connection != null) {
connection.disconnect(); connection.disconnect();
@ -119,11 +117,12 @@ public class HttpDownloader extends Downloader {
status.setDone(true); status.setDone(true);
} }
private void onFail(int reason) { private void onFail(int reason, String reasonDetailed) {
if (AppConfig.DEBUG) { if (AppConfig.DEBUG) {
Log.d(TAG, "Download failed"); Log.d(TAG, "Download failed");
} }
status.setReason(reason); status.setReason(reason);
status.setReasonDetailed(reasonDetailed);
status.setDone(true); status.setDone(true);
status.setSuccessful(false); status.setSuccessful(false);
} }

View File

@ -25,7 +25,7 @@ import de.danoeh.antennapod.feed.SimpleChapter;
* */ * */
public class PodDBAdapter { public class PodDBAdapter {
private static final String TAG = "PodDBAdapter"; private static final String TAG = "PodDBAdapter";
private static final int DATABASE_VERSION = 5; private static final int DATABASE_VERSION = 6;
private static final String DATABASE_NAME = "Antennapod.db"; private static final String DATABASE_NAME = "Antennapod.db";
/** Maximum number of arguments for IN-operator. */ /** Maximum number of arguments for IN-operator. */
@ -67,6 +67,8 @@ public class PodDBAdapter {
public static final int KEY_REASON_INDEX = 3; public static final int KEY_REASON_INDEX = 3;
public static final int KEY_SUCCESSFUL_INDEX = 4; public static final int KEY_SUCCESSFUL_INDEX = 4;
public static final int KEY_COMPLETION_DATE_INDEX = 5; public static final int KEY_COMPLETION_DATE_INDEX = 5;
public static final int KEY_REASON_DETAILED_INDEX = 6;
public static final int KEY_DOWNLOADSTATUS_TITLE_INDEX = 7;
// --------- Queue indices // --------- Queue indices
public static final int KEY_FEEDITEM_INDEX = 1; public static final int KEY_FEEDITEM_INDEX = 1;
public static final int KEY_QUEUE_FEED_INDEX = 2; public static final int KEY_QUEUE_FEED_INDEX = 2;
@ -109,6 +111,8 @@ public class PodDBAdapter {
public static final String KEY_TYPE = "type"; public static final String KEY_TYPE = "type";
public static final String KEY_ITEM_IDENTIFIER = "item_identifier"; public static final String KEY_ITEM_IDENTIFIER = "item_identifier";
public static final String KEY_FEED_IDENTIFIER = "feed_identifier"; public static final String KEY_FEED_IDENTIFIER = "feed_identifier";
public static final String KEY_REASON_DETAILED = "reason_detailed";
public static final String KEY_DOWNLOADSTATUS_TITLE = "title";
// Table names // Table names
public static final String TABLE_NAME_FEEDS = "Feeds"; public static final String TABLE_NAME_FEEDS = "Feeds";
@ -156,7 +160,8 @@ public class PodDBAdapter {
+ TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE
+ " INTEGER," + KEY_FEEDFILETYPE + " INTEGER," + KEY_REASON + " INTEGER," + KEY_FEEDFILETYPE + " INTEGER," + KEY_REASON
+ " INTEGER," + KEY_SUCCESSFUL + " INTEGER," + KEY_COMPLETION_DATE + " INTEGER," + KEY_SUCCESSFUL + " INTEGER," + KEY_COMPLETION_DATE
+ " INTEGER)"; + " INTEGER," + KEY_REASON_DETAILED + " TEXT,"
+ KEY_DOWNLOADSTATUS_TITLE + " TEXT)";
private static final String CREATE_TABLE_QUEUE = "CREATE TABLE " private static final String CREATE_TABLE_QUEUE = "CREATE TABLE "
+ TABLE_NAME_QUEUE + "(" + KEY_ID + " INTEGER PRIMARY KEY," + TABLE_NAME_QUEUE + "(" + KEY_ID + " INTEGER PRIMARY KEY,"
@ -368,9 +373,8 @@ public class PodDBAdapter {
* Inserts or updates a download status. * Inserts or updates a download status.
* */ * */
public long setDownloadStatus(DownloadStatus status) { public long setDownloadStatus(DownloadStatus status) {
// Don't save failed downloads ContentValues values = new ContentValues();
if (status.getFeedFile() != null) { if (status.getFeedFile() != null) {
ContentValues values = new ContentValues();
values.put(KEY_FEEDFILE, status.getFeedFile().getId()); values.put(KEY_FEEDFILE, status.getFeedFile().getId());
if (status.getFeedFile().getClass() == Feed.class) { if (status.getFeedFile().getClass() == Feed.class) {
values.put(KEY_FEEDFILETYPE, FEEDFILETYPE_FEED); values.put(KEY_FEEDFILETYPE, FEEDFILETYPE_FEED);
@ -379,18 +383,19 @@ public class PodDBAdapter {
} else if (status.getFeedFile().getClass() == FeedMedia.class) { } else if (status.getFeedFile().getClass() == FeedMedia.class) {
values.put(KEY_FEEDFILETYPE, FEEDFILETYPE_FEEDMEDIA); values.put(KEY_FEEDFILETYPE, FEEDFILETYPE_FEEDMEDIA);
} }
values.put(KEY_REASON, status.getReason());
values.put(KEY_SUCCESSFUL, status.isSuccessful());
values.put(KEY_COMPLETION_DATE, status.getCompletionDate()
.getTime());
if (status.getId() == 0) {
status.setId(db.insert(TABLE_NAME_DOWNLOAD_LOG, null, values));
} else {
db.update(TABLE_NAME_DOWNLOAD_LOG, values, KEY_ID + "=?",
new String[] { String.valueOf(status.getId()) });
}
} }
values.put(KEY_REASON, status.getReason());
values.put(KEY_SUCCESSFUL, status.isSuccessful());
values.put(KEY_COMPLETION_DATE, status.getCompletionDate().getTime());
values.put(KEY_REASON_DETAILED, status.getReasonDetailed());
values.put(KEY_DOWNLOADSTATUS_TITLE, status.getTitle());
if (status.getId() == 0) {
status.setId(db.insert(TABLE_NAME_DOWNLOAD_LOG, null, values));
} else {
db.update(TABLE_NAME_DOWNLOAD_LOG, values, KEY_ID + "=?",
new String[] { String.valueOf(status.getId()) });
}
return status.getId(); return status.getId();
} }
@ -570,7 +575,8 @@ public class PodDBAdapter {
} else { } else {
neededLength = elementsLeft; neededLength = elementsLeft;
parts = Arrays.copyOfRange(mediaIds, i parts = Arrays.copyOfRange(mediaIds, i
* IN_OPERATOR_MAXIMUM, (i * IN_OPERATOR_MAXIMUM) + neededLength); * IN_OPERATOR_MAXIMUM, (i * IN_OPERATOR_MAXIMUM)
+ neededLength);
} }
cursors[i] = db.rawQuery("SELECT * FROM " cursors[i] = db.rawQuery("SELECT * FROM "
@ -666,6 +672,12 @@ public class PodDBAdapter {
db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS + " ADD COLUMN " db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS + " ADD COLUMN "
+ KEY_FEED_IDENTIFIER + " TEXT"); + KEY_FEED_IDENTIFIER + " TEXT");
} }
if (oldVersion <= 5) {
db.execSQL("ALTER TABLE " + TABLE_NAME_DOWNLOAD_LOG
+ " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT");
db.execSQL("ALTER TABLE " + TABLE_NAME_DOWNLOAD_LOG
+ " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT");
}
} }
} }