diff options
Diffstat (limited to 'core/src/main')
10 files changed, 291 insertions, 100 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java index b6ece6dc8..4f2d5b204 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java @@ -6,8 +6,12 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.MediaMetadataRetriever; import android.net.Uri; +import android.text.TextUtils; import android.util.Log; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Response; import com.squareup.picasso.Cache; import com.squareup.picasso.LruCache; import com.squareup.picasso.OkHttpDownloader; @@ -22,13 +26,18 @@ import org.apache.commons.lang3.StringUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import de.danoeh.antennapod.core.service.download.HttpDownloader; +import de.danoeh.antennapod.core.storage.DBReader; + /** * Provides access to Picasso instances. */ public class PicassoProvider { + private static final String TAG = "PicassoProvider"; private static final boolean DEBUG = false; @@ -56,10 +65,12 @@ public class PicassoProvider { if (picassoSetup) { return; } + OkHttpClient client = new OkHttpClient(); + client.interceptors().add(new BasicAuthenticationInterceptor(appContext)); Picasso picasso = new Picasso.Builder(appContext) .indicatorsEnabled(DEBUG) .loggingEnabled(DEBUG) - .downloader(new OkHttpDownloader(appContext)) + .downloader(new OkHttpDownloader(client)) .addRequestHandler(new MediaRequestHandler(appContext)) .executor(getExecutorService()) .memoryCache(getMemoryCache(appContext)) @@ -75,6 +86,48 @@ public class PicassoProvider { picassoSetup = true; } + private static class BasicAuthenticationInterceptor implements Interceptor { + + private final Context context; + + public BasicAuthenticationInterceptor(Context context) { + this.context = context; + } + + @Override + public Response intercept(Chain chain) throws IOException { + com.squareup.okhttp.Request request = chain.request(); + String url = request.urlString(); + String authentication = DBReader.getImageAuthentication(context, url); + + if(TextUtils.isEmpty(authentication)) { + Log.d(TAG, "no credentials for '" + url + "'"); + return chain.proceed(request); + } + + // add authentication + String[] auth = authentication.split(":"); + String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1"); + com.squareup.okhttp.Request newRequest = request + .newBuilder() + .addHeader("Authorization", credentials) + .build(); + Log.d(TAG, "Basic authentication with ISO-8859-1 encoding"); + Response response = chain.proceed(newRequest); + if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { + credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "UTF-8"); + newRequest = request + .newBuilder() + .addHeader("Authorization", credentials) + .build(); + Log.d(TAG, "Basic authentication with UTF-8 encoding"); + return chain.proceed(newRequest); + } else { + return response; + } + } + } + private static class MediaRequestHandler extends RequestHandler { final Context context; @@ -90,7 +143,7 @@ public class PicassoProvider { } @Override - public Result load(Request data) throws IOException { + public Result load(Request data, int networkPolicy) throws IOException { Bitmap bitmap = null; MediaMetadataRetriever mmr = null; try { @@ -109,13 +162,7 @@ public class PicassoProvider { } if (bitmap == null) { - // check for fallback Uri - String fallbackParam = data.uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK); - - if (fallbackParam != null) { - Uri fallback = Uri.parse(fallbackParam); - bitmap = decodeStreamFromFile(data, fallback); - } + Log.wtf(TAG, "THIS SHOULD NEVER EVER HAPPEN!!"); } return new Result(bitmap, Picasso.LoadedFrom.DISK); diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 4fd7a184c..b74875175 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -315,10 +315,10 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr @Override public Uri getImageUri() { - if (hasItemImageDownloaded()) { - return image.getImageUri(); - } else if (hasMedia()) { + if(media.hasEmbeddedPicture()) { return media.getImageUri(); + } else if (hasItemImageDownloaded()) { + return image.getImageUri(); } else if (feed != null) { return feed.getImageUri(); } else { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 93f826894..3dda291fa 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -2,9 +2,11 @@ package de.danoeh.antennapod.core.feed; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.media.MediaMetadataRetriever; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; import java.util.Date; import java.util.List; @@ -34,6 +36,7 @@ public class FeedMedia extends FeedFile implements Playable { private String mime_type; private volatile FeedItem item; private Date playbackCompletionDate; + private boolean hasEmbeddedPicture; /* Used for loading item when restoring from parcel. */ private long itemID; @@ -50,6 +53,7 @@ public class FeedMedia extends FeedFile implements Playable { long size, String mime_type, String file_url, String download_url, boolean downloaded, Date playbackCompletionDate, int played_duration) { super(file_url, download_url, downloaded); + checkEmbeddedPicture(); this.id = id; this.item = item; this.duration = duration; @@ -61,12 +65,6 @@ public class FeedMedia extends FeedFile implements Playable { ? null : (Date) playbackCompletionDate.clone(); } - public FeedMedia(long id, FeedItem item) { - super(); - this.id = id; - this.item = item; - } - @Override public String getHumanReadableIdentifier() { if (item != null && item.getTitle() != null) { @@ -227,18 +225,16 @@ public class FeedMedia extends FeedFile implements Playable { return (this.position > 0); } - public FeedImage getImage() { - if (item != null) { - return (item.hasItemImageDownloaded()) ? item.getImage() : item.getFeed().getImage(); - } - return null; - } - @Override public int describeContents() { return 0; } + public boolean hasEmbeddedPicture() { + Log.d(TAG, "hasEmbeddedPicture() -> " + hasEmbeddedPicture); + return this.hasEmbeddedPicture; + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(id); @@ -415,28 +411,46 @@ public class FeedMedia extends FeedFile implements Playable { @Override public Uri getImageUri() { - final Uri feedImgUri = getFeedImageUri(); - - if (localFileAvailable()) { + if (hasEmbeddedPicture) { Uri.Builder builder = new Uri.Builder(); - builder.scheme(SCHEME_MEDIA) - .encodedPath(getLocalMediaUrl()); - if (feedImgUri != null) { - builder.appendQueryParameter(PARAM_FALLBACK, feedImgUri.toString()); - } + builder.scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()); return builder.build(); - } else if (item.hasItemImageDownloaded()) { - return item.getImage().getImageUri(); } else { - return feedImgUri; + return item.getImageUri(); } } - private Uri getFeedImageUri() { - if (item != null && item.getFeed() != null) { - return item.getFeed().getImageUri(); - } else { - return null; + @Override + public void setDownloaded(boolean downloaded) { + super.setDownloaded(downloaded); + checkEmbeddedPicture(); + } + + @Override + public void setFile_url(String file_url) { + super.setFile_url(file_url); + checkEmbeddedPicture(); + } + + private void checkEmbeddedPicture() { + Log.d(TAG, "checkEmbeddedPicture()"); + if (!localFileAvailable()) { + hasEmbeddedPicture = false; + return; + } + MediaMetadataRetriever mmr = new MediaMetadataRetriever(); + try { + mmr.setDataSource(getLocalMediaUrl()); + byte[] image = mmr.getEmbeddedPicture(); + if(image != null) { + hasEmbeddedPicture = true; + } + else { + hasEmbeddedPicture = false; + } + } catch (Exception e) { + e.printStackTrace(); + hasEmbeddedPicture = false; } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java index db242c3bc..23d89a3a3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java @@ -726,7 +726,12 @@ public class GpodnetService { Validate.notNull(body); ByteArrayOutputStream outputStream; - int contentLength = (int) body.contentLength(); + int contentLength = 0; + try { + contentLength = (int) body.contentLength(); + } catch (IOException ignore) { + // ignore + } if (contentLength > 0) { outputStream = new ByteArrayOutputStream(contentLength); } else { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index d5f17c099..4e40fbe1e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -520,9 +520,7 @@ public class DownloadService extends Service { /** * Creates a notification at the end of the service lifecycle to notify the * user about the number of completed downloads. A report will only be - * created if the number of successfully downloaded feeds is bigger than 1 - * or if there is at least one failed download which is not an image or if - * there is at least one downloaded media file. + * created if there is at least one failed download excluding images */ private void updateReport() { // check if report should be created @@ -550,16 +548,16 @@ public class DownloadService extends Service { .setTicker( getString(R.string.download_report_title)) .setContentTitle( - getString(R.string.download_report_title)) + getString(R.string.download_report_content_title)) .setContentText( String.format( getString(R.string.download_report_content), successfulDownloads, failedDownloads) ) - .setSmallIcon(R.drawable.stat_notify_sync) + .setSmallIcon(R.drawable.stat_notify_sync_error) .setLargeIcon( BitmapFactory.decodeResource(getResources(), - R.drawable.stat_notify_sync) + R.drawable.stat_notify_sync_error) ) .setContentIntent( ClientConfig.downloadServiceCallbacks.getReportNotificationContentIntent(this) @@ -939,6 +937,13 @@ public class DownloadService extends Service { if (successful) { + // we create a 'successful' download log if the feed's last refresh failed + List<DownloadStatus> log = DBReader.getFeedDownloadLog(DownloadService.this, feed); + if(log.size() > 0 && log.get(0).isSuccessful() == false) { + saveDownloadStatus(new DownloadStatus(feed, + feed.getHumanReadableIdentifier(), DownloadError.SUCCESS, successful, + reasonDetailed)); + } return Pair.create(request, result); } else { numberOfDownloads.decrementAndGet(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 7abb6df5e..ac0fe8036 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -2,7 +2,6 @@ package de.danoeh.antennapod.core.service.download; import android.util.Log; -import com.squareup.okhttp.Credentials; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; @@ -18,19 +17,20 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URI; import java.net.UnknownHostException; import java.util.Date; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.URIUtil; +import okio.ByteString; public class HttpDownloader extends Downloader { private static final String TAG = "HttpDownloader"; @@ -81,11 +81,12 @@ public class HttpDownloader extends Downloader { if (userInfo != null) { String[] parts = userInfo.split(":"); if (parts.length == 2) { - String credentials = Credentials.basic(parts[0], parts[1]); + String credentials = encodeCredentials(parts[0], parts[1], "ISO-8859-1"); httpReq.header("Authorization", credentials); } } else if (!StringUtils.isEmpty(request.getUsername()) && request.getPassword() != null) { - String credentials = Credentials.basic(request.getUsername(), request.getPassword()); + String credentials = encodeCredentials(request.getUsername(), request.getPassword(), + "ISO-8859-1"); httpReq.header("Authorization", credentials); } @@ -99,13 +100,29 @@ public class HttpDownloader extends Downloader { Response response = httpClient.newCall(httpReq.build()).execute(); responseBody = response.body(); - String contentEncodingHeader = response.header("Content-Encoding"); - - final boolean isGzip = StringUtils.equalsIgnoreCase(contentEncodingHeader, "gzip"); - - if (BuildConfig.DEBUG) - Log.d(TAG, "Response code is " + response.code()); + boolean isGzip = StringUtils.equalsIgnoreCase(contentEncodingHeader, "gzip"); + + Log.d(TAG, "Response code is " + response.code()); + + if(!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { + Log.d(TAG, "Authorization failed, re-trying with UTF-8 encoding"); + if (userInfo != null) { + String[] parts = userInfo.split(":"); + if (parts.length == 2) { + String credentials = encodeCredentials(parts[0], parts[1], "UTF-8"); + httpReq.header("Authorization", credentials); + } + } else if (!StringUtils.isEmpty(request.getUsername()) && request.getPassword() != null) { + String credentials = encodeCredentials(request.getUsername(), request.getPassword(), + "UTF-8"); + httpReq.header("Authorization", credentials); + } + response = httpClient.newCall(httpReq.build()).execute(); + responseBody = response.body(); + contentEncodingHeader = response.header("Content-Encoding"); + isGzip = StringUtils.equalsIgnoreCase(contentEncodingHeader, "gzip"); + } if(!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_NOT_MODIFIED) { Log.d(TAG, "Feed '" + request.getSource() + "' not modified since last update, Download canceled"); @@ -151,22 +168,18 @@ public class HttpDownloader extends Downloader { out = new RandomAccessFile(destination, "rw"); } - byte[] buffer = new byte[BUFFER_SIZE]; int count = 0; request.setStatusMsg(R.string.download_running); - if (BuildConfig.DEBUG) - Log.d(TAG, "Getting size of download"); + Log.d(TAG, "Getting size of download"); request.setSize(responseBody.contentLength() + request.getSoFar()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Size is " + request.getSize()); + Log.d(TAG, "Size is " + request.getSize()); if (request.getSize() < 0) { request.setSize(DownloadStatus.SIZE_UNKNOWN); } long freeSpace = StorageUtils.getFreeSpaceAvailable(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Free space is " + freeSpace); + Log.d(TAG, "Free space is " + freeSpace); if (request.getSize() != DownloadStatus.SIZE_UNKNOWN && request.getSize() > freeSpace) { @@ -174,8 +187,7 @@ public class HttpDownloader extends Downloader { return; } - if (BuildConfig.DEBUG) - Log.d(TAG, "Starting download"); + Log.d(TAG, "Starting download"); while (!cancelled && (count = connection.read(buffer)) != -1) { out.write(buffer, 0, count); @@ -226,15 +238,12 @@ public class HttpDownloader extends Downloader { } private void onSuccess() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Download was successful"); + Log.d(TAG, "Download was successful"); result.setSuccessful(); } private void onFail(DownloadError reason, String reasonDetailed) { - if (BuildConfig.DEBUG) { - Log.d(TAG, "Download failed"); - } + Log.d(TAG, "Download failed"); result.setFailed(reason, reasonDetailed); if (request.isDeleteOnFailure()) { cleanup(); @@ -242,8 +251,7 @@ public class HttpDownloader extends Downloader { } private void onCancelled() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Download was cancelled"); + Log.d(TAG, "Download was cancelled"); result.setCancelled(); cleanup(); } @@ -256,14 +264,23 @@ public class HttpDownloader extends Downloader { File dest = new File(request.getDestination()); if (dest.exists()) { boolean rc = dest.delete(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Deleted file " + dest.getName() + "; Result: " + Log.d(TAG, "Deleted file " + dest.getName() + "; Result: " + rc); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, "cleanup() didn't delete file: does not exist."); + Log.d(TAG, "cleanup() didn't delete file: does not exist."); } } } + public static String encodeCredentials(String username, String password, String charset) { + try { + String credentials = username + ":" + password; + byte[] bytes = credentials.getBytes(charset); + String encoded = ByteString.of(bytes).base64(); + return "Basic " + encoded; + } catch (UnsupportedEncodingException e) { + throw new AssertionError(); + } + } + } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index cab63891b..3f6769ee4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -254,6 +254,8 @@ public class PlaybackService extends Service { unregisterReceiver(bluetoothStateUpdated); unregisterReceiver(audioBecomingNoisy); unregisterReceiver(skipCurrentEpisodeReceiver); + unregisterReceiver(pausePlayCurrentEpisodeReceiver); + unregisterReceiver(pauseResumeCurrentEpisodeReceiver); mediaPlayer.shutdown(); taskManager.shutdown(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index a7c98c7c6..94fb6f0a7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -327,6 +327,21 @@ public final class DBReader { return feed; } + private static DownloadStatus extractDownloadStatusFromCursorRow(final Cursor cursor) { + long id = cursor.getLong(PodDBAdapter.KEY_ID_INDEX); + long feedfileId = cursor.getLong(PodDBAdapter.KEY_FEEDFILE_INDEX); + int feedfileType = cursor.getInt(PodDBAdapter.KEY_FEEDFILETYPE_INDEX); + boolean successful = cursor.getInt(PodDBAdapter.KEY_SUCCESSFUL_INDEX) > 0; + int reason = cursor.getInt(PodDBAdapter.KEY_REASON_INDEX); + String reasonDetailed = cursor.getString(PodDBAdapter.KEY_REASON_DETAILED_INDEX); + String title = cursor.getString(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE_INDEX); + Date completionDate = new Date(cursor.getLong(PodDBAdapter.KEY_COMPLETION_DATE_INDEX)); + + return new DownloadStatus(id, title, feedfileId, + feedfileType, successful, DownloadError.fromCode(reason), completionDate, + reasonDetailed); + } + private static FeedItem getMatchingItemForMedia(long itemId, List<FeedItem> items) { @@ -565,27 +580,7 @@ public final class DBReader { if (logCursor.moveToFirst()) { do { - long id = logCursor.getLong(PodDBAdapter.KEY_ID_INDEX); - - long feedfileId = logCursor - .getLong(PodDBAdapter.KEY_FEEDFILE_INDEX); - int feedfileType = logCursor - .getInt(PodDBAdapter.KEY_FEEDFILETYPE_INDEX); - 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, feedfileId, - feedfileType, successful, DownloadError.fromCode(reason), completionDate, - reasonDetailed)); - + downloadLog.add(extractDownloadStatusFromCursorRow(logCursor)); } while (logCursor.moveToNext()); } logCursor.close(); @@ -594,6 +589,60 @@ public final class DBReader { } /** + * Loads the download log for a particular feed from the database. + * + * @param context A context that is used for opening a database connection. + * @param feed Feed for which the download log is loaded + * @return A list with DownloadStatus objects that represent the feed's download log, + * newest events first. + */ + public static List<DownloadStatus> getFeedDownloadLog(Context context, Feed feed) { + Log.d(TAG, "getFeedDownloadLog(CONTEXT, " + feed.toString() + ")"); + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + Cursor cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feed.getId()); + List<DownloadStatus> downloadLog = new ArrayList<DownloadStatus>( + cursor.getCount()); + + if (cursor.moveToFirst()) { + do { + downloadLog.add(extractDownloadStatusFromCursorRow(cursor)); + } while (cursor.moveToNext()); + } + cursor.close(); + Collections.sort(downloadLog, new DownloadStatusComparator()); + return downloadLog; + } + + /** + * Loads the download log for a particular feed media from the database. + * + * @param context A context that is used for opening a database connection. + * @param media Feed media for which the download log is loaded + * @return A list with DownloadStatus objects that represent the feed media's download log, + * newest events first. + */ + public static List<DownloadStatus> getFeedMediaDownloadLog(Context context, FeedMedia media) { + Log.d(TAG, "getFeedDownloadLog(CONTEXT, " + media.toString() + ")"); + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + Cursor cursor = adapter.getDownloadLog(FeedMedia.FEEDFILETYPE_FEEDMEDIA, media.getId()); + List<DownloadStatus> downloadLog = new ArrayList<DownloadStatus>( + cursor.getCount()); + + if (cursor.moveToFirst()) { + do { + downloadLog.add(extractDownloadStatusFromCursorRow(cursor)); + } while (cursor.moveToNext()); + } + cursor.close(); + Collections.sort(downloadLog, new DownloadStatusComparator()); + return downloadLog; + } + + /** * Loads the FeedItemStatistics objects of all Feeds in the database. This method should be preferred over * {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)} if only metadata about * the FeedItems is needed. @@ -712,6 +761,35 @@ public final class DBReader { } /** + * Returns credentials based on image URL + * + * @param context A context that is used for opening a database connection. + * @param imageUrl The URL of the image + * @return Credentials in format "<Username>:<Password>", empty String if no authorization given + */ + public static String getImageAuthentication(final Context context, final String imageUrl) { + Log.d(TAG, "Loading credentials for image with URL " + imageUrl); + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + String credentials = getImageAuthentication(context, imageUrl, adapter); + adapter.close(); + return credentials; + + } + + static String getImageAuthentication(final Context context, final String imageUrl, PodDBAdapter adapter) { + String credentials = null; + Cursor cursor = adapter.getImageAuthenticationCursor(imageUrl); + if (cursor.moveToFirst()) { + String username = cursor.getString(0); + String password = cursor.getString(1); + return username + ":" + password; + } + return ""; + } + + /** * Loads a specific FeedItem from the database. * * @param context A context that is used for opening a database connection. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index f518a4f5f..0d680fe6f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -977,6 +977,14 @@ public class PodDBAdapter { return c; } + public final Cursor getDownloadLog(final int feedFileType, final long feedFileId) { + final String query = "SELECT * FROM " + TABLE_NAME_DOWNLOAD_LOG + + " WHERE " + KEY_FEEDFILE + "=" + feedFileId + " AND " + KEY_FEEDFILETYPE + "=" + feedFileType + + " ORDER BY " + KEY_ID + " DESC"; + Cursor c = db.rawQuery(query, null); + return c; + } + public final Cursor getDownloadLogCursor(final int limit) { Cursor c = db.query(TABLE_NAME_DOWNLOAD_LOG, null, null, null, null, null, KEY_COMPLETION_DATE + " DESC LIMIT " + limit); @@ -1146,6 +1154,20 @@ public class PodDBAdapter { return db.rawQuery(query, null); } + public Cursor getImageAuthenticationCursor(final String imageUrl) { + final String query = "SELECT " + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + + TABLE_NAME_FEED_IMAGES + " INNER JOIN " + TABLE_NAME_FEEDS + " ON " + + TABLE_NAME_FEED_IMAGES + "." + KEY_ID + "=" + TABLE_NAME_FEEDS + "." + KEY_IMAGE + " WHERE " + + TABLE_NAME_FEED_IMAGES + "." + KEY_DOWNLOAD_URL + "='" + imageUrl + "' UNION SELECT " + + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + TABLE_NAME_FEED_IMAGES + " INNER JOIN " + + TABLE_NAME_FEED_ITEMS + " ON " + TABLE_NAME_FEED_IMAGES + "." + KEY_ID + "=" + + TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE + " INNER JOIN " + TABLE_NAME_FEEDS + " ON " + + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + " WHERE " + + TABLE_NAME_FEED_IMAGES + "." + KEY_DOWNLOAD_URL + "='" + imageUrl + "'"; + Log.d(TAG, "Query: " + query); + return db.rawQuery(query, null); + } + public int getQueueSize() { final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_QUEUE); Cursor c = db.rawQuery(query, null); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index f162bb353..c0c2f06de 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -128,7 +128,8 @@ <string name="download_error_unauthorized">Authentication error</string> <string name="cancel_all_downloads_label">Cancel all downloads</string> <string name="download_cancelled_msg">Download cancelled</string> - <string name="download_report_title">Downloads completed</string> + <string name="download_report_title">Downloads completed with error(s)</string> + <string name="download_report_content_title">Download report</string> <string name="download_error_malformed_url">Malformed URL</string> <string name="download_error_io_error">IO Error</string> <string name="download_error_request_error">Request error</string> |