Load feed media size on demand

This commit is contained in:
Martin Fietz 2015-08-18 17:38:51 +02:00
parent fd2633e42f
commit 3abce4c597
14 changed files with 133 additions and 131 deletions

View File

@ -1,6 +1,7 @@
import org.apache.tools.ant.filters.ReplaceTokens
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
repositories {
mavenCentral()
@ -22,6 +23,7 @@ dependencies {
compile 'com.squareup.okio:okio:1.2.0'
compile 'de.greenrobot:eventbus:2.4.0'
compile 'com.joanzapata.android:android-iconify:1.0.9'
compile 'io.reactivex:rxandroid:1.0.1'
compile project(':core')
compile project(':library:drag-sort-listview')
@ -108,6 +110,11 @@ android {
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
// about.html is templatized so that we can automatically insert

View File

@ -44,8 +44,6 @@ public class PodcastApp extends Application {
EventDistributor.getInstance();
SPAUtil.sendSPAppsQueryFeedsIntent(this);
// startService(new Intent(this, FeedMediaSizeService.class));
}
public static float getLogicalDensity() {

View File

@ -1,19 +1,23 @@
package de.danoeh.antennapod.adapter;
import android.content.res.Resources;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.joanzapata.android.iconify.Iconify;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.NetworkUtils;
/**
* Utility methods for adapters
*/
public class AdapterUtils {
private static final String TAG = AdapterUtils.class.getSimpleName();
private AdapterUtils() {
}
@ -21,7 +25,7 @@ public class AdapterUtils {
/**
* Updates the contents of the TextView that shows the current playback position and the ProgressBar.
*/
public static void updateEpisodePlaybackProgress(FeedItem item, Resources res, TextView txtvPos, ProgressBar episodeProgress) {
public static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) {
FeedMedia media = item.getMedia();
episodeProgress.setVisibility(View.GONE);
if (media == null) {
@ -42,8 +46,19 @@ public class AdapterUtils {
- media.getPosition()));
}
} else if (!media.isDownloaded()) {
if(media.getSize() > 0) {
if (media.getSize() > 0) {
txtvPos.setText(Converter.byteToString(media.getSize()));
} else if(media.getSize() > Integer.MIN_VALUE) {
txtvPos.setText("{fa-spinner}");
Iconify.addIcons(txtvPos);
NetworkUtils.getFeedMediaSizeObservable(media)
.subscribe(size -> {
if (size > 0) {
txtvPos.setText(Converter.byteToString(size));
} else {
txtvPos.setText("");
}
});
} else {
txtvPos.setText("");
}

View File

@ -14,10 +14,10 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.joanzapata.android.iconify.Iconify;
import java.lang.ref.WeakReference;
@ -27,12 +27,15 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.NetworkUtils;
/**
* List adapter for the list of new episodes
*/
public class AllEpisodesListAdapter extends BaseAdapter {
private static final String TAG = AllEpisodesListAdapter.class.getSimpleName();
private final Context context;
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
@ -117,6 +120,17 @@ public class AllEpisodesListAdapter extends BaseAdapter {
holder.txtvDuration.setText(Converter.getDurationStringLong(media.getDuration()));
} else if (media.getSize() > 0) {
holder.txtvDuration.setText(Converter.byteToString(media.getSize()));
} else if(media.getSize() > Integer.MIN_VALUE) {
holder.txtvDuration.setText("{fa-spinner}");
Iconify.addIcons(holder.txtvDuration);
NetworkUtils.getFeedMediaSizeObservable(media)
.subscribe(size -> {
if (size > 0) {
holder.txtvDuration.setText(Converter.byteToString(size));
} else {
holder.txtvDuration.setText("");
}
});
} else {
holder.txtvDuration.setText("");
}

View File

@ -91,7 +91,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
holder.inPlaylist = (ImageView) convertView
.findViewById(R.id.imgvInPlaylist);
holder.type = (ImageView) convertView.findViewById(R.id.imgvType);
holder.statusUnread = (View) convertView
holder.statusUnread = convertView
.findViewById(R.id.statusUnread);
holder.episodeProgress = (ProgressBar) convertView
.findViewById(R.id.pbar_episode_progress);
@ -100,6 +100,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
} else {
holder = (Holder) convertView.getTag();
}
if (!(getItemViewType(position) == Adapter.IGNORE_ITEM_VIEW_TYPE)) {
convertView.setVisibility(View.VISIBLE);
if (position == selectedItemIndex) {
@ -139,18 +140,17 @@ public class FeedItemlistAdapter extends BaseAdapter {
holder.lenSize.setVisibility(View.INVISIBLE);
} else {
AdapterUtils.updateEpisodePlaybackProgress(item, context.getResources(), holder.lenSize, holder.episodeProgress);
AdapterUtils.updateEpisodePlaybackProgress(item, holder.lenSize, holder.episodeProgress);
if (((ItemAccess) itemAccess).isInQueue(item)) {
if (itemAccess.isInQueue(item)) {
holder.inPlaylist.setVisibility(View.VISIBLE);
} else {
holder.inPlaylist.setVisibility(View.INVISIBLE);
}
if (DownloadRequester.getInstance().isDownloadingFile(
item.getMedia())) {
if (DownloadRequester.getInstance().isDownloadingFile(item.getMedia())) {
holder.episodeProgress.setVisibility(View.VISIBLE);
holder.episodeProgress.setProgress(((ItemAccess) itemAccess).getItemDownloadProgressPercent(item));
holder.episodeProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
} else {
if(media.getPosition() == 0) {
holder.episodeProgress.setVisibility(View.GONE);
@ -206,15 +206,6 @@ public class FeedItemlistAdapter extends BaseAdapter {
ProgressBar episodeProgress;
}
public int getSelectedItemIndex() {
return selectedItemIndex;
}
public void setSelectedItemIndex(int selectedItemIndex) {
this.selectedItemIndex = selectedItemIndex;
notifyDataSetChanged();
}
public interface ItemAccess {
boolean isInQueue(FeedItem item);

View File

@ -4,7 +4,6 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -15,10 +14,10 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.joanzapata.android.iconify.Iconify;
import java.lang.ref.WeakReference;
@ -29,6 +28,7 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.NetworkUtils;
/**
* List adapter for the queue.
@ -143,6 +143,17 @@ public class QueueListAdapter extends BaseAdapter {
} else {
if(media.getSize() > 0) {
holder.progressLeft.setText(Converter.byteToString(media.getSize()));
} else if(media.getSize() > Integer.MIN_VALUE) {
holder.progressLeft.setText("{fa-spinner}");
Iconify.addIcons(holder.progressLeft);
NetworkUtils.getFeedMediaSizeObservable(media)
.subscribe(size -> {
if (size > 0) {
holder.progressLeft.setText(Converter.byteToString(size));
} else {
holder.progressLeft.setText("");
}
});
} else {
holder.progressLeft.setText("");
}

View File

@ -5,7 +5,8 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'me.tatarka:gradle-retrolambda:3.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@ -1,4 +1,5 @@
apply plugin: 'com.android.library'
apply plugin: 'me.tatarka.retrolambda'
android {
compileSdkVersion 21
@ -25,8 +26,8 @@ android {
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
@ -49,4 +50,5 @@ dependencies {
compile 'com.squareup.okio:okio:1.2.0'
compile 'com.nineoldandroids:library:2.4.0'
compile 'de.greenrobot:eventbus:2.4.0'
compile 'io.reactivex:rxandroid:1.0.1'
}

View File

@ -23,9 +23,6 @@
<service
android:name=".service.GpodnetSyncService"
android:enabled="true" />
<service
android:name=".service.FeedMediaSizeService"
android:enabled="true" />
<receiver
android:name=".receiver.MediaButtonReceiver"

View File

@ -1,64 +0,0 @@
package de.danoeh.antennapod.core.service;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
public class FeedMediaSizeService extends IntentService {
private final static String TAG = "FeedMediaSizeService";
public FeedMediaSizeService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent()");
return;
// if(false == NetworkUtils.isDownloadAllowed()) {
// return;
// }
// List<FeedMedia> list = DBReader.getFeedMediaUnknownSize(this);
// for (FeedMedia media : list) {
// Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url());
// if(false == NetworkUtils.isDownloadAllowed()) {
// return;
// }
// long size = Integer.MIN_VALUE;
// if (media.isDownloaded()) {
// File mediaFile = new File(media.getLocalMediaUrl());
// if(mediaFile.exists()) {
// size = mediaFile.length();
// }
// } else if (false == media.checkedOnSizeButUnknown()) {
// // only query the network if we haven't already checked
// HttpURLConnection conn = null;
// try {
// URL url = new URL(media.getDownload_url());
// conn = (HttpURLConnection) url.openConnection();
// conn.setRequestProperty("Accept-Encoding", "");
// conn.setRequestMethod("HEAD");
// size = conn.getContentLength();
// } catch (IOException e) {
// Log.d(TAG, media.getDownload_url());
// e.printStackTrace();
// } finally {
// if (conn != null) {
// conn.disconnect();
// }
// }
// }
// if (size <= 0) {
// // they didn't tell us the size, but we don't want to keep querying on it
// media.setCheckedOnSizeButUnknown();
// } else {
// media.setSize(size);
// }
// Log.d(TAG, "Size now: " + media.getSize());
// DBWriter.setFeedMedia(this, media);
// EventBus.getDefault().post(FeedMediaEvent.update(media));
// }
}
}

View File

@ -521,29 +521,6 @@ public final class DBReader {
return itemIds;
}
/**
* Loads FeedMedia whose file size is unknown
*
* @param context A context that is used for opening a database connection.
* @return A list of FeedMedia items whose size is 0 (unknown and never tried to
* determine the correct size)
*/
public static List<FeedMedia> getFeedMediaUnknownSize(Context context) {
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
Cursor cursor = adapter.getFeedMediaUnknownSizeCursor();
List<FeedMedia> result = new ArrayList<>(cursor.getCount());
if (cursor.moveToFirst()) {
do {
FeedMedia media = extractFeedMediaFromCursorRow(cursor);
result.add(media);
} while (cursor.moveToNext());
}
cursor.close();
return result;
}
/**
* Loads a list of FeedItems sorted by pubDate in descending order.
*

View File

@ -5,9 +5,6 @@ import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -28,11 +25,8 @@ import de.danoeh.antennapod.core.asynctask.FlattrClickWorker;
import de.danoeh.antennapod.core.asynctask.FlattrStatusFetcher;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.FeedMediaSizeService;
import de.danoeh.antennapod.core.service.GpodnetSyncService;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
@ -578,8 +572,6 @@ public final class DBTasks {
EventDistributor.getInstance().sendFeedUpdateBroadcast();
// context.startService(new Intent(context, FeedMediaSizeService.class));
return resultFeeds;
}

View File

@ -1110,13 +1110,6 @@ public class PodDBAdapter {
return db.rawQuery(query, null);
}
public final Cursor getFeedMediaUnknownSizeCursor() {
final String query = "SELECT * "
+ " FROM " + TABLE_NAME_FEED_MEDIA
+ " WHERE " + KEY_SIZE + "<= 0";
return db.rawQuery(query, null);
}
/**
* Returns a cursor which contains all items of a feed that are considered new.
* The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.

View File

@ -7,10 +7,23 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.core.storage.DBWriter;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class NetworkUtils {
@ -78,4 +91,59 @@ public class NetworkUtils {
return mWifi.isConnected();
}
public static Observable<Long> getFeedMediaSizeObservable(FeedMedia media) {
return Observable.create(new Observable.OnSubscribe<Long>() {
@Override
public void call(Subscriber<? super Long> subscriber) {
if (false == NetworkUtils.isDownloadAllowed()) {
subscriber.onNext(0L);
subscriber.onCompleted();
return;
}
long size = Integer.MIN_VALUE;
if (media.isDownloaded()) {
File mediaFile = new File(media.getLocalMediaUrl());
if (mediaFile.exists()) {
size = mediaFile.length();
}
} else if (false == media.checkedOnSizeButUnknown()) {
// only query the network if we haven't already checked
OkHttpClient client = AntennapodHttpClient.getHttpClient();
Request.Builder httpReq = new Request.Builder()
.url(media.getDownload_url())
.header("Accept-Encoding", "identity")
.head();
try {
Response response = client.newCall(httpReq.build()).execute();
if (response.isSuccessful()) {
String contentLength = response.header("Content-Length");
try {
size = Integer.parseInt(contentLength);
} catch (NumberFormatException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
} catch (IOException e) {
subscriber.onNext(0L);
subscriber.onCompleted();
Log.e(TAG, Log.getStackTraceString(e));
return; // better luck next time
}
}
Log.d(TAG, "new size: " + size);
if (size <= 0) {
// they didn't tell us the size, but we don't want to keep querying on it
media.setCheckedOnSizeButUnknown();
} else {
media.setSize(size);
}
subscriber.onNext(size);
subscriber.onCompleted();
DBWriter.setFeedMedia(context, media);
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
}