summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml5
-rw-r--r--res/layout-land/audioplayer_activity.xml164
-rw-r--r--res/layout-land/videoplayer_activity.xml (renamed from res/layout-land/mediaplayer_activity.xml)0
-rw-r--r--res/layout/audioplayer_activity.xml (renamed from res/layout/mediaplayer_activity.xml)14
-rw-r--r--res/layout/cover_fragment.xml1
-rw-r--r--res/layout/external_itemlist_item.xml92
-rw-r--r--res/layout/feeditemlist_header.xml79
-rw-r--r--res/layout/feeditemlist_item.xml2
-rw-r--r--res/values/dimens.xml2
-rw-r--r--src/de/danoeh/antennapod/activity/AudioplayerActivity.java140
-rw-r--r--src/de/danoeh/antennapod/activity/ItemviewActivity.java4
-rw-r--r--src/de/danoeh/antennapod/activity/MediaplayerActivity.java12
-rw-r--r--src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java19
-rw-r--r--src/de/danoeh/antennapod/activity/VideoplayerActivity.java5
-rw-r--r--src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java29
-rw-r--r--src/de/danoeh/antennapod/feed/FeedManager.java42
-rw-r--r--src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java89
-rw-r--r--src/de/danoeh/antennapod/storage/DownloadRequester.java2
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java39
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java17
-rw-r--r--src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java3
-rw-r--r--src/de/danoeh/antennapod/util/playback/ExternalMedia.java9
-rw-r--r--tests/src/de/danoeh/antennapod/test/TestFeeds.java149
23 files changed, 675 insertions, 243 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7a79c26a3..002eac453 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -75,9 +75,7 @@
android:label="@string/downloads_label" />
<activity
android:name=".activity.AudioplayerActivity"
- android:configChanges="keyboardHidden|orientation"
- android:launchMode="singleTask"
- android:screenOrientation="portrait" >
+ android:launchMode="standard" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -362,6 +360,7 @@
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
+
<data
android:path="de.danoeh.antennapod"
android:scheme="package" />
diff --git a/res/layout-land/audioplayer_activity.xml b/res/layout-land/audioplayer_activity.xml
new file mode 100644
index 000000000..521dbc68a
--- /dev/null
+++ b/res/layout-land/audioplayer_activity.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal" >
+
+ <FrameLayout
+ android:id="@+id/contentView"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0.5" >
+ </FrameLayout>
+
+ <RelativeLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0.5"
+ android:background="?attr/non_transparent_background"
+ android:orientation="vertical" >
+
+ <RelativeLayout
+ android:id="@+id/navBar"
+ android:layout_width="fill_parent"
+ android:layout_height="60dp"
+ android:layout_alignParentTop="true" >
+
+ <ImageButton
+ android:id="@+id/butNavLeft"
+ android:layout_width="60dp"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ android:background="?attr/borderless_button"
+ android:padding="4dp" />
+
+ <ImageButton
+ android:id="@+id/butNavRight"
+ android:layout_width="60dp"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:background="?attr/borderless_button"
+ android:padding="4dp" />
+
+ <TextView
+ android:id="@+id/txtvTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_marginTop="8dp"
+ android:layout_toLeftOf="@id/butNavRight"
+ android:layout_toRightOf="@id/butNavLeft"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="@dimen/text_size_medium"
+ android:textStyle="bold" />
+
+ <TextView
+ android:id="@+id/txtvFeed"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/txtvTitle"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_toLeftOf="@id/butNavRight"
+ android:layout_toRightOf="@id/butNavLeft"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="@dimen/text_size_small" />
+ </RelativeLayout>
+
+ <View
+ android:id="@+id/navBarDivider"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_below="@id/navBar"
+ android:background="@color/bright_blue" />
+
+ <RelativeLayout
+ android:id="@+id/player_control"
+ android:layout_width="match_parent"
+ android:layout_height="80dp"
+ android:layout_alignParentBottom="true"
+ android:background="?attr/overlay_background" >
+
+ <ImageButton
+ android:id="@+id/butPlay"
+ android:layout_width="80dp"
+ android:layout_height="match_parent"
+ android:layout_centerHorizontal="true"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:background="?attr/borderless_button"
+ android:src="?attr/av_pause" />
+
+ <ImageButton
+ android:id="@+id/butRev"
+ android:layout_width="80dp"
+ android:layout_height="match_parent"
+ android:layout_toLeftOf="@id/butPlay"
+ android:background="?attr/borderless_button"
+ android:src="?attr/av_rewind" />
+
+ <ImageButton
+ android:id="@+id/butFF"
+ android:layout_width="80dp"
+ android:layout_height="match_parent"
+ android:layout_toRightOf="@id/butPlay"
+ android:background="?attr/borderless_button"
+ android:src="?attr/av_fast_forward" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/playtime_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_above="@id/player_control"
+ android:layout_alignParentLeft="true"
+ android:background="?attr/overlay_drawable" >
+
+ <TextView
+ android:id="@+id/txtvPosition"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:layout_marginLeft="8dp"
+ android:layout_marginTop="16dp"
+ android:text="@string/position_default_label"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="@dimen/text_size_micro" />
+
+ <TextView
+ android:id="@+id/txtvLength"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_centerVertical="true"
+ android:layout_marginRight="8dp"
+ android:layout_marginTop="16dp"
+ android:text="@string/position_default_label"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="@dimen/text_size_micro" />
+
+ <SeekBar
+ android:id="@+id/sbPosition"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_marginTop="16dp"
+ android:layout_toLeftOf="@id/txtvLength"
+ android:layout_toRightOf="@id/txtvPosition"
+ android:max="500" />
+ </RelativeLayout>
+ </RelativeLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout-land/mediaplayer_activity.xml b/res/layout-land/videoplayer_activity.xml
index 675d9709d..675d9709d 100644
--- a/res/layout-land/mediaplayer_activity.xml
+++ b/res/layout-land/videoplayer_activity.xml
diff --git a/res/layout/mediaplayer_activity.xml b/res/layout/audioplayer_activity.xml
index 73a0e0be6..bf7540ed1 100644
--- a/res/layout/mediaplayer_activity.xml
+++ b/res/layout/audioplayer_activity.xml
@@ -41,7 +41,7 @@
android:marqueeRepeatLimit="marquee_forever"
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
- android:textSize="@dimen/text_size_medium"
+ android:textSize="@dimen/text_size_small"
android:textStyle="bold" />
<TextView
@@ -70,23 +70,23 @@
<RelativeLayout
android:id="@+id/player_control"
android:layout_width="match_parent"
- android:layout_height="60dp"
+ android:layout_height="80dp"
android:layout_alignParentBottom="true"
android:background="?attr/overlay_background" >
<ImageButton
android:id="@+id/butPlay"
- android:layout_width="60dp"
+ android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
- android:layout_marginLeft="8dp"
- android:layout_marginRight="8dp"
+ android:layout_marginLeft="12dp"
+ android:layout_marginRight="12dp"
android:background="?attr/borderless_button"
android:src="?attr/av_pause" />
<ImageButton
android:id="@+id/butRev"
- android:layout_width="60dp"
+ android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_toLeftOf="@id/butPlay"
android:background="?attr/borderless_button"
@@ -94,7 +94,7 @@
<ImageButton
android:id="@+id/butFF"
- android:layout_width="60dp"
+ android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_toRightOf="@id/butPlay"
android:background="?attr/borderless_button"
diff --git a/res/layout/cover_fragment.xml b/res/layout/cover_fragment.xml
index f897d318c..9602f1ebc 100644
--- a/res/layout/cover_fragment.xml
+++ b/res/layout/cover_fragment.xml
@@ -11,6 +11,7 @@
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
android:adjustViewBounds="true"
android:scaleType="centerInside" />
diff --git a/res/layout/external_itemlist_item.xml b/res/layout/external_itemlist_item.xml
index 6f2405abc..2d0093641 100644
--- a/res/layout/external_itemlist_item.xml
+++ b/res/layout/external_itemlist_item.xml
@@ -33,63 +33,67 @@
android:layout_alignParentTop="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="4dp"
- android:layout_marginTop="8dp"
+ android:layout_marginTop="2dp"
android:layout_toLeftOf="@id/butAction"
android:layout_toRightOf="@id/imgvFeedimage"
android:ellipsize="end"
- android:maxLines="1"
+ android:lines="2"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/text_size_small" />
- <TextView
- android:id="@+id/txtvFeedname"
+ <LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_below="@id/txtvTitle"
- android:layout_marginLeft="8dp"
- android:layout_marginRight="8dp"
+ android:layout_alignParentBottom="true"
android:layout_toLeftOf="@id/butAction"
android:layout_toRightOf="@id/imgvFeedimage"
- android:ellipsize="end"
- android:maxLines="1"
- android:textColor="?android:attr/textColorSecondary"
- android:textSize="@dimen/text_size_micro" />
+ android:orientation="vertical" >
- <TextView
- android:id="@+id/txtvLenSize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/txtvFeedname"
- android:layout_marginBottom="8dp"
- android:layout_marginLeft="8dp"
- android:layout_marginRight="8dp"
- android:layout_marginTop="4dp"
- android:layout_toRightOf="@id/imgvFeedimage"
- android:ellipsize="end"
- android:maxLines="1"
- android:textColor="?android:attr/textColorTertiary"
- android:textSize="@dimen/text_size_micro" />
+ <TextView
+ android:id="@+id/txtvFeedname"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="@dimen/text_size_micro" />
- <ImageView
- android:id="@+id/imgvDownloadStatus"
- android:layout_width="@dimen/enc_icons_size"
- android:layout_height="@dimen/enc_icons_size"
- android:layout_below="@id/txtvFeedname"
- android:layout_marginBottom="8dp"
- android:layout_marginLeft="8dp"
- android:layout_marginRight="8dp"
- android:layout_marginTop="4dp"
- android:layout_toLeftOf="@id/butAction" />
+ <RelativeLayout
+ android:id="@+id/bottom_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
- <ProgressBar
- android:id="@+id/pbar_episode_progress"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_below="@id/txtvFeedname"
- android:layout_marginTop="4dp"
- android:layout_toLeftOf="@id/imgvDownloadStatus"
- android:layout_toRightOf="@id/txtvLenSize" />
+ <TextView
+ android:id="@+id/txtvLenSize"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorTertiary"
+ android:textSize="@dimen/text_size_micro" />
+
+ <ImageView
+ android:id="@+id/imgvDownloadStatus"
+ android:layout_width="@dimen/enc_icons_size"
+ android:layout_height="@dimen/enc_icons_size"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp" />
+
+ <ProgressBar
+ android:id="@+id/pbar_episode_progress"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_toLeftOf="@id/imgvDownloadStatus"
+ android:layout_toRightOf="@id/txtvLenSize" />
+ </RelativeLayout>
+ </LinearLayout>
<ImageView
android:id="@+id/statusPlaying"
diff --git a/res/layout/feeditemlist_header.xml b/res/layout/feeditemlist_header.xml
index 4dbeae28b..31ccb7e96 100644
--- a/res/layout/feeditemlist_header.xml
+++ b/res/layout/feeditemlist_header.xml
@@ -1,38 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?attr/borderless_button" >
+ android:background="?attr/borderless_button"
+ android:orientation="vertical" >
- <TextView
- android:id="@+id/txtvHeaderTitle"
+ <RelativeLayout
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:layout_marginBottom="24dp"
- android:layout_marginLeft="@dimen/thumbnail_length_itemlist"
- android:layout_marginRight="16dp"
- android:layout_marginTop="24dp"
- android:paddingLeft="8dp"
- android:textColor="@color/dark_blue"
- android:textSize="@dimen/text_size_large"
- android:textStyle="bold" />
+ android:layout_height="match_parent" >
- <ImageButton
- android:id="@+id/butAction"
- android:layout_width="48dp"
- android:layout_height="match_parent"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:background="?attr/borderless_button"
- android:clickable="false"
- android:focusable="false"
- android:focusableInTouchMode="false"
- android:paddingLeft="24dp"
- android:paddingRight="8dp"
- android:paddingTop="16dp"
- android:scaleType="fitEnd"
- android:src="?attr/spinner_button" />
+ <TextView
+ android:id="@+id/txtvHeaderTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:layout_marginBottom="32dp"
+ android:layout_marginLeft="28dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginTop="32dp"
+ android:paddingLeft="8dp"
+ android:textAllCaps="true"
+ android:textColor="@color/dark_blue"
+ android:textSize="@dimen/text_size_large"
+ android:typeface="sans" />
-</RelativeLayout> \ No newline at end of file
+ <ImageButton
+ android:id="@+id/butAction"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:background="?attr/borderless_button"
+ android:clickable="false"
+ android:focusable="false"
+ android:focusableInTouchMode="false"
+ android:paddingLeft="24dp"
+ android:paddingRight="8dp"
+ android:paddingTop="16dp"
+ android:scaleType="fitEnd"
+ android:src="?attr/spinner_button" />
+
+ <TextView
+ android:id="@+id/txtvNumItems"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_centerVertical="true"
+ android:layout_toLeftOf="@id/butAction"
+ android:textColor="@color/dark_blue"
+ android:textSize="@dimen/text_size_large"
+ android:textStyle="normal" />
+ </RelativeLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/feeditemlist_item.xml b/res/layout/feeditemlist_item.xml
index 4fbddbbac..ed4b0d46d 100644
--- a/res/layout/feeditemlist_item.xml
+++ b/res/layout/feeditemlist_item.xml
@@ -14,7 +14,7 @@
android:layout_marginTop="4dp"
android:layout_toLeftOf="@+id/butAction"
android:ellipsize="end"
- android:maxLines="2"
+ android:lines="2"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/text_size_medium" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a74ccf1a9..3b7e7475a 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -11,5 +11,5 @@
<dimen name="text_size_medium">18sp</dimen>
<dimen name="text_size_large">22sp</dimen>
<dimen name="status_indicator_width">36dp</dimen>
- <dimen name="thumbnail_length_itemlist">70dp</dimen>
+ <dimen name="thumbnail_length_itemlist">80dp</dimen>
</resources> \ No newline at end of file
diff --git a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
index 2809d638f..0e2c520fc 100644
--- a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -1,6 +1,8 @@
package de.danoeh.antennapod.activity;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -38,6 +40,9 @@ public class AudioplayerActivity extends MediaplayerActivity {
private static final int NUM_CONTENT_FRAGMENTS = 3;
final String TAG = "AudioplayerActivity";
+ private static final String PREFS = "AudioPlayerActivityPreferences";
+ private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition";
+ private static final String PREF_PLAYABLE_ID = "playableId";
private Fragment[] detachedFragments;
@@ -54,6 +59,37 @@ public class AudioplayerActivity extends MediaplayerActivity {
private ImageButton butNavRight;
private void resetFragmentView() {
+ FragmentTransaction fT = getSupportFragmentManager().beginTransaction();
+
+ if (coverFragment != null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Removing cover fragment");
+ fT.remove(coverFragment);
+ }
+ if (descriptionFragment != null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Removing description fragment");
+ fT.remove(descriptionFragment);
+ }
+ if (chapterFragment != null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Removing chapter fragment");
+ fT.remove(chapterFragment);
+ }
+ if (currentlyShownFragment != null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Removing currently shown fragment");
+ fT.remove(currentlyShownFragment);
+ }
+ for (int i = 0; i < detachedFragments.length; i++) {
+ Fragment f = detachedFragments[i];
+ if (f != null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Removing detached fragment");
+ fT.remove(f);
+ }
+ }
+ fT.commit();
currentlyShownFragment = null;
coverFragment = null;
descriptionFragment = null;
@@ -65,7 +101,8 @@ public class AudioplayerActivity extends MediaplayerActivity {
@Override
protected void onStop() {
super.onStop();
- resetFragmentView();
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "onStop");
}
@@ -77,6 +114,85 @@ public class AudioplayerActivity extends MediaplayerActivity {
detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
}
+ private void savePreferences() {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Saving preferences");
+ SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ if (currentlyShownPosition >= 0 && controller != null
+ && controller.getMedia() != null) {
+ editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
+ currentlyShownPosition);
+ editor.putString(PREF_PLAYABLE_ID, controller.getMedia()
+ .getIdentifier().toString());
+ } else {
+ editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1);
+ editor.putString(PREF_PLAYABLE_ID, "");
+ }
+ editor.commit();
+
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ // super.onSaveInstanceState(outState); would cause crash
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "onSaveInstanceState");
+ }
+
+ @Override
+ protected void onPause() {
+ savePreferences();
+ resetFragmentView();
+ super.onPause();
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ restoreFromPreferences();
+ }
+
+ /**
+ * Tries to restore the selected fragment position from the Activity's
+ * preferences.
+ *
+ * @return true if restoreFromPrefernces changed the activity's state
+ * */
+ private boolean restoreFromPreferences() {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Restoring instance state");
+ SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
+ int savedPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
+ -1);
+ String playableId = prefs.getString(PREF_PLAYABLE_ID, "");
+
+ if (savedPosition != -1
+ && controller != null
+ && controller.getMedia() != null
+ && controller.getMedia().getIdentifier().toString()
+ .equals(playableId)) {
+ switchToFragment(savedPosition);
+ return true;
+ } else if (controller == null || controller.getMedia() == null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Couldn't restore from preferences: controller or media was null");
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Couldn't restore from preferences: savedPosition was -1 or saved identifier and playable identifier didn't match.\nsavedPosition: "
+ + savedPosition + ", id: " + playableId);
+
+ }
+ return false;
+ }
+
@Override
protected void onResume() {
super.onResume();
@@ -131,7 +247,7 @@ public class AudioplayerActivity extends MediaplayerActivity {
private void switchToFragment(int pos) {
if (AppConfig.DEBUG)
Log.d(TAG, "Switching contentView to position " + pos);
- if (currentlyShownPosition != pos) {
+ if (currentlyShownPosition != pos && controller != null) {
Playable media = controller.getMedia();
if (media != null) {
FragmentTransaction ft = getSupportFragmentManager()
@@ -151,7 +267,7 @@ public class AudioplayerActivity extends MediaplayerActivity {
case POS_DESCR:
if (descriptionFragment == null) {
descriptionFragment = ItemDescriptionFragment
- .newInstance(media);
+ .newInstance(media, true);
}
currentlyShownFragment = descriptionFragment;
break;
@@ -187,6 +303,7 @@ public class AudioplayerActivity extends MediaplayerActivity {
ft.add(R.id.contentView, currentlyShownFragment);
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ ft.disallowAddToBackStack();
ft.commit();
updateNavButtonDrawable();
}
@@ -211,8 +328,8 @@ public class AudioplayerActivity extends MediaplayerActivity {
@Override
public void run() {
- ImageLoader.getInstance().loadThumbnailBitmap(
- media, butNavLeft);
+ ImageLoader.getInstance().loadThumbnailBitmap(media,
+ butNavLeft);
}
});
butNavRight.setImageDrawable(drawables.getDrawable(1));
@@ -223,8 +340,8 @@ public class AudioplayerActivity extends MediaplayerActivity {
@Override
public void run() {
- ImageLoader.getInstance().loadThumbnailBitmap(
- media, butNavLeft);
+ ImageLoader.getInstance().loadThumbnailBitmap(media,
+ butNavLeft);
}
});
butNavRight.setImageDrawable(drawables.getDrawable(0));
@@ -291,7 +408,9 @@ public class AudioplayerActivity extends MediaplayerActivity {
}
if (currentlyShownPosition == -1) {
- switchToFragment(POS_COVER);
+ if (!restoreFromPreferences()) {
+ switchToFragment(POS_COVER);
+ }
}
if (currentlyShownFragment instanceof AudioplayerContentFragment) {
((AudioplayerContentFragment) currentlyShownFragment)
@@ -333,4 +452,9 @@ public class AudioplayerActivity extends MediaplayerActivity {
public void onDataSetChanged(Playable media);
}
+ @Override
+ protected int getContentViewResourceId() {
+ return R.layout.audioplayer_activity;
+ }
+
}
diff --git a/src/de/danoeh/antennapod/activity/ItemviewActivity.java b/src/de/danoeh/antennapod/activity/ItemviewActivity.java
index 63dcb78f1..5ead667dc 100644
--- a/src/de/danoeh/antennapod/activity/ItemviewActivity.java
+++ b/src/de/danoeh/antennapod/activity/ItemviewActivity.java
@@ -99,7 +99,7 @@ public class ItemviewActivity extends SherlockFragmentActivity {
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
ItemDescriptionFragment fragment = ItemDescriptionFragment
- .newInstance(item);
+ .newInstance(item, false);
fragmentTransaction.replace(R.id.description_fragment, fragment);
fragmentTransaction.commit();
}
@@ -127,7 +127,7 @@ public class ItemviewActivity extends SherlockFragmentActivity {
DownloadRequestErrorDialogCreator.newRequestErrorDialog(this,
e.getMessage());
}
- invalidateOptionsMenu();
+ supportInvalidateOptionsMenu();
return true;
}
diff --git a/src/de/danoeh/antennapod/activity/MediaplayerActivity.java b/src/de/danoeh/antennapod/activity/MediaplayerActivity.java
index 6d27a82e0..16b03809a 100644
--- a/src/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ b/src/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod.activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Bundle;
@@ -331,13 +330,6 @@ public abstract class MediaplayerActivity extends SherlockFragmentActivity
controller.init();
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- // ignore orientation change
-
- }
-
/**
* Called by 'handleStatus()' when the PlaybackService is in the
* AWAITING_VIDEO_SURFACE state.
@@ -399,7 +391,7 @@ public abstract class MediaplayerActivity extends SherlockFragmentActivity
}
protected void setupGUI() {
- setContentView(R.layout.mediaplayer_activity);
+ setContentView(getContentViewResourceId());
sbPosition = (SeekBar) findViewById(R.id.sbPosition);
txtvPosition = (TextView) findViewById(R.id.txtvPosition);
txtvLength = (TextView) findViewById(R.id.txtvLength);
@@ -421,6 +413,8 @@ public abstract class MediaplayerActivity extends SherlockFragmentActivity
}
+ protected abstract int getContentViewResourceId();
+
void handleError(int errorCode) {
final AlertDialog.Builder errorDialog = new AlertDialog.Builder(this);
errorDialog.setTitle(R.string.error_label);
diff --git a/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java b/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java
index 65225a584..89001f7f5 100644
--- a/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java
+++ b/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java
@@ -72,10 +72,7 @@ public class OrganizeQueueActivity extends SherlockListActivity {
@Override
public void drop(int from, int to) {
FeedManager manager = FeedManager.getInstance();
- int offset = (manager.firstQueueItemIsPlaying()) ? 1 : 0;
-
- manager.moveQueueItem(OrganizeQueueActivity.this, from + offset, to
- + offset, false);
+ manager.moveQueueItem(OrganizeQueueActivity.this, from, to, false);
adapter.notifyDataSetChanged();
}
};
@@ -85,7 +82,6 @@ public class OrganizeQueueActivity extends SherlockListActivity {
@Override
public void remove(int which) {
FeedManager manager = FeedManager.getInstance();
-
manager.removeQueueItem(OrganizeQueueActivity.this,
(FeedItem) getListAdapter().getItem(which));
}
@@ -174,21 +170,12 @@ public class OrganizeQueueActivity extends SherlockListActivity {
@Override
public int getCount() {
int queueSize = manager.getQueueSize(true);
- if (manager.firstQueueItemIsPlaying()) {
- return queueSize - 1;
- } else {
- return queueSize;
- }
+ return queueSize;
}
@Override
public FeedItem getItem(int position) {
- if (manager.firstQueueItemIsPlaying() && position < getCount()) {
- return manager.getQueueItemAtIndex(position + 1, true);
- } else {
- return manager.getQueueItemAtIndex(position, true);
- }
-
+ return manager.getQueueItemAtIndex(position, true);
}
@Override
diff --git a/src/de/danoeh/antennapod/activity/VideoplayerActivity.java b/src/de/danoeh/antennapod/activity/VideoplayerActivity.java
index 2d9834a3e..b3567e417 100644
--- a/src/de/danoeh/antennapod/activity/VideoplayerActivity.java
+++ b/src/de/danoeh/antennapod/activity/VideoplayerActivity.java
@@ -287,4 +287,9 @@ public class VideoplayerActivity extends MediaplayerActivity implements
videoOverlay.setVisibility(View.GONE);
}
+ @Override
+ protected int getContentViewResourceId() {
+ return R.layout.videoplayer_activity;
+ }
+
}
diff --git a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
index 0e5ef2435..916e13469 100644
--- a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
@@ -166,7 +166,7 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
holder.downloadStatus.setVisibility(View.INVISIBLE);
holder.lenSize.setVisibility(View.INVISIBLE);
}
-
+
holder.feedImage.setTag(item.getImageLoaderCacheKey());
ImageLoader.getInstance().loadThumbnailBitmap(
item,
@@ -209,7 +209,12 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
@Override
public int getGroupCount() {
- return 2;
+ // Hide 'unread items' group if empty
+ if (manager.getUnreadItemsSize(true) > 0) {
+ return 2;
+ } else {
+ return 1;
+ }
}
@Override
@@ -226,20 +231,26 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
TextView headerTitle = (TextView) convertView
.findViewById(R.id.txtvHeaderTitle);
ImageButton actionButton = (ImageButton) convertView
- .findViewById(R.id.butAction);
+ .findViewById(R.id.butAction);
+ TextView numItems = (TextView) convertView.findViewById(R.id.txtvNumItems);
+
String headerString = null;
+ int childrenCount = 0;
+
if (groupPosition == 0) {
headerString = context.getString(R.string.queue_label);
- if (manager.getQueueSize(true) > 0) {
- headerString += " (" + getChildrenCount(GROUP_POS_QUEUE) + ")";
- }
+ childrenCount = getChildrenCount(GROUP_POS_QUEUE);
} else {
headerString = context.getString(R.string.waiting_list_label);
- if (manager.getUnreadItemsSize(true) > 0) {
- headerString += " (" + getChildrenCount(GROUP_POS_UNREAD) + ")";
- }
+ childrenCount = getChildrenCount(GROUP_POS_UNREAD);
}
headerTitle.setText(headerString);
+ if (childrenCount <= 0) {
+ numItems.setVisibility(View.INVISIBLE);
+ } else {
+ numItems.setVisibility(View.VISIBLE);
+ numItems.setText(Integer.toString(childrenCount));
+ }
actionButton.setFocusable(false);
actionButton.setOnClickListener(new OnClickListener() {
diff --git a/src/de/danoeh/antennapod/feed/FeedManager.java b/src/de/danoeh/antennapod/feed/FeedManager.java
index c7f317b62..bdffdc667 100644
--- a/src/de/danoeh/antennapod/feed/FeedManager.java
+++ b/src/de/danoeh/antennapod/feed/FeedManager.java
@@ -7,6 +7,9 @@ import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.TreeSet;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
@@ -114,8 +117,8 @@ public class FeedManager {
/**
* Play FeedMedia and start the playback service + launch Mediaplayer
- * Activity. The FeedItem belonging to the media is moved to the top of the
- * queue.
+ * Activity. The FeedItem will be added at the top of the queue if it isn't
+ * in there yet.
*
* @param context
* for starting the playbackservice
@@ -153,9 +156,7 @@ public class FeedManager {
context.startActivity(PlaybackService.getPlayerActivityIntent(
context, media));
}
- if (queue.contains(media.getItem())) {
- moveQueueItem(context, queue.indexOf(media.getItem()), 0, true);
- } else {
+ if (!queue.contains(media.getItem())) {
addQueueItemAt(context, media.getItem(), 0, false);
}
} catch (MediaFileNotFoundException e) {
@@ -1627,6 +1628,10 @@ public class FeedManager {
if (AppConfig.DEBUG)
Log.d(TAG, "Extracting Queue");
Cursor cursor = adapter.getQueueCursor();
+
+ // Sort cursor results by ID with TreeMap
+ TreeMap<Integer, FeedItem> map = new TreeMap<Integer, FeedItem>();
+
if (cursor.moveToFirst()) {
do {
int index = cursor.getInt(PodDBAdapter.KEY_ID_INDEX);
@@ -1637,13 +1642,17 @@ public class FeedManager {
cursor.getLong(PodDBAdapter.KEY_FEEDITEM_INDEX),
feed);
if (item != null) {
- queue.add(index, item);
+ map.put(index, item);
}
}
-
} while (cursor.moveToNext());
}
cursor.close();
+
+ for (Map.Entry<Integer, FeedItem> entry : map.entrySet()) {
+ FeedItem item = entry.getValue();
+ queue.add(item);
+ }
}
/**
@@ -1786,18 +1795,23 @@ public class FeedManager {
}
/**
- * Returns true if the first item in the queue is currently being played or
- * false otherwise. If the queue is empty, this method will also return
- * false.
+ * Returns the index of the episode that is currently being played in the
+ * queue or -1 if the queue is empty or no episode in the queue is being
+ * played.
* */
- public boolean firstQueueItemIsPlaying() {
+ public int getQueuePlayingEpisodeIndex() {
FeedManager manager = FeedManager.getInstance();
int queueSize = manager.getQueueSize(true);
if (queueSize == 0) {
- return false;
+ return -1;
} else {
- FeedItem item = getQueueItemAtIndex(0, true);
- return item.getState() == FeedItem.State.PLAYING;
+ for (int x = 0; x < queueSize; x++) {
+ FeedItem item = getQueueItemAtIndex(x, true);
+ if (item.getState() == FeedItem.State.PLAYING) {
+ return x;
+ }
+ }
+ return -1;
}
}
diff --git a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
index 02b74a4e5..a1dfa51d4 100644
--- a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -7,7 +7,9 @@ import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.TypedArray;
+import android.graphics.Picture;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@@ -21,8 +23,10 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.webkit.WebChromeClient;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebView;
+import android.webkit.WebView.PictureListener;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
@@ -40,10 +44,16 @@ import de.danoeh.antennapod.util.playback.Playable;
public class ItemDescriptionFragment extends SherlockFragment {
private static final String TAG = "ItemDescriptionFragment";
+
+ private static final String PREF = "ItemDescriptionFragmentPrefs";
+ private static final String PREF_SCROLL_Y = "prefScrollY";
+ private static final String PREF_PLAYABLE_ID = "prefPlayableId";
+
private static final String ARG_PLAYABLE = "arg.playable";
private static final String ARG_FEED_ID = "arg.feedId";
private static final String ARG_FEED_ITEM_ID = "arg.feeditemId";
+ private static final String ARG_SAVE_STATE = "arg.saveState";
private WebView webvDescription;
private Playable media;
@@ -57,19 +67,29 @@ public class ItemDescriptionFragment extends SherlockFragment {
/** URL that was selected via long-press. */
private String selectedURL;
- public static ItemDescriptionFragment newInstance(Playable media) {
+ /**
+ * True if Fragment should save its state (e.g. scrolling position) in a
+ * shared preference.
+ */
+ private boolean saveState;
+
+ public static ItemDescriptionFragment newInstance(Playable media,
+ boolean saveState) {
ItemDescriptionFragment f = new ItemDescriptionFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_PLAYABLE, media);
+ args.putBoolean(ARG_SAVE_STATE, saveState);
f.setArguments(args);
return f;
}
- public static ItemDescriptionFragment newInstance(FeedItem item) {
+ public static ItemDescriptionFragment newInstance(FeedItem item,
+ boolean saveState) {
ItemDescriptionFragment f = new ItemDescriptionFragment();
Bundle args = new Bundle();
args.putLong(ARG_FEED_ID, item.getFeed().getId());
args.putLong(ARG_FEED_ITEM_ID, item.getId());
+ args.putBoolean(ARG_SAVE_STATE, saveState);
f.setArguments(args);
return f;
}
@@ -138,6 +158,7 @@ public class ItemDescriptionFragment extends SherlockFragment {
if (AppConfig.DEBUG)
Log.d(TAG, "Creating fragment");
Bundle args = getArguments();
+ saveState = args.getBoolean(ARG_SAVE_STATE, false);
if (args.containsKey(ARG_PLAYABLE)) {
media = args.getParcelable(ARG_PLAYABLE);
} else if (args.containsKey(ARG_FEED_ID)
@@ -244,6 +265,7 @@ public class ItemDescriptionFragment extends SherlockFragment {
}
};
+ @SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
public boolean onContextItemSelected(MenuItem item) {
@@ -314,6 +336,7 @@ public class ItemDescriptionFragment extends SherlockFragment {
String data;
+ @SuppressWarnings("deprecation")
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
@@ -327,6 +350,16 @@ public class ItemDescriptionFragment extends SherlockFragment {
if (AppConfig.DEBUG)
Log.d(TAG, "Webview loaded");
webViewLoader = null;
+ webvDescription.setPictureListener(new PictureListener() {
+
+ @Override
+ @Deprecated
+ public void onNewPicture(WebView view, Picture picture) {
+ restoreFromPreference();
+
+ }
+ });
+
}
@Override
@@ -364,4 +397,56 @@ public class ItemDescriptionFragment extends SherlockFragment {
};
}
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ savePreference();
+ }
+
+ private void savePreference() {
+ if (saveState) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Saving preferences");
+ SharedPreferences prefs = getActivity().getSharedPreferences(PREF,
+ Activity.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ if (media != null && webvDescription != null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Saving scroll position: "
+ + webvDescription.getScrollY());
+ editor.putInt(PREF_SCROLL_Y, webvDescription.getScrollY());
+ editor.putString(PREF_PLAYABLE_ID, media.getIdentifier()
+ .toString());
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "savePreferences was called while media or webview was null");
+ editor.putInt(PREF_SCROLL_Y, -1);
+ editor.putString(PREF_PLAYABLE_ID, "");
+ }
+ editor.commit();
+ }
+ }
+
+ private boolean restoreFromPreference() {
+ if (saveState) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Restoring from preferences");
+ SharedPreferences prefs = getActivity().getSharedPreferences(PREF,
+ Activity.MODE_PRIVATE);
+ String id = prefs.getString(PREF_PLAYABLE_ID, "");
+ int scrollY = prefs.getInt(PREF_SCROLL_Y, -1);
+ if (scrollY != -1 && media != null
+ && id.equals(media.getIdentifier().toString())
+ && webvDescription != null) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Restored scroll Position: " + scrollY);
+ webvDescription.scrollTo(webvDescription.getScrollX(), scrollY);
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/de/danoeh/antennapod/storage/DownloadRequester.java b/src/de/danoeh/antennapod/storage/DownloadRequester.java
index bebffe8f9..29bd764dd 100644
--- a/src/de/danoeh/antennapod/storage/DownloadRequester.java
+++ b/src/de/danoeh/antennapod/storage/DownloadRequester.java
@@ -113,7 +113,7 @@ public class DownloadRequester {
private boolean isFilenameAvailable(String path) {
for (String key : downloads.keySet()) {
FeedFile f = downloads.get(key);
- if (f.getFile_url().equals(path)) {
+ if (f.getFile_url() != null && f.getFile_url().equals(path)) {
if (AppConfig.DEBUG)
Log.d(TAG, path
+ " is already used by another requested download");
diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
index f1842800b..420264840 100644
--- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java
+++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
@@ -6,6 +6,7 @@ import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
+import android.database.DatabaseUtils;
import android.database.MergeCursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
@@ -212,7 +213,6 @@ public class PodDBAdapter {
public static final int IDX_FI_EXTRA_CONTENT_ENCODED = 2;
public static final int IDX_FI_EXTRA_FEED = 3;
-
public PodDBAdapter(Context c) {
this.context = c;
helper = new PodDBHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -441,6 +441,7 @@ public class PodDBAdapter {
public void setQueue(List<FeedItem> queue) {
ContentValues values = new ContentValues();
+ db.beginTransaction();
db.delete(TABLE_NAME_QUEUE, null, null);
for (int i = 0; i < queue.size(); i++) {
FeedItem item = queue.get(i);
@@ -450,6 +451,8 @@ public class PodDBAdapter {
db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values,
SQLiteDatabase.CONFLICT_REPLACE);
}
+ db.setTransactionSuccessful();
+ db.endTransaction();
}
public void removeFeedMedia(FeedMedia media) {
@@ -654,6 +657,18 @@ public class PodDBAdapter {
}
/**
+ * Uses DatabaseUtils to escape a search query and removes ' at the
+ * beginning and the end of the string returned by the escape method.
+ */
+ private String prepareSearchQuery(String query) {
+ StringBuilder builder = new StringBuilder();
+ DatabaseUtils.appendEscapedSQLString(builder, query);
+ builder.deleteCharAt(0);
+ builder.deleteCharAt(builder.length() - 1);
+ return builder.toString();
+ }
+
+ /**
* Searches for the given query in the description of all items or the items
* of a specified feed.
*
@@ -663,13 +678,15 @@ public class PodDBAdapter {
if (feed != null) {
// search items in specific feed
return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_FEED
- + "=? AND " + KEY_DESCRIPTION + " LIKE '%" + query + "%'", new String[] {
- String.valueOf(feed.getId()) }, null, null, null);
+ + "=? AND " + KEY_DESCRIPTION + " LIKE '%"
+ + prepareSearchQuery(query) + "%'",
+ new String[] { String.valueOf(feed.getId()) }, null, null,
+ null);
} else {
// search through all items
return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA,
- KEY_DESCRIPTION + " LIKE '%" + query + "%'", null, null,
- null, null);
+ KEY_DESCRIPTION + " LIKE '%" + prepareSearchQuery(query)
+ + "%'", null, null, null, null);
}
}
@@ -683,14 +700,16 @@ public class PodDBAdapter {
if (feed != null) {
// search items in specific feed
return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_FEED
- + "=? AND " + KEY_CONTENT_ENCODED + " LIKE '%" + query + "%'",
- new String[] { String.valueOf(feed.getId())}, null,
- null, null);
+ + "=? AND " + KEY_CONTENT_ENCODED + " LIKE '%"
+ + prepareSearchQuery(query) + "%'",
+ new String[] { String.valueOf(feed.getId()) }, null, null,
+ null);
} else {
// search through all items
return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA,
- KEY_CONTENT_ENCODED + " LIKE '%" + query + "%'", null,
- null, null, null);
+ KEY_CONTENT_ENCODED + " LIKE '%"
+ + prepareSearchQuery(query) + "%'", null, null,
+ null, null);
}
}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java b/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java
index 522b16efe..1efaac359 100644
--- a/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java
+++ b/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java
@@ -42,6 +42,12 @@ public class NSAtom extends Namespace {
private static final String LINK_REL_PAYMENT = "payment";
private static final String LINK_REL_RELATED = "related";
private static final String LINK_REL_SELF = "self";
+ // type-values
+ private static final String LINK_TYPE_ATOM = "application/atom+xml";
+ private static final String LINK_TYPE_HTML = "text/html";
+ private static final String LINK_TYPE_XHTML = "application/xml+xhtml";
+
+ private static final String LINK_TYPE_RSS = "application/rss+xml";
/** Regexp to test whether an Element is a Text Element. */
private static final String isText = TITLE + "|" + CONTENT + "|" + "|"
@@ -85,7 +91,16 @@ public class NSAtom extends Namespace {
}
} else if (parent.getName().matches(isFeed)) {
if (rel == null || rel.equals(LINK_REL_ALTERNATE)) {
- state.getFeed().setLink(href);
+ String type = attributes.getValue(LINK_TYPE);
+ /*
+ * Use as link if a) no type-attribute is given and
+ * feed-object has no link yet b) type of link is
+ * LINK_TYPE_HTML or LINK_TYPE_XHTML
+ */
+ if ((type == null && state.getFeed().getLink() == null)
+ || (type != null && (type.equals(LINK_TYPE_HTML) || type.equals(LINK_TYPE_XHTML)))) {
+ state.getFeed().setLink(href);
+ }
} else if (rel.equals(LINK_REL_PAYMENT)) {
state.getFeed().setPaymentLink(href);
}
diff --git a/src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java b/src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java
index 6196d064d..30835434f 100644
--- a/src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java
+++ b/src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java
@@ -11,8 +11,7 @@ import android.util.Log;
public class SyndDateUtils {
private static final String TAG = "DateUtils";
- public static final String[] RFC822DATES = { "dd MMM yyyy HH:mm:ss Z",
- "dd MMM yy HH:mm:ss Z", };
+ public static final String[] RFC822DATES = { "dd MMM yy HH:mm:ss Z", };
/** RFC 3339 date format for UTC dates. */
public static final String RFC3339UTC = "yyyy-MM-dd'T'HH:mm:ss'Z'";
diff --git a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java b/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
index 55a37413b..c0a92904b 100644
--- a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
+++ b/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
@@ -69,6 +69,11 @@ public class ExternalMedia implements Playable {
e.printStackTrace();
throw new PlayableException(
"IllegalArgumentException when setting up MediaMetadataReceiver");
+ } catch (RuntimeException e) {
+ // http://code.google.com/p/android/issues/detail?id=39770
+ e.printStackTrace();
+ throw new PlayableException(
+ "RuntimeException when setting up MediaMetadataRetriever");
}
episodeTitle = mmr
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
@@ -78,10 +83,10 @@ public class ExternalMedia implements Playable {
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
ChapterUtils.loadChaptersFromFileUrl(this);
}
-
+
@Override
public void loadChapterMarks() {
-
+
}
@Override
diff --git a/tests/src/de/danoeh/antennapod/test/TestFeeds.java b/tests/src/de/danoeh/antennapod/test/TestFeeds.java
index e875bc7ce..576a8ddd9 100644
--- a/tests/src/de/danoeh/antennapod/test/TestFeeds.java
+++ b/tests/src/de/danoeh/antennapod/test/TestFeeds.java
@@ -3,76 +3,6 @@ package de.danoeh.antennapod.test;
public class TestFeeds {
public static final String[] urls = {
- "http://www.guardian.co.uk/global-development/series/global-development-podcast/rss",
- "http://rss.sciam.com/sciam/60secsciencepodcast",
- "http://rss.sciam.com/sciam/60-second-mind",
- "http://rss.sciam.com/sciam/60-second-space",
- "http://rss.sciam.com/sciam/60-second-health",
- "http://rss.sciam.com/sciam/60-second-tech",
- "http://risky.biz/feeds/risky-business",
- "http://risky.biz/feeds/rb2",
- "http://podcast.hr-online.de/lateline/podcast.xml",
- "http://bitlove.org/nsemak/mikrodilettanten/feed",
- "http://bitlove.org/moepmoeporg/riotburnz/feed",
- "http://bitlove.org/moepmoeporg/schachcast/feed",
- "http://bitlove.org/moepmoeporg/sundaymoaning/feed",
- "http://bitlove.org/motofunk/anekdotkast/feed",
- "http://bitlove.org/motofunk/motofunk/feed",
- "http://bitlove.org/nerdinand/zch/feed",
- "http://podcast.homerj.de/podcasts.xml",
- "http://www.dradio.de/rss/podcast/sendungen/wissenschaftundbildung/",
- "http://www.dradio.de/rss/podcast/sendungen/wirtschaftundverbraucher/",
- "http://www.dradio.de/rss/podcast/sendungen/literatur/",
- "http://www.dradio.de/rss/podcast/sendungen/sport/",
- "http://www.dradio.de/rss/podcast/sendungen/wirtschaftundgesellschaft/",
- "http://www.dradio.de/rss/podcast/sendungen/filmederwoche/",
- "http://www.blacksweetstories.com/feed/podcast/",
- "http://feeds.5by5.tv/buildanalyze",
- "http://bitlove.org/ranzzeit/ranz/feed",
- "http://bitlove.org/importthis/mp3/feed",
- "http://bitlove.org/astro/youtube/feed",
- "http://bitlove.org/channelcast/channelcast/feed",
- "http://bitlove.org/cccb/chaosradio/feed",
- "http://bitlove.org/astro/bitlove-show/feed",
- "http://feeds.thisamericanlife.org/talpodcast",
- "http://www.casasola.de/137b/1337motiv/1337motiv.xml",
- "http://alternativlos.org/ogg.rss", "http://www.bitsundso.de/feed",
- "http://www.gamesundso.de/feed/",
- "http://feeds.feedburner.com/cre-podcast",
- "http://feeds.feedburner.com/NotSafeForWorkPodcast",
- "http://feeds.feedburner.com/mobile-macs-podcast",
- "http://www.gamesundso.de/feed/",
- "http://feeds.feedburner.com/DerLautsprecher",
- "http://feeds.feedburner.com/raumzeit-podcast",
- "http://feeds.feedburner.com/TheLunaticFringe",
- "http://feeds.feedburner.com/Kuechenradioorg",
- "http://feeds.feedburner.com/Medienradio_Podcast_RSS",
- "http://feeds.feedburner.com/wrint/wrint",
- "http://retrozirkel.de/episodes.mp3.rss",
- "http://trackback.fritz.de/?feed=podcast",
- "http://feeds.feedburner.com/linuxoutlaws-ogg",
- "http://www.mevio.com/feeds/noagenda.xml",
- "http://podcast.hr2.de/derTag/podcast.xml",
- "http://feeds.feedburner.com/thechangelog",
- "http://leoville.tv/podcasts/floss.xml",
- "http://www.radiotux.de/index.php?/feeds/index.rss2",
- "http://megamagis.ch/episodes.mp3.rss",
- "http://www.eurogamer.net/rss/eurogamer_podcast_itunes.rss",
- "http://bobsonbob.de/?feed=rss2",
- "http://www.blacksweetstories.com/feed/podcast/",
- "http://www.eurogamer.net/rss/eurogamer_podcast_itunes.rss",
- "http://diehoppeshow.de/podcast/feed.xml",
- "http://feeds.feedburner.com/ThisIsMyNextPodcast?format=xml",
- "http://bitlove.org/343max/maerchenstunde/feed",
- "http://bitlove.org/343max/wmr-aac/feed",
- "http://bitlove.org/343max/wmr-mp3/feed",
- "http://bitlove.org/343max/wmr-oga/feed",
- "http://bitlove.org/adamc1999/noagenda/feed",
- "http://bitlove.org/alexbrueckel/normalzeit_podcast/feed",
- "http://bitlove.org/alexbrueckel/normalzeit_podcast_mp3/feed",
- "http://bitlove.org/alexbrueckel/tisch3-podcast/feed",
- "http://bitlove.org/alexolma/iphoneblog/feed",
- "http://bitlove.org/andydrop/nachtnerd/feed",
"http://bitlove.org/apollo40/ps3newsroom/feed",
"http://bitlove.org/beapirate/hauptstadtpiraten/feed",
"http://bitlove.org/benni/besondereumstaende/feed",
@@ -86,7 +16,6 @@ public class TestFeeds {
"http://bitlove.org/binaergewitter/talk-ogg/feed",
"http://bitlove.org/bitgamers/bitgamerscast/feed",
"http://bitlove.org/boingsworld/boingsworld/feed",
- "http://bitlove.org/boris/appsacker/feed",
"http://bitlove.org/boris/bam/feed",
"http://bitlove.org/bruhndsoweiter/anycast-aac/feed",
"http://bitlove.org/bruhndsoweiter/anycast-mp3/feed",
@@ -113,8 +42,6 @@ public class TestFeeds {
"http://bitlove.org/cinext/cinext/feed",
"http://bitlove.org/ckater/schoeneecken/feed",
"http://bitlove.org/ckater/schoeneecken-mp3/feed",
- "http://bitlove.org/cllassnig/bytegefluester/feed",
- "http://bitlove.org/cllassnig/nerdtirol/feed",
"http://bitlove.org/cocoaheads/austria/feed",
"http://bitlove.org/compod/compod/feed",
"http://bitlove.org/consolmedia/consolpodcast/feed",
@@ -173,7 +100,6 @@ public class TestFeeds {
"http://bitlove.org/ich-bin-radio/fir/feed",
"http://bitlove.org/ich-bin-radio/rsff/feed",
"http://bitlove.org/incerio/podcast/feed",
- "http://bitlove.org/jagdfunk/jagdfunk/feed",
"http://bitlove.org/janlelis/rubykraut/feed",
"http://bitlove.org/jed/feed1/feed",
"http://bitlove.org/jupiterbroadcasting/coderradio/feed",
@@ -223,7 +149,6 @@ public class TestFeeds {
"http://bitlove.org/mfromm/explorism/feed",
"http://bitlove.org/mfromm/transientesichten/feed",
"http://bitlove.org/mhpod/pofacs/feed",
- "http://bitlove.org/michaelgreth/sharepointpdcast/feed",
"http://bitlove.org/mintcast/podcast/feed",
"http://bitlove.org/mitgezwitschert/brandung/feed",
"http://bitlove.org/moepmoeporg/anonnewsde/feed",
@@ -244,7 +169,6 @@ public class TestFeeds {
"http://bitlove.org/moepmoeporg/sundaymoaning/feed",
"http://bitlove.org/motofunk/anekdotkast/feed",
"http://bitlove.org/motofunk/motofunk/feed",
- "http://bitlove.org/nerdinand/zch/feed",
"http://bitlove.org/netzpolitik/netzpolitik-podcast/feed",
"http://bitlove.org/netzpolitik/netzpolitik-tv/feed",
"http://bitlove.org/nischenkultur/soziopod/feed",
@@ -282,7 +206,6 @@ public class TestFeeds {
"http://bitlove.org/podsafepilot/psid/feed",
"http://bitlove.org/pratfm/strunt/feed",
"http://bitlove.org/pressrecord/podcast/feed",
- "http://bitlove.org/pztv/alle_formate/feed",
"http://bitlove.org/qbi/datenkanal-mp3/feed",
"http://bitlove.org/qbi/datenkanal-ogg/feed",
"http://bitlove.org/quotidianitaet/quotidianitaet/feed",
@@ -347,10 +270,76 @@ public class TestFeeds {
"http://bitlove.org/weezerle/brandung/feed",
"http://bitlove.org/weezerle/guestcast/feed",
"http://bitlove.org/weezerle/stupalog/feed",
- "http://bitlove.org/wikigeeks/wikigeeks-aac/feed",
- "http://bitlove.org/wikigeeks/wikigeeks-mp3/feed",
- "http://bitlove.org/wikigeeks/wikigeeks-ogg/feed",
+ "http://bitlove.org/wikigeeks/mp3/feed",
"http://bitlove.org/workingdraft/revisionen/feed",
"http://bitlove.org/wunderlich/podcast/feed",
+ "http://www.guardian.co.uk/global-development/series/global-development-podcast/rss",
+ "http://rss.sciam.com/sciam/60secsciencepodcast",
+ "http://rss.sciam.com/sciam/60-second-mind",
+ "http://rss.sciam.com/sciam/60-second-space",
+ "http://rss.sciam.com/sciam/60-second-health",
+ "http://rss.sciam.com/sciam/60-second-tech",
+ "http://risky.biz/feeds/risky-business",
+ "http://risky.biz/feeds/rb2",
+ "http://podcast.hr-online.de/lateline/podcast.xml",
+ "http://bitlove.org/nsemak/mikrodilettanten/feed",
+ "http://bitlove.org/moepmoeporg/riotburnz/feed",
+ "http://bitlove.org/moepmoeporg/schachcast/feed",
+ "http://bitlove.org/moepmoeporg/sundaymoaning/feed",
+ "http://bitlove.org/motofunk/anekdotkast/feed",
+ "http://bitlove.org/motofunk/motofunk/feed",
+ "http://podcast.homerj.de/podcasts.xml",
+ "http://www.dradio.de/rss/podcast/sendungen/wissenschaftundbildung/",
+ "http://www.dradio.de/rss/podcast/sendungen/wirtschaftundverbraucher/",
+ "http://www.dradio.de/rss/podcast/sendungen/literatur/",
+ "http://www.dradio.de/rss/podcast/sendungen/sport/",
+ "http://www.dradio.de/rss/podcast/sendungen/wirtschaftundgesellschaft/",
+ "http://www.dradio.de/rss/podcast/sendungen/filmederwoche/",
+ "http://www.blacksweetstories.com/feed/podcast/",
+ "http://feeds.5by5.tv/buildanalyze",
+ "http://bitlove.org/ranzzeit/ranz/feed",
+ "http://bitlove.org/importthis/mp3/feed",
+ "http://bitlove.org/astro/youtube/feed",
+ "http://bitlove.org/channelcast/channelcast/feed",
+ "http://bitlove.org/cccb/chaosradio/feed",
+ "http://bitlove.org/astro/bitlove-show/feed",
+ "http://feeds.thisamericanlife.org/talpodcast",
+ "http://www.casasola.de/137b/1337motiv/1337motiv.xml",
+ "http://alternativlos.org/ogg.rss", "http://www.bitsundso.de/feed",
+ "http://www.gamesundso.de/feed/",
+ "http://feeds.feedburner.com/cre-podcast",
+ "http://feeds.feedburner.com/NotSafeForWorkPodcast",
+ "http://feeds.feedburner.com/mobile-macs-podcast",
+ "http://www.gamesundso.de/feed/",
+ "http://feeds.feedburner.com/DerLautsprecher",
+ "http://feeds.feedburner.com/raumzeit-podcast",
+ "http://feeds.feedburner.com/TheLunaticFringe",
+ "http://feeds.feedburner.com/Kuechenradioorg",
+ "http://feeds.feedburner.com/Medienradio_Podcast_RSS",
+ "http://feeds.feedburner.com/wrint/wrint",
+ "http://retrozirkel.de/episodes.mp3.rss",
+ "http://trackback.fritz.de/?feed=podcast",
+ "http://feeds.feedburner.com/linuxoutlaws-ogg",
+ "http://www.mevio.com/feeds/noagenda.xml",
+ "http://podcast.hr2.de/derTag/podcast.xml",
+ "http://feeds.feedburner.com/thechangelog",
+ "http://leoville.tv/podcasts/floss.xml",
+ "http://www.radiotux.de/index.php?/feeds/index.rss2",
+ "http://megamagis.ch/episodes.mp3.rss",
+ "http://www.eurogamer.net/rss/eurogamer_podcast_itunes.rss",
+ "http://bobsonbob.de/?feed=rss2",
+ "http://www.blacksweetstories.com/feed/podcast/",
+ "http://www.eurogamer.net/rss/eurogamer_podcast_itunes.rss",
+ "http://diehoppeshow.de/podcast/feed.xml",
+ "http://feeds.feedburner.com/ThisIsMyNextPodcast?format=xml",
+ "http://bitlove.org/343max/maerchenstunde/feed",
+ "http://bitlove.org/343max/wmr-aac/feed",
+ "http://bitlove.org/343max/wmr-mp3/feed",
+ "http://bitlove.org/343max/wmr-oga/feed",
+ "http://bitlove.org/adamc1999/noagenda/feed",
+ "http://bitlove.org/alexbrueckel/normalzeit_podcast/feed",
+ "http://bitlove.org/alexbrueckel/normalzeit_podcast_mp3/feed",
+ "http://bitlove.org/alexbrueckel/tisch3-podcast/feed",
+ "http://bitlove.org/alexolma/iphoneblog/feed",
"http://www.cczwei.de/rss_tvissues.php" };
}