Merge branch 'queue_update' into develop

This commit is contained in:
daniel oeh 2013-03-10 19:40:50 +01:00
commit fc156782f4
26 changed files with 1043 additions and 449 deletions

View File

@ -23,6 +23,7 @@
<uses-feature
android:name="android.hardware.screen.portrait"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:name="de.danoeh.antennapod.PodcastApp"
@ -347,6 +348,11 @@
android:configChanges="orientation"
android:label="@string/organize_queue_label" >
</activity>
<receiver android:name=".receiver.ConnectivityActionReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
</application>
</manifest>

View File

@ -32,8 +32,8 @@
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="4dp"
android:layout_marginTop="8dp"
android:layout_toLeftOf="@id/butAction"
android:layout_toRightOf="@id/imgvFeedimage"
android:ellipsize="end"
@ -81,21 +81,15 @@
android:layout_marginTop="4dp"
android:layout_toLeftOf="@id/butAction" />
<TextView
android:id="@+id/statusUnread"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="8dp"
android:background="@color/status_unread"
android:gravity="center"
android:minWidth="@dimen/status_indicator_width"
android:text="@string/new_label"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="@dimen/text_size_micro"
android:textStyle="bold" />
<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" />
<ImageView
android:id="@+id/statusPlaying"
@ -109,21 +103,4 @@
android:padding="2dp"
android:src="@drawable/av_play_dark" />
<TextView
android:id="@+id/statusInProgress"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="8dp"
android:background="@color/status_progress"
android:gravity="center"
android:minWidth="@dimen/status_indicator_width"
android:paddingLeft="2dp"
android:paddingRight="2dp"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="@dimen/text_size_micro"
android:textStyle="bold" />
</RelativeLayout>

View File

@ -87,6 +87,19 @@
android:textColor="?android:attr/textColorTertiary"
android:textSize="@dimen/text_size_micro" />
<ProgressBar
android:id="@+id/pbar_episode_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_below="@id/txtvPublished"
android:layout_marginBottom="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginTop="2dp"
android:layout_toLeftOf="@id/imgvType"
android:layout_toRightOf="@id/txtvLenSize" />
<ImageButton
android:id="@id/butAction"
android:layout_width="48dp"
@ -131,21 +144,4 @@
android:padding="2dp"
android:src="@drawable/av_play_dark" />
<TextView
android:id="@+id/statusInProgress"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="8dp"
android:background="@color/status_progress"
android:gravity="center"
android:minWidth="@dimen/status_indicator_width"
android:paddingLeft="2dp"
android:paddingRight="2dp"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="@dimen/text_size_micro"
android:textStyle="bold" />
</RelativeLayout>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
<item android:id="@id/skip_episode_item" android:title="@string/skip_episode_label" android:showAsAction="collapseActionView"></item><item
android:id="@+id/download_item"
android:icon="?attr/av_download"
android:showAsAction="ifRoom"
@ -67,5 +67,6 @@
android:showAsAction="collapseActionView"
android:title="@string/support_label">
</item>
</menu>

View File

@ -1,7 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/disable_sleeptimer_item" android:icon="?attr/device_access_time" android:title="@string/sleep_timer_label" android:showAsAction="always"></item><item android:id="@+id/set_sleeptimer_item" android:showAsAction="collapseActionView" android:title="@string/set_sleeptimer_label"></item><item
<item
android:id="@+id/disable_sleeptimer_item"
android:icon="?attr/device_access_time"
android:showAsAction="always"
android:title="@string/sleep_timer_label">
</item>
<item
android:id="@+id/set_sleeptimer_item"
android:showAsAction="collapseActionView"
android:title="@string/set_sleeptimer_label">
</item>
<item
android:id="@+id/share_link_item"
android:showAsAction="collapseActionView"
android:title="@string/share_link_label">
@ -19,7 +30,10 @@
android:title="@string/support_label"
android:visible="false">
</item>
<item
android:id="@id/skip_episode_item"
android:showAsAction="collapseActionView"
android:title="@string/skip_episode_label"
android:visible="true"/>
</menu>

View File

@ -21,6 +21,23 @@
<item>24</item>
</string-array>
<string-array name="episode_cache_size">
<item>10</item>
<item>20</item>
<item>40</item>
<item>60</item>
<item>80</item>
<item>100</item>
</string-array>
<string-array name="autodl_select_networks_default_entries">
<item>N/A</item>
</string-array>
<string-array name="autodl_select_networks_default_values">
<item>0</item>
</string-array>
<string-array name="theme_options">
<item>Light</item>
<item>Dark</item>

View File

@ -14,5 +14,6 @@
<item name="share_url_item" type="id"/>
<item name="organize_queue_item" type="id"/>
<item name="drag_handle" type="id"/>
<item name="skip_episode_item" type="id"/>
</resources>

View File

@ -7,6 +7,7 @@
<string name="podcasts_label">PODCASTS</string>
<string name="episodes_label">EPISODES</string>
<string name="new_label">New</string>
<string name="waiting_list_label">Waiting list</string>
<string name="settings_label">Settings</string>
<string name="add_new_feed_label">Add a new Feed</string>
<string name="downloads_label">Downloads</string>
@ -70,6 +71,7 @@
<string name="support_label">Flattr this</string>
<string name="enqueue_all_new">Enqueue all</string>
<string name="download_all">Download all</string>
<string name="skip_episode_label">Skip episode</string>
<!-- Download messages and labels -->
<string name="download_successful">Download successful</string>
@ -165,15 +167,16 @@
<string name="pref_flattr_this_app_sum">Support the development of AntennaPod by flattring it. Thanks!</string>
<string name="pref_revokeAccess_title">Revoke access</string>
<string name="pref_revokeAccess_sum">Revoke the access permission to your flattr account for this app.</string>
<string name="pref_autoQueue_title">Auto-enqueue</string>
<string name="pref_autoQueue_sum">Add an episode to the queue when you start to download it.</string>
<string name="pref_display_only_episodes_title">Display only episodes</string>
<string name="pref_display_only_episodes_sum">Display only items which also have an episode.</string>
<string name="user_interface_label">User Interface</string>
<string name="pref_auto_delete_title">Auto-delete</string>
<string name="pref_auto_delete_sum">Delete an episode when playback completes or when it is removed from the queue.</string>
<string name="pref_set_theme_title">Select theme</string>
<string name="pref_set_theme_sum">Change the appearance of AntennaPod.</string>
<string name="pref_automatic_download_title">Automatic download</string>
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
<string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string>
<string name="pref_autodl_wifi_filter_sum">Allow automatic download only for selected Wi-Fi networks.</string>
<string name="pref_episode_cache_title">Episode cache</string>
<!-- Search -->
<string name="search_hint">Search for Feeds or Episodes</string>

View File

@ -17,7 +17,6 @@
android:key="prefFollowQueue"
android:summary="@string/pref_followQueue_sum"
android:title="@string/pref_followQueue_title" />
<CheckBoxPreference android:key="prefAutoDelete" android:summary="@string/pref_auto_delete_sum" android:title="@string/pref_auto_delete_title"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/network_pref" >
@ -35,7 +34,10 @@
android:key="prefMobileUpdate"
android:summary="@string/pref_mobileUpdate_sum"
android:title="@string/pref_mobileUpdate_title" />
<CheckBoxPreference android:summary="@string/pref_autoQueue_sum" android:defaultValue="true" android:key="prefAutoQueue" android:title="@string/pref_autoQueue_title"/>
<ListPreference android:defaultValue="20" android:entries="@array/episode_cache_size" android:key="prefEpisodeCacheSize" android:title="@string/pref_episode_cache_title" android:entryValues="@array/episode_cache_size"/><PreferenceScreen android:summary="@string/pref_automatic_download_sum" android:key="prefAutoDownloadSettings" android:title="@string/pref_automatic_download_title">
<CheckBoxPreference android:key="prefEnableAutoDownloadWifiFilter" android:title="@string/pref_autodl_wifi_filter_title" android:summary="@string/pref_autodl_wifi_filter_sum"/>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:title="@string/flattr_settings_label" >
<PreferenceScreen

View File

@ -128,6 +128,11 @@ public abstract class MediaplayerActivity extends SherlockFragmentActivity
public void onShutdownNotification() {
finish();
}
@Override
public void onPlaybackEnd() {
finish();
}
};
}
@ -227,7 +232,7 @@ public abstract class MediaplayerActivity extends SherlockFragmentActivity
media != null && media.getWebsiteLink() != null);
menu.findItem(R.id.visit_website_item).setVisible(
media != null && media.getWebsiteLink() != null);
menu.findItem(R.id.skip_episode_item).setVisible(media != null);
boolean sleepTimerSet = controller.sleepTimerActive();
boolean sleepTimerNotSet = controller.sleepTimerNotActive();
menu.findItem(R.id.set_sleeptimer_item).setVisible(sleepTimerNotSet);
@ -303,6 +308,10 @@ public abstract class MediaplayerActivity extends SherlockFragmentActivity
case R.id.share_link_item:
ShareUtils.shareLink(this, media.getWebsiteLink());
break;
case R.id.skip_episode_item:
sendBroadcast(new Intent(
PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
break;
default:
return false;

View File

@ -72,7 +72,10 @@ public class OrganizeQueueActivity extends SherlockListActivity {
@Override
public void drop(int from, int to) {
FeedManager manager = FeedManager.getInstance();
manager.moveQueueItem(OrganizeQueueActivity.this, from, to, false);
int offset = (manager.firstQueueItemIsPlaying()) ? 1 : 0;
manager.moveQueueItem(OrganizeQueueActivity.this, from + offset, to
+ offset, false);
adapter.notifyDataSetChanged();
}
};
@ -82,6 +85,7 @@ public class OrganizeQueueActivity extends SherlockListActivity {
@Override
public void remove(int which) {
FeedManager manager = FeedManager.getInstance();
manager.removeQueueItem(OrganizeQueueActivity.this,
(FeedItem) getListAdapter().getItem(which));
}
@ -110,9 +114,15 @@ public class OrganizeQueueActivity extends SherlockListActivity {
}
}
/**
* WARNING: If the PlaybackService is playing an episode from the queue,
* this list adapter will ignore the first item in the list to make sure
* that the position of the first queue item cannot be changed.
*/
private static class OrganizeAdapter extends BaseAdapter {
private Context context;
private FeedManager manager = FeedManager.getInstance();
public OrganizeAdapter(Context context) {
super();
@ -164,13 +174,22 @@ public class OrganizeQueueActivity extends SherlockListActivity {
@Override
public int getCount() {
return FeedManager.getInstance().getQueueSize(true);
int queueSize = manager.getQueueSize(true);
if (manager.firstQueueItemIsPlaying()) {
return queueSize - 1;
} else {
return queueSize;
}
}
@Override
public FeedItem getItem(int position) {
return FeedManager.getInstance()
.getQueueItemAtIndex(position, true);
if (manager.firstQueueItemIsPlaying() && position < getCount()) {
return manager.getQueueItemAtIndex(position + 1, true);
} else {
return manager.getQueueItemAtIndex(position, true);
}
}
@Override

View File

@ -1,13 +1,22 @@
package de.danoeh.antennapod.activity;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources.Theme;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceScreen;
import android.util.Log;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
@ -32,6 +41,9 @@ public class PreferenceActivity extends SherlockPreferenceActivity {
private static final String PREF_OPML_EXPORT = "prefOpmlExport";
private static final String PREF_ABOUT = "prefAbout";
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
private CheckBoxPreference[] selectedNetworks;
@SuppressWarnings("deprecation")
@Override
@ -102,27 +114,69 @@ public class PreferenceActivity extends SherlockPreferenceActivity {
return true;
}
});
findPreference(UserPreferences.PREF_THEME).setOnPreferenceChangeListener(
new OnPreferenceChangeListener() {
findPreference(UserPreferences.PREF_THEME)
.setOnPreferenceChangeListener(
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
Intent i = getIntent();
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NEW_TASK);
finish();
startActivity(i);
return true;
}
});
@Override
public boolean onPreferenceChange(
Preference preference, Object newValue) {
Intent i = getIntent();
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NEW_TASK);
finish();
startActivity(i);
return true;
}
});
findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
.setOnPreferenceChangeListener(
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(
Preference preference, Object newValue) {
if (newValue instanceof Boolean) {
setSelectedNetworksEnabled((Boolean) newValue);
return true;
} else {
return false;
}
}
});
findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE)
.setOnPreferenceChangeListener(
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(
Preference preference, Object newValue) {
if (newValue instanceof String) {
setEpisodeCacheSizeText(Integer
.valueOf((String) newValue));
}
return true;
}
});
buildAutodownloadSelectedNetworsPreference();
setSelectedNetworksEnabled(UserPreferences
.isEnableAutodownloadWifiFilter());
}
private void setSelectedNetworksEnabled(boolean b) {
if (selectedNetworks != null) {
for (Preference p : selectedNetworks) {
p.setEnabled(b);
}
}
}
@Override
protected void onResume() {
super.onResume();
checkItemVisibility();
setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize());
setDataFolderText();
}
@ -136,6 +190,12 @@ public class PreferenceActivity extends SherlockPreferenceActivity {
}
private void setEpisodeCacheSizeText(int cacheSize) {
findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setSummary(
Integer.toString(cacheSize)
+ getString(R.string.episodes_suffix));
}
private void setDataFolderText() {
File f = UserPreferences.getDataFolder(this, null);
if (f != null) {
@ -180,4 +240,81 @@ public class PreferenceActivity extends SherlockPreferenceActivity {
}
}
private void buildAutodownloadSelectedNetworsPreference() {
if (selectedNetworks != null) {
clearAutodownloadSelectedNetworsPreference();
}
// get configured networks
WifiManager wifiservice = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> networks = wifiservice.getConfiguredNetworks();
if (networks != null) {
selectedNetworks = new CheckBoxPreference[networks.size()];
List<String> prefValues = Arrays.asList(UserPreferences
.getAutodownloadSelectedNetworks());
PreferenceScreen prefScreen = (PreferenceScreen) findPreference(AUTO_DL_PREF_SCREEN);
OnPreferenceClickListener clickListener = new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference instanceof CheckBoxPreference) {
String key = preference.getKey();
ArrayList<String> prefValuesList = new ArrayList<String>(
Arrays.asList(UserPreferences
.getAutodownloadSelectedNetworks()));
boolean newValue = ((CheckBoxPreference) preference)
.isChecked();
if (AppConfig.DEBUG)
Log.d(TAG, "Selected network " + key
+ ". New state: " + newValue);
int index = prefValuesList.indexOf(key);
if (index >= 0 && newValue == false) {
// remove network
prefValuesList.remove(index);
} else if (index < 0 && newValue == true) {
prefValuesList.add(key);
}
UserPreferences.setAutodownloadSelectedNetworks(
PreferenceActivity.this, prefValuesList
.toArray(new String[prefValuesList
.size()]));
return true;
} else {
return false;
}
}
};
// create preference for each known network. attach listener and set
// value
for (int i = 0; i < networks.size(); i++) {
WifiConfiguration config = networks.get(i);
CheckBoxPreference pref = new CheckBoxPreference(this);
String key = Integer.toString(config.networkId);
pref.setTitle(config.SSID);
pref.setKey(key);
pref.setOnPreferenceClickListener(clickListener);
pref.setPersistent(false);
pref.setChecked(prefValues.contains(key));
selectedNetworks[i] = pref;
prefScreen.addPreference(pref);
}
} else {
Log.e(TAG, "Couldn't get list of configure Wi-Fi networks");
}
}
private void clearAutodownloadSelectedNetworsPreference() {
if (selectedNetworks != null) {
PreferenceScreen prefScreen = (PreferenceScreen) findPreference(AUTO_DL_PREF_SCREEN);
for (int i = 0; i < selectedNetworks.length; i++) {
if (selectedNetworks[i] != null) {
prefScreen.removePreference(selectedNetworks[i]);
}
}
}
}
}

View File

@ -9,6 +9,7 @@ import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.asynctask.ImageLoader;
@ -89,10 +90,8 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
.findViewById(R.id.butAction);
holder.statusPlaying = (View) convertView
.findViewById(R.id.statusPlaying);
holder.statusUnread = (View) convertView
.findViewById(R.id.statusUnread);
holder.statusInProgress = (TextView) convertView
.findViewById(R.id.statusInProgress);
holder.episodeProgress = (ProgressBar) convertView
.findViewById(R.id.pbar_episode_progress);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
@ -100,41 +99,53 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
holder.title.setText(item.getTitle());
holder.feedTitle.setText(item.getFeed().getTitle());
FeedItem.State state = item.getState();
if (groupPosition == GROUP_POS_QUEUE) {
FeedItem.State state = item.getState();
switch (state) {
case PLAYING:
holder.statusPlaying.setVisibility(View.VISIBLE);
holder.statusUnread.setVisibility(View.GONE);
holder.statusInProgress.setVisibility(View.GONE);
holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case IN_PROGRESS:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.GONE);
holder.statusInProgress.setVisibility(View.VISIBLE);
holder.statusInProgress.setText(Converter
.getDurationStringLong(item.getMedia().getPosition()));
holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case NEW:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.VISIBLE);
holder.statusInProgress.setVisibility(View.GONE);
holder.episodeProgress.setVisibility(View.GONE);
break;
default:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.GONE);
holder.statusInProgress.setVisibility(View.GONE);
holder.episodeProgress.setVisibility(View.GONE);
break;
}
} else {
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.GONE);
holder.statusInProgress.setVisibility(View.GONE);
holder.episodeProgress.setVisibility(View.GONE);
}
FeedMedia media = item.getMedia();
if (media != null) {
if (state == FeedItem.State.PLAYING
|| state == FeedItem.State.IN_PROGRESS) {
if (media.getDuration() > 0) {
holder.episodeProgress.setProgress((int) (((double) media
.getPosition()) / media.getDuration() * 100));
holder.lenSize.setText(Converter
.getDurationStringLong(media.getDuration()
- media.getPosition()));
}
} else if (!media.isDownloaded()) {
holder.lenSize.setText(context.getString(R.string.size_prefix)
+ Converter.byteToString(media.getSize()));
} else {
holder.lenSize.setText(context
.getString(R.string.length_prefix)
+ Converter.getDurationStringLong(media.getDuration()));
}
TypedArray drawables = context.obtainStyledAttributes(new int[] {
R.attr.av_download, R.attr.navigation_refresh });
holder.lenSize.setVisibility(View.VISIBLE);
@ -144,20 +155,15 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
holder.downloadStatus.setImageDrawable(drawables
.getDrawable(1));
} else {
holder.downloadStatus.setVisibility(View.GONE);
holder.downloadStatus.setVisibility(View.INVISIBLE);
}
holder.lenSize.setText(context.getString(R.string.size_prefix)
+ Converter.byteToString(media.getSize()));
} else {
holder.downloadStatus.setVisibility(View.VISIBLE);
holder.downloadStatus
.setImageDrawable(drawables.getDrawable(0));
holder.lenSize.setText(context
.getString(R.string.length_prefix)
+ Converter.getDurationStringLong(media.getDuration()));
}
} else {
holder.downloadStatus.setVisibility(View.GONE);
holder.downloadStatus.setVisibility(View.INVISIBLE);
holder.lenSize.setVisibility(View.INVISIBLE);
}
@ -188,9 +194,8 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
ImageView downloadStatus;
ImageView feedImage;
ImageButton butAction;
View statusUnread;
View statusPlaying;
TextView statusInProgress;
ProgressBar episodeProgress;
}
@Override
@ -230,7 +235,7 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
headerString += " (" + getChildrenCount(GROUP_POS_QUEUE) + ")";
}
} else {
headerString = context.getString(R.string.new_label);
headerString = context.getString(R.string.waiting_list_label);
if (manager.getUnreadItemsSize(true) > 0) {
headerString += " (" + getChildrenCount(GROUP_POS_UNREAD) + ")";
}

View File

@ -12,10 +12,12 @@ import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.feed.MediaType;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.util.Converter;
@ -72,8 +74,8 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
.findViewById(R.id.statusPlaying);
holder.statusUnread = (View) convertView
.findViewById(R.id.statusUnread);
holder.statusInProgress = (TextView) convertView
.findViewById(R.id.statusInProgress);
holder.episodeProgress = (ProgressBar) convertView
.findViewById(R.id.pbar_episode_progress);
convertView.setTag(holder);
} else {
@ -99,24 +101,22 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
case PLAYING:
holder.statusPlaying.setVisibility(View.VISIBLE);
holder.statusUnread.setVisibility(View.GONE);
holder.statusInProgress.setVisibility(View.GONE);
holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case IN_PROGRESS:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.GONE);
holder.statusInProgress.setVisibility(View.VISIBLE);
holder.statusInProgress.setText(Converter
.getDurationStringLong(item.getMedia().getPosition()));
holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case NEW:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.VISIBLE);
holder.statusInProgress.setVisibility(View.GONE);
holder.episodeProgress.setVisibility(View.GONE);
break;
default:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.GONE);
holder.statusInProgress.setVisibility(View.GONE);
holder.episodeProgress.setVisibility(View.GONE);
break;
}
@ -126,13 +126,36 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
System.currentTimeMillis(), DateFormat.MEDIUM,
DateFormat.SHORT));
if (item.getMedia() == null) {
FeedMedia media = item.getMedia();
if (media == null) {
holder.downloaded.setVisibility(View.GONE);
holder.downloading.setVisibility(View.GONE);
holder.inPlaylist.setVisibility(View.GONE);
holder.type.setVisibility(View.GONE);
holder.lenSize.setVisibility(View.GONE);
} else {
if (state == FeedItem.State.PLAYING
|| state == FeedItem.State.IN_PROGRESS) {
if (media.getDuration() > 0) {
holder.episodeProgress
.setProgress((int) (((double) media
.getPosition()) / media.getDuration() * 100));
holder.lenSize.setText(Converter
.getDurationStringLong(media.getDuration()
- media.getPosition()));
}
} else if (!media.isDownloaded()) {
holder.lenSize.setText(getContext().getString(
R.string.size_prefix)
+ Converter.byteToString(media.getSize()));
} else {
holder.lenSize.setText(getContext().getString(
R.string.length_prefix)
+ Converter.getDurationStringLong(media
.getDuration()));
}
holder.lenSize.setVisibility(View.VISIBLE);
if (FeedManager.getInstance().isInQueue(item)) {
holder.inPlaylist.setVisibility(View.VISIBLE);
@ -140,17 +163,8 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
holder.inPlaylist.setVisibility(View.GONE);
}
if (item.getMedia().isDownloaded()) {
holder.lenSize.setText(convertView.getResources()
.getString(R.string.length_prefix)
+ Converter.getDurationStringLong(item.getMedia()
.getDuration()));
holder.downloaded.setVisibility(View.VISIBLE);
} else {
holder.lenSize
.setText(convertView.getResources().getString(
R.string.size_prefix)
+ Converter.byteToString(item.getMedia()
.getSize()));
holder.downloaded.setVisibility(View.GONE);
}
@ -200,7 +214,7 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
ImageButton butAction;
View statusUnread;
View statusPlaying;
TextView statusInProgress;
ProgressBar episodeProgress;
}
public int getSelectedItemIndex() {

View File

@ -213,9 +213,7 @@ public class FeedItem extends FeedComponent {
private boolean isPlaying() {
if (media != null) {
if (PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == media.getId()) {
return true;
}
return media.isPlaying();
}
return false;
}

View File

@ -29,6 +29,7 @@ import de.danoeh.antennapod.storage.PodDBAdapter;
import de.danoeh.antennapod.util.DownloadError;
import de.danoeh.antennapod.util.EpisodeFilter;
import de.danoeh.antennapod.util.FeedtitleComparator;
import de.danoeh.antennapod.util.NetworkUtils;
import de.danoeh.antennapod.util.comparator.DownloadStatusComparator;
import de.danoeh.antennapod.util.comparator.FeedItemPubdateComparator;
import de.danoeh.antennapod.util.comparator.PlaybackCompletionDateComparator;
@ -111,7 +112,8 @@ public class FeedManager {
/**
* Play FeedMedia and start the playback service + launch Mediaplayer
* Activity.
* Activity. The FeedItem belonging to the media is moved to the top of the
* queue.
*
* @param context
* for starting the playbackservice
@ -149,9 +151,14 @@ public class FeedManager {
context.startActivity(PlaybackService.getPlayerActivityIntent(
context, media));
}
if (queue.contains(media.getItem())) {
moveQueueItem(context, queue.indexOf(media.getItem()), 0, true);
} else {
addQueueItemAt(context, media.getItem(), 0);
}
} catch (MediaFileNotFoundException e) {
e.printStackTrace();
if (PlaybackPreferences.getLastPlayedId() == media.getId()) {
if (media.isPlaying()) {
context.sendBroadcast(new Intent(
PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
@ -173,14 +180,20 @@ public class FeedManager {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
if (media.getId() == PlaybackPreferences.getLastPlayedId()) {
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_STREAM, true);
editor.commit();
}
if (PlaybackPreferences.getLastPlayedId() == media.getId()) {
context.sendBroadcast(new Intent(
PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA) {
if (media.getId() == PlaybackPreferences
.getCurrentlyPlayingFeedMediaId()) {
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(
PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM,
true);
editor.commit();
}
if (PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == media
.getId()) {
context.sendBroadcast(new Intent(
PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
}
}
if (AppConfig.DEBUG)
@ -192,12 +205,13 @@ public class FeedManager {
public void deleteFeed(final Context context, final Feed feed) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context.getApplicationContext());
if (PlaybackPreferences.getLastPlayedFeedId() == feed.getId()) {
if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA
&& PlaybackPreferences.getLastPlayedFeedId() == feed.getId()) {
context.sendBroadcast(new Intent(
PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
SharedPreferences.Editor editor = prefs.edit();
editor.putLong(PlaybackPreferences.PREF_LAST_PLAYED_ID, -1);
editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID, -1);
editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
-1);
editor.commit();
}
@ -560,11 +574,26 @@ public class FeedManager {
}
}
/** Downloads FeedItems if they have not been downloaded yet. */
public void downloadFeedItem(final Context context, FeedItem... items)
throws DownloadRequestException {
List<FeedItem> addToQueue = new ArrayList<FeedItem>();
downloadFeedItem(true, context, items);
}
/** Downloads FeedItems if they have not been downloaded yet. */
private void downloadFeedItem(boolean performAutoCleanup,
final Context context, final FeedItem... items)
throws DownloadRequestException {
if (performAutoCleanup) {
new Thread() {
@Override
public void run() {
performAutoCleanup(context,
getPerformAutoCleanupArgs(items.length));
}
}.start();
}
for (FeedItem item : items) {
if (item.getMedia() != null
&& !requester.isDownloadingFile(item.getMedia())
@ -584,15 +613,165 @@ public class FeedManager {
} else {
requester.downloadMedia(context, item.getMedia());
}
addToQueue.add(item);
}
}
if (UserPreferences.isAutoQueue()) {
addQueueItem(context,
addToQueue.toArray(new FeedItem[addToQueue.size()]));
}
/**
* This method will try to download undownloaded items in the queue or the
* unread items list. If not enough space is available, an episode cleanup
* will be performed first.
*/
public void autodownloadUndownloadedItems(Context context) {
if (AppConfig.DEBUG)
Log.d(TAG, "Performing auto-dl of undownloaded episodes");
if (NetworkUtils.autodownloadNetworkAvailable(context)) {
int undownloadedEpisodes = getNumberOfUndownloadedEpisodes();
int downloadedEpisodes = getNumberOfDownloadedEpisodes();
int deletedEpisodes = performAutoCleanup(context,
getPerformAutoCleanupArgs(undownloadedEpisodes));
int episodeSpaceLeft = undownloadedEpisodes;
if (UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
+ undownloadedEpisodes) {
episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
- (downloadedEpisodes - deletedEpisodes);
}
List<FeedItem> itemsToDownload = new ArrayList<FeedItem>();
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
for (FeedItem item : queue) {
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
itemsToDownload.add(item);
episodeSpaceLeft--;
undownloadedEpisodes--;
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
break;
}
}
}
}
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
for (FeedItem item : unreadItems) {
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
itemsToDownload.add(item);
episodeSpaceLeft--;
undownloadedEpisodes--;
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
break;
}
}
}
}
if (AppConfig.DEBUG)
Log.d(TAG, "Enqueueing " + itemsToDownload.size()
+ " items for download");
try {
downloadFeedItem(false, context,
itemsToDownload.toArray(new FeedItem[itemsToDownload
.size()]));
} catch (DownloadRequestException e) {
e.printStackTrace();
}
}
}
/**
* This method will determine the number of episodes that have to be deleted
* depending on a given number of episodes.
*
* @return The argument that has to be passed to performAutoCleanup() so
* that the number of episodes fits into the episode cache.
* */
private int getPerformAutoCleanupArgs(final int episodeNumber) {
if (episodeNumber >= 0) {
int downloadedEpisodes = getNumberOfDownloadedEpisodes();
if (downloadedEpisodes + episodeNumber >= UserPreferences
.getEpisodeCacheSize()) {
return downloadedEpisodes + episodeNumber
- UserPreferences.getEpisodeCacheSize();
}
}
return 0;
}
/**
* Performs an auto-cleanup so that the number of downloaded episodes is
* below or equal to the episode cache size. The method will be executed in
* the caller's thread.
*/
public void performAutoCleanup(Context context) {
performAutoCleanup(context, getPerformAutoCleanupArgs(0));
}
/**
* This method will try to delete a given number of episodes. An episode
* will only be deleted if it is not in the queue.
*
* @return The number of episodes that were actually deleted
* */
private int performAutoCleanup(Context context, final int episodeNumber) {
int counter = 0;
int episodesLeft = episodeNumber;
feedloop: for (Feed feed : feeds) {
for (FeedItem item : feed.getItems()) {
if (item.hasMedia() && item.getMedia().isDownloaded()) {
if (!isInQueue(item) && item.isRead()) {
deleteFeedMedia(context, item.getMedia());
counter++;
episodesLeft--;
if (episodesLeft == 0) {
break feedloop;
}
}
}
}
}
if (AppConfig.DEBUG)
Log.d(TAG, String.format(
"Auto-delete deleted %d episodes (%d requested)", counter,
episodeNumber));
return counter;
}
/**
* Counts items in the queue and the unread items list which haven't been
* downloaded yet.
*/
private int getNumberOfUndownloadedEpisodes() {
int counter = 0;
for (FeedItem item : queue) {
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
counter++;
}
}
for (FeedItem item : unreadItems) {
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
counter++;
}
}
return counter;
}
/** Counts all downloaded items. */
private int getNumberOfDownloadedEpisodes() {
int counter = 0;
for (Feed feed : feeds) {
for (FeedItem item : feed.getItems()) {
if (item.hasMedia() && item.getMedia().isDownloaded()) {
counter++;
}
}
}
if (AppConfig.DEBUG)
Log.d(TAG, "Number of downloaded episodes: " + counter);
return counter;
}
/**
* Enqueues all items that are currently in the unreadItems list and marks
* them as 'read'.
@ -605,7 +784,49 @@ public class FeedManager {
}
}
/** Adds FeedItems to the queue if they are not in the queue yet. */
/**
* Adds a feeditem to the queue at the specified index if it is not in the
* queue yet. The item is marked as 'read'.
*/
public void addQueueItemAt(final Context context, final FeedItem item,
final int index) {
contentChanger.post(new Runnable() {
@Override
public void run() {
if (!queue.contains(item)) {
queue.add(index, item);
if (!item.isRead()) {
markItemRead(context, item, true, false);
}
}
eventDist.sendQueueUpdateBroadcast();
dbExec.execute(new Runnable() {
@Override
public void run() {
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
adapter.setQueue(queue);
adapter.close();
}
});
new Thread() {
@Override
public void run() {
autodownloadUndownloadedItems(context);
}
}.start();
}
});
}
/**
* Adds FeedItems to the queue if they are not in the queue yet. The items
* are marked as 'read'.
*/
public void addQueueItem(final Context context, final FeedItem... items) {
if (items.length > 0) {
contentChanger.post(new Runnable() {
@ -615,6 +836,9 @@ public class FeedManager {
for (FeedItem item : items) {
if (!queue.contains(item)) {
queue.add(item);
if (!item.isRead()) {
markItemRead(context, item, true, false);
}
}
}
eventDist.sendQueueUpdateBroadcast();
@ -628,6 +852,12 @@ public class FeedManager {
adapter.close();
}
});
new Thread() {
@Override
public void run() {
autodownloadUndownloadedItems(context);
}
}.start();
}
});
}
@ -673,14 +903,12 @@ public class FeedManager {
if (removed) {
adapter.setQueue(queue);
}
}
/** Removes a FeedItem from the queue. */
public void removeQueueItem(final Context context, FeedItem item) {
boolean removed = queue.remove(item);
if (removed) {
autoDeleteIfPossible(context, item.getMedia());
dbExec.execute(new Runnable() {
@Override
@ -693,45 +921,13 @@ public class FeedManager {
});
}
eventDist.sendQueueUpdateBroadcast();
}
/**
* Delete the episode of this FeedMedia object if auto-delete is enabled and
* it is not the last played media or it is the last played media and
* playback has been completed.
*/
public void autoDeleteIfPossible(Context context, FeedMedia media) {
if (media != null) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context
.getApplicationContext());
if (UserPreferences.isAutoDelete()) {
if ((media.getId() != PlaybackPreferences.getLastPlayedId())
&& ((media.getId() != PlaybackPreferences
.getAutoDeleteMediaId()) || (media.getId() == PlaybackPreferences
.getAutoDeleteMediaId() && PlaybackPreferences
.isAutoDeleteMediaPlaybackCompleted()))) {
if (AppConfig.DEBUG)
Log.d(TAG, "Performing auto-cleanup");
deleteFeedMedia(context, media);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong(
PlaybackPreferences.PREF_AUTODELETE_MEDIA_ID, -1);
editor.commit();
} else {
if (AppConfig.DEBUG)
Log.d(TAG, "Didn't do auto-cleanup");
}
} else {
if (AppConfig.DEBUG)
Log.d(TAG, "Auto-delete preference is disabled");
new Thread() {
@Override
public void run() {
autodownloadUndownloadedItems(context);
}
} else {
Log.e(TAG, "Could not do auto-cleanup: media was null");
}
}.start();
eventDist.sendQueueUpdateBroadcast();
}
/**
@ -806,7 +1002,7 @@ public class FeedManager {
*
* @return The saved Feed with a database ID
*/
public Feed updateFeed(Context context, final Feed newFeed) {
public Feed updateFeed(final Context context, final Feed newFeed) {
// Look up feed in the feedslist
final Feed savedFeed = searchFeedByIdentifyingValue(newFeed
.getIdentifyingValue());
@ -853,6 +1049,12 @@ public class FeedManager {
savedFeed.setLastUpdate(newFeed.getLastUpdate());
savedFeed.setType(newFeed.getType());
setCompleteFeed(context, savedFeed);
new Thread() {
@Override
public void run() {
autodownloadUndownloadedItems(context);
}
}.start();
return savedFeed;
}
@ -1520,6 +1722,22 @@ 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.
* */
public boolean firstQueueItemIsPlaying() {
FeedManager manager = FeedManager.getInstance();
int queueSize = manager.getQueueSize(true);
if (queueSize == 0) {
return false;
} else {
FeedItem item = getQueueItemAtIndex(0, true);
return item.getState() == FeedItem.State.PLAYING;
}
}
/**
* Returns the number of unread items.
*

View File

@ -8,6 +8,7 @@ import android.content.SharedPreferences.Editor;
import android.os.Parcel;
import android.os.Parcelable;
import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.preferences.PlaybackPreferences;
import de.danoeh.antennapod.util.ChapterUtils;
import de.danoeh.antennapod.util.playback.Playable;
@ -103,6 +104,15 @@ public class FeedMedia extends FeedFile implements Playable {
return false;
}
/**
* Reads playback preferences to determine whether this FeedMedia object is
* currently being played.
*/
public boolean isPlaying() {
return PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA
&& PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == id;
}
@Override
public int getTypeAsInt() {
return FEEDFILETYPE_FEEDMEDIA;
@ -257,10 +267,6 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public void onPlaybackStart() {
if (getItem().isRead() == false) {
FeedManager.getInstance().markItemRead(PodcastApp.getInstance(),
getItem(), true, false);
}
}
@Override

View File

@ -162,6 +162,18 @@ public class ExternalPlayerFragment extends SherlockFragment {
}
}
@Override
public void onPlaybackEnd() {
if (fragmentLayout != null) {
fragmentLayout.setVisibility(View.GONE);
}
controller = setupPlaybackController();
if (butPlay != null) {
butPlay.setOnClickListener(controller
.newOnPlayButtonClickListener());
}
}
};
}

View File

@ -17,9 +17,6 @@ public class PlaybackPreferences implements
SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "PlaybackPreferences";
/** Contains the type of the media that was played last. */
public static final String PREF_LAST_PLAYED_ID = "de.danoeh.antennapod.preferences.lastPlayedId";
/**
* Contains the feed id of the currently playing item if it is a FeedMedia
* object.
@ -40,31 +37,19 @@ public class PlaybackPreferences implements
public static final String PREF_CURRENTLY_PLAYING_MEDIA = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
/** True if last played media was streamed. */
public static final String PREF_LAST_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
public static final String PREF_CURRENT_EPISODE_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
/** True if last played media was a video. */
public static final String PREF_LAST_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
/** True if playback of last played media has been completed. */
public static final String PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED = "de.danoeh.antennapod.preferences.lastPlaybackCompleted";
/**
* ID of the last played media which should be auto-deleted as soon as
* PREF_LAST_PLAYED_ID changes.
*/
public static final String PREF_AUTODELETE_MEDIA_ID = "de.danoeh.antennapod.preferences.autoDeleteMediaId";
public static final String PREF_CURRENT_EPISODE_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
/** Value of PREF_CURRENTLY_PLAYING_MEDIA if no media is playing. */
public static final long NO_MEDIA_PLAYING = -1;
private long lastPlayedId;
private long currentlyPlayingFeedId;
private long currentlyPlayingFeedMediaId;
private long currentlyPlayingMedia;
private boolean lastIsStream;
private boolean lastIsVideo;
private boolean autoDeleteMediaPlaybackCompleted;
private long autoDeleteMediaId;
private boolean currentEpisodeIsStream;
private boolean currentEpisodeIsVideo;
private static PlaybackPreferences instance;
private Context context;
@ -94,33 +79,18 @@ public class PlaybackPreferences implements
private void loadPreferences() {
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(context);
lastPlayedId = sp.getLong(PREF_LAST_PLAYED_ID, -1);
currentlyPlayingFeedId = sp.getLong(PREF_CURRENTLY_PLAYING_FEED_ID, -1);
currentlyPlayingFeedMediaId = sp.getLong(
PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
currentlyPlayingMedia = sp.getLong(PREF_CURRENTLY_PLAYING_MEDIA,
NO_MEDIA_PLAYING);
lastIsStream = sp.getBoolean(PREF_LAST_IS_STREAM, true);
lastIsVideo = sp.getBoolean(PREF_LAST_IS_VIDEO, false);
autoDeleteMediaPlaybackCompleted = sp.getBoolean(
PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED, false);
autoDeleteMediaId = sp.getLong(PREF_AUTODELETE_MEDIA_ID, -1);
currentEpisodeIsStream = sp.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
currentEpisodeIsVideo = sp.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
if (key.equals(PREF_LAST_PLAYED_ID)) {
lastPlayedId = sp.getLong(PREF_LAST_PLAYED_ID, -1);
long mediaId = sp.getLong(
PlaybackPreferences.PREF_AUTODELETE_MEDIA_ID, -1);
if (mediaId != -1) {
FeedManager manager = FeedManager.getInstance();
FeedMedia media = manager.getFeedMedia(mediaId);
if (media != null) {
manager.autoDeleteIfPossible(context, media);
}
}
} else if (key.equals(PREF_CURRENTLY_PLAYING_FEED_ID)) {
if (key.equals(PREF_CURRENTLY_PLAYING_FEED_ID)) {
currentlyPlayingFeedId = sp.getLong(PREF_CURRENTLY_PLAYING_FEED_ID,
-1);
@ -128,17 +98,12 @@ public class PlaybackPreferences implements
currentlyPlayingMedia = sp
.getLong(PREF_CURRENTLY_PLAYING_MEDIA, -1);
} else if (key.equals(PREF_LAST_IS_STREAM)) {
lastIsStream = sp.getBoolean(PREF_LAST_IS_STREAM, true);
} else if (key.equals(PREF_CURRENT_EPISODE_IS_STREAM)) {
currentEpisodeIsStream = sp.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
} else if (key.equals(PREF_LAST_IS_VIDEO)) {
lastIsVideo = sp.getBoolean(PREF_LAST_IS_VIDEO, false);
} else if (key.equals(PREF_CURRENT_EPISODE_IS_VIDEO)) {
currentEpisodeIsVideo = sp.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
} else if (key.equals(PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED)) {
autoDeleteMediaPlaybackCompleted = sp.getBoolean(
PREF_AUTODELETE_MEDIA_ID, false);
} else if (key.equals(PREF_AUTODELETE_MEDIA_ID)) {
autoDeleteMediaId = sp.getLong(PREF_AUTODELETE_MEDIA_ID, -1);
} else if (key.equals(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID)) {
currentlyPlayingFeedMediaId = sp.getLong(
PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
@ -152,14 +117,6 @@ public class PlaybackPreferences implements
}
}
public static long getLastPlayedId() {
instanceAvailable();
return instance.lastPlayedId;
}
public static long getAutoDeleteMediaId() {
return instance.autoDeleteMediaId;
}
public static long getLastPlayedFeedId() {
instanceAvailable();
@ -175,19 +132,14 @@ public class PlaybackPreferences implements
return instance.currentlyPlayingFeedMediaId;
}
public static boolean isLastIsStream() {
public static boolean getCurrentEpisodeIsStream() {
instanceAvailable();
return instance.lastIsStream;
return instance.currentEpisodeIsStream;
}
public static boolean isLastIsVideo() {
public static boolean getCurrentEpisodeIsVideo() {
instanceAvailable();
return instance.lastIsVideo;
}
public static boolean isAutoDeleteMediaPlaybackCompleted() {
instanceAvailable();
return instance.autoDeleteMediaPlaybackCompleted;
return instance.currentEpisodeIsVideo;
}
}

View File

@ -2,8 +2,11 @@ package de.danoeh.antennapod.preferences;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
@ -31,11 +34,13 @@ public class UserPreferences implements
public static final String PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY = "prefDownloadMediaOnWifiOnly";
public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall";
public static final String PREF_MOBILE_UPDATE = "prefMobileUpdate";
public static final String PREF_AUTO_QUEUE = "prefAutoQueue";
public static final String PREF_DISPLAY_ONLY_EPISODES = "prefDisplayOnlyEpisodes";
public static final String PREF_AUTO_DELETE = "prefAutoDelete";
public static final String PREF_THEME = "prefTheme";
public static final String PREF_DATA_FOLDER = "prefDataFolder";
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
private static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
private static UserPreferences instance;
private Context context;
@ -46,10 +51,12 @@ public class UserPreferences implements
private boolean downloadMediaOnWifiOnly;
private long updateInterval;
private boolean allowMobileUpdate;
private boolean autoQueue;
private boolean displayOnlyEpisodes;
private boolean autoDelete;
private int theme;
private boolean enableAutodownloadWifiFilter;
private String[] autodownloadSelectedNetworks;
private int episodeCacheSize;
private UserPreferences(Context context) {
this.context = context;
@ -86,10 +93,15 @@ public class UserPreferences implements
updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL,
"0"));
allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false);
autoQueue = sp.getBoolean(PREF_AUTO_QUEUE, true);
displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES, false);
autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
theme = readThemeValue(sp.getString(PREF_THEME, "0"));
enableAutodownloadWifiFilter = sp.getBoolean(
PREF_ENABLE_AUTODL_WIFI_FILTER, false);
autodownloadSelectedNetworks = StringUtils.split(
sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ',');
episodeCacheSize = Integer.valueOf(sp.getString(
PREF_EPISODE_CACHE_SIZE, "20"));
}
private int readThemeValue(String valueFromPrefs) {
@ -140,11 +152,6 @@ public class UserPreferences implements
return instance.allowMobileUpdate;
}
public static boolean isAutoQueue() {
instanceAvailable();
return instance.autoQueue;
}
public static boolean isDisplayOnlyEpisodes() {
instanceAvailable();
return instance.displayOnlyEpisodes;
@ -160,6 +167,21 @@ public class UserPreferences implements
return instance.theme;
}
public static boolean isEnableAutodownloadWifiFilter() {
instanceAvailable();
return instance.enableAutodownloadWifiFilter;
}
public static String[] getAutodownloadSelectedNetworks() {
instanceAvailable();
return instance.autodownloadSelectedNetworks;
}
public static int getEpisodeCacheSize() {
instanceAvailable();
return instance.episodeCacheSize;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
if (AppConfig.DEBUG)
@ -196,17 +218,33 @@ public class UserPreferences implements
} else if (key.equals(PREF_AUTO_DELETE)) {
autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
} else if (key.equals(PREF_AUTO_QUEUE)) {
autoQueue = sp.getBoolean(PREF_AUTO_QUEUE, true);
} else if (key.equals(PREF_DISPLAY_ONLY_EPISODES)) {
displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES,
false);
} else if (key.equals(PREF_THEME)) {
theme = readThemeValue(sp.getString(PREF_THEME, ""));
} else if (key.equals(PREF_ENABLE_AUTODL_WIFI_FILTER)) {
enableAutodownloadWifiFilter = sp.getBoolean(
PREF_ENABLE_AUTODL_WIFI_FILTER, false);
} else if (key.equals(PREF_AUTODL_SELECTED_NETWORKS)) {
autodownloadSelectedNetworks = StringUtils.split(
sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ',');
} else if (key.equals(PREF_EPISODE_CACHE_SIZE)) {
episodeCacheSize = Integer.valueOf(sp.getString(
PREF_EPISODE_CACHE_SIZE, "20"));
}
}
public static void setAutodownloadSelectedNetworks(Context context,
String[] value) {
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(context.getApplicationContext())
.edit();
editor.putString(PREF_AUTODL_SELECTED_NETWORKS,
StringUtils.join(value, ','));
editor.commit();
}
/**
* Return the folder where the app stores all of its data. This method will
* return the standard data folder if none has been set by the user.

View File

@ -0,0 +1,49 @@
package de.danoeh.antennapod.receiver;
import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.feed.FeedManager;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.util.NetworkUtils;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
public class ConnectivityActionReceiver extends BroadcastReceiver {
private static final String TAG = "ConnectivityActionReceiver";
@Override
public void onReceive(final Context context, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
if (AppConfig.DEBUG)
Log.d(TAG, "Received intent");
if (NetworkUtils.autodownloadNetworkAvailable(context)) {
if (AppConfig.DEBUG)
Log.d(TAG,
"auto-dl network available, starting auto-download");
new Thread() {
@Override
public void run() {
FeedManager.getInstance()
.autodownloadUndownloadedItems(context);
}
}.start();
} else { // if new network is Wi-Fi, finish ongoing downloads,
// otherwise cancel all downloads
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni == null || ni.getType() != ConnectivityManager.TYPE_WIFI) {
if (AppConfig.DEBUG)
Log.i(TAG,
"Device is no longer connected to Wi-Fi. Cancelling ongoing downloads");
DownloadRequester.getInstance().cancelAllDownloads(context);
}
}
}
}
}

View File

@ -85,6 +85,12 @@ public class PlaybackService extends Service {
*/
public static final String ACTION_SHUTDOWN_PLAYBACK_SERVICE = "action.de.danoeh.antennapod.service.actionShutdownPlaybackService";
/**
* If the PlaybackService receives this action, it will end playback of the
* current episode and load the next episode if there is one available.
* */
public static final String ACTION_SKIP_CURRENT_EPISODE = "action.de.danoeh.antennapod.service.skipCurrentEpisode";
/** Used in NOTIFICATION_TYPE_RELOAD. */
public static final int EXTRA_CODE_AUDIO = 1;
public static final int EXTRA_CODE_VIDEO = 2;
@ -97,6 +103,8 @@ public class PlaybackService extends Service {
public static final int NOTIFICATION_TYPE_SLEEPTIMER_UPDATE = 4;
public static final int NOTIFICATION_TYPE_BUFFER_START = 5;
public static final int NOTIFICATION_TYPE_BUFFER_END = 6;
/** No more episodes are going to be played. */
public static final int NOTIFICATION_TYPE_PLAYBACK_END = 7;
/**
* Returned by getPositionSafe() or getDurationSafe() if the playbackService
@ -173,7 +181,7 @@ public class PlaybackService extends Service {
return new Intent(context, AudioplayerActivity.class);
}
} else {
if (PlaybackPreferences.isLastIsVideo()) {
if (PlaybackPreferences.getCurrentEpisodeIsVideo()) {
return new Intent(context, VideoplayerActivity.class);
} else {
return new Intent(context, AudioplayerActivity.class);
@ -194,35 +202,6 @@ public class PlaybackService extends Service {
}
}
/** Get last played FeedMedia object or null if it doesn't exist. */
public static FeedMedia getLastPlayedMediaFromPreferences(Context context) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context.getApplicationContext());
long mediaId = PlaybackPreferences.getLastPlayedId();
long feedId = PlaybackPreferences.getLastPlayedFeedId();
FeedManager manager = FeedManager.getInstance();
if (mediaId != -1 && feedId != -1) {
Feed feed = manager.getFeed(feedId);
if (feed != null) {
return manager.getFeedMedia(mediaId, feed);
}
}
return null;
}
private void setLastPlayedMediaId(long mediaId) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
long autoDeleteId = PlaybackPreferences.getAutoDeleteMediaId();
SharedPreferences.Editor editor = prefs.edit();
if (mediaId == autoDeleteId) {
editor.putBoolean(
PlaybackPreferences.PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED,
false);
}
editor.commit();
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
@ -266,6 +245,8 @@ public class PlaybackService extends Service {
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
registerReceiver(audioBecomingNoisy, new IntentFilter(
AudioManager.ACTION_AUDIO_BECOMING_NOISY));
registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(
ACTION_SKIP_CURRENT_EPISODE));
}
@ -296,6 +277,7 @@ public class PlaybackService extends Service {
unregisterReceiver(headsetDisconnected);
unregisterReceiver(shutdownReceiver);
unregisterReceiver(audioBecomingNoisy);
unregisterReceiver(skipCurrentEpisodeReceiver);
if (android.os.Build.VERSION.SDK_INT >= 14) {
audioManager.unregisterRemoteControlClient(remoteControlClient);
}
@ -460,25 +442,28 @@ public class PlaybackService extends Service {
@Override
protected void onPostExecute(Playable result) {
if (result != null) {
try {
if (shouldStream) {
player.setDataSource(media.getStreamUrl());
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
} else {
player.setDataSource(media
.getLocalMediaUrl());
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
if (status == PlayerStatus.INITIALIZING) {
if (result != null) {
try {
if (shouldStream) {
player.setDataSource(media
.getStreamUrl());
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
} else {
player.setDataSource(media
.getLocalMediaUrl());
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} else {
setStatus(PlayerStatus.ERROR);
sendBroadcast(new Intent(
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
} else {
setStatus(PlayerStatus.ERROR);
sendBroadcast(new Intent(
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
}
@ -510,7 +495,9 @@ public class PlaybackService extends Service {
player.release();
player = createMediaPlayer();
status = PlayerStatus.STOPPED;
initMediaplayer();
if (media != null) {
initMediaplayer();
}
}
public void notifyVideoSurfaceAbandoned() {
@ -531,35 +518,45 @@ public class PlaybackService extends Service {
@Override
protected void onPostExecute(Playable result) {
if (result != null) {
playingVideo = false;
try {
if (shouldStream) {
player.setDataSource(media.getStreamUrl());
} else if (media.localFileAvailable()) {
player.setDataSource(media
.getLocalMediaUrl());
}
// check if state of service has changed. If it has
// changed, assume that loaded metadata is not needed
// anymore.
if (status == PlayerStatus.INITIALIZING) {
if (result != null) {
playingVideo = false;
try {
if (shouldStream) {
player.setDataSource(media
.getStreamUrl());
} else if (media.localFileAvailable()) {
player.setDataSource(media
.getLocalMediaUrl());
}
if (prepareImmediately) {
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
} else {
setStatus(PlayerStatus.INITIALIZED);
if (prepareImmediately) {
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
} else {
setStatus(PlayerStatus.INITIALIZED);
}
} catch (IOException e) {
e.printStackTrace();
media = null;
setStatus(PlayerStatus.ERROR);
sendBroadcast(new Intent(
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
} catch (IOException e) {
e.printStackTrace();
} else {
Log.e(TAG, "InitTask could not load metadata");
media = null;
setStatus(PlayerStatus.ERROR);
sendBroadcast(new Intent(
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
} else {
Log.e(TAG, "InitTask could not load metadata");
media = null;
setStatus(PlayerStatus.ERROR);
sendBroadcast(new Intent(
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
if (AppConfig.DEBUG)
Log.d(TAG,
"Status of player has changed during initialization. Stopping init process.");
}
}
@ -673,78 +670,7 @@ public class PlaybackService extends Service {
@Override
public void onCompletion(MediaPlayer mp) {
if (AppConfig.DEBUG)
Log.d(TAG, "Playback completed");
audioManager.abandonAudioFocus(audioFocusChangeListener);
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = prefs.edit();
// Save state
cancelPositionSaver();
boolean isInQueue = false;
FeedItem nextItem = null;
if (media instanceof FeedMedia) {
FeedItem item = ((FeedMedia) media).getItem();
((FeedMedia) media).setPlaybackCompletionDate(new Date());
manager.markItemRead(PlaybackService.this, item, true, true);
nextItem = manager.getQueueSuccessorOfItem(item);
isInQueue = media instanceof FeedMedia
&& manager.isInQueue(((FeedMedia) media).getItem());
if (isInQueue) {
manager.removeQueueItem(PlaybackService.this, item);
}
manager.addItemToPlaybackHistory(PlaybackService.this, item);
manager.setFeedMedia(PlaybackService.this, (FeedMedia) media);
long autoDeleteMediaId = ((FeedComponent) media).getId();
if (shouldStream) {
autoDeleteMediaId = -1;
}
editor.putLong(PlaybackPreferences.PREF_AUTODELETE_MEDIA_ID,
autoDeleteMediaId);
}
editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
PlaybackPreferences.NO_MEDIA_PLAYING);
editor.putBoolean(
PlaybackPreferences.PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED,
true);
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
editor.commit();
// Prepare for playing next item
boolean playNextItem = isInQueue && UserPreferences.isFollowQueue()
&& nextItem != null;
if (playNextItem) {
if (AppConfig.DEBUG)
Log.d(TAG, "Loading next item in queue");
media = nextItem.getMedia();
shouldStream = !media.localFileAvailable();
prepareImmediately = startWhenPrepared = true;
} else {
if (AppConfig.DEBUG)
Log.d(TAG,
"No more episodes available to play; Reloading current episode");
prepareImmediately = startWhenPrepared = false;
stopForeground(true);
stopWidgetUpdater();
}
int notificationCode = 0;
if (media.getMediaType() == MediaType.AUDIO) {
notificationCode = EXTRA_CODE_AUDIO;
playingVideo = false;
} else if (media.getMediaType() == MediaType.VIDEO) {
notificationCode = EXTRA_CODE_VIDEO;
}
resetVideoSurface();
refreshRemoteControlClientState();
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
notificationCode);
endPlayback(true);
}
};
@ -757,6 +683,82 @@ public class PlaybackService extends Service {
}
};
private void endPlayback(boolean playNextEpisode) {
if (AppConfig.DEBUG)
Log.d(TAG, "Playback ended");
audioManager.abandonAudioFocus(audioFocusChangeListener);
// Save state
cancelPositionSaver();
boolean isInQueue = false;
FeedItem nextItem = null;
if (media instanceof FeedMedia) {
FeedItem item = ((FeedMedia) media).getItem();
((FeedMedia) media).setPlaybackCompletionDate(new Date());
manager.markItemRead(PlaybackService.this, item, true, true);
nextItem = manager.getQueueSuccessorOfItem(item);
isInQueue = media instanceof FeedMedia
&& manager.isInQueue(((FeedMedia) media).getItem());
if (isInQueue) {
manager.removeQueueItem(PlaybackService.this, item);
}
manager.addItemToPlaybackHistory(PlaybackService.this, item);
manager.setFeedMedia(PlaybackService.this, (FeedMedia) media);
long autoDeleteMediaId = ((FeedComponent) media).getId();
if (shouldStream) {
autoDeleteMediaId = -1;
}
}
// Load next episode if previous episode was in the queue and if there
// is an episode in the queue left.
// Start playback immediately if continuous playback is enabled
boolean loadNextItem = isInQueue && nextItem != null;
playNextEpisode = playNextEpisode && loadNextItem
&& UserPreferences.isFollowQueue();
if (loadNextItem) {
if (AppConfig.DEBUG)
Log.d(TAG, "Loading next item in queue");
media = nextItem.getMedia();
}
if (playNextEpisode) {
if (AppConfig.DEBUG)
Log.d(TAG, "Playback of next episode will start immediately.");
prepareImmediately = startWhenPrepared = true;
} else {
if (AppConfig.DEBUG)
Log.d(TAG,
"No more episodes available to play");
media = null;
prepareImmediately = startWhenPrepared = false;
stopForeground(true);
stopWidgetUpdater();
}
int notificationCode = 0;
if (media != null) {
shouldStream = !media.localFileAvailable();
if (media.getMediaType() == MediaType.AUDIO) {
notificationCode = EXTRA_CODE_AUDIO;
playingVideo = false;
} else if (media.getMediaType() == MediaType.VIDEO) {
notificationCode = EXTRA_CODE_VIDEO;
}
}
writePlaybackPreferences();
if (media != null) {
resetVideoSurface();
refreshRemoteControlClientState();
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, notificationCode);
} else {
sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
stopSelf();
}
}
public void setSleepTimer(long waitingTime) {
if (AppConfig.DEBUG)
Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime)
@ -856,40 +858,8 @@ public class PlaybackService extends Service {
Log.d(TAG, "Audiofocus successfully requested");
if (AppConfig.DEBUG)
Log.d(TAG, "Resuming/Starting playback");
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext())
.edit();
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
media.getPlayableType());
editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_STREAM,
shouldStream);
editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_VIDEO,
playingVideo);
editor.putLong(PlaybackPreferences.PREF_LAST_PLAYED_ID,
media.getPlayableType());
if (media instanceof FeedMedia) {
FeedMedia fMedia = (FeedMedia) media;
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
fMedia.getItem().getFeed().getId());
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
fMedia.getId());
} else {
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
}
media.writeToPreferences(editor);
writePlaybackPreferences();
editor.commit();
if (media instanceof FeedMedia) {
setLastPlayedMediaId(((FeedMedia) media).getId());
}
player.start();
if (status != PlayerStatus.PAUSED) {
player.seekTo((int) media.getPosition());
@ -913,6 +883,51 @@ public class PlaybackService extends Service {
}
}
private void writePlaybackPreferences() {
if (AppConfig.DEBUG)
Log.d(TAG, "Writing playback preferences");
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext()).edit();
if (media != null) {
editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
media.getPlayableType());
editor.putBoolean(
PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM,
shouldStream);
editor.putBoolean(
PlaybackPreferences.PREF_CURRENT_EPISODE_IS_VIDEO,
playingVideo);
if (media instanceof FeedMedia) {
FeedMedia fMedia = (FeedMedia) media;
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
fMedia.getItem().getFeed().getId());
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
fMedia.getId());
} else {
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
}
media.writeToPreferences(editor);
} else {
editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
PlaybackPreferences.NO_MEDIA_PLAYING);
editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
editor.putLong(
PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
PlaybackPreferences.NO_MEDIA_PLAYING);
}
editor.commit();
}
private void setStatus(PlayerStatus newStatus) {
if (AppConfig.DEBUG)
Log.d(TAG, "Setting status to " + newStatus);
@ -1005,7 +1020,9 @@ public class PlaybackService extends Service {
public void seek(int i) {
saveCurrentPosition();
if (status == PlayerStatus.INITIALIZED) {
if (status == PlayerStatus.INITIALIZED
|| status == PlayerStatus.INITIALIZING
|| status == PlayerStatus.PREPARING) {
media.setPosition(i);
setStartWhenPrepared(true);
prepare();
@ -1201,6 +1218,22 @@ public class PlaybackService extends Service {
};
private BroadcastReceiver skipCurrentEpisodeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_SKIP_CURRENT_EPISODE)) {
if (AppConfig.DEBUG)
Log.d(TAG, "Received SKIP_CURRENT_EPISODE intent");
if (media != null) {
setStatus(PlayerStatus.STOPPED);
player.reset();
endPlayback(false);
}
}
}
};
/** Periodically saves the position of the media file */
class PositionSaver implements Runnable {
public static final int WAITING_INTERVALL = 5000;

View File

@ -58,6 +58,7 @@ import de.danoeh.antennapod.feed.FeedImage;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.preferences.UserPreferences;
import de.danoeh.antennapod.storage.DownloadRequestException;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.syndication.handler.FeedHandler;
@ -831,7 +832,7 @@ public class DownloadService extends Service {
} finally {
mediaplayer.release();
}
if (media.getItem().getChapters() == null) {
ChapterUtils.loadChaptersFromFileUrl(media);
if (media.getItem().getChapters() != null) {
@ -847,6 +848,11 @@ public class DownloadService extends Service {
manager.setFeedMedia(DownloadService.this, media);
}
if (!FeedManager.getInstance().isInQueue(media.getItem())) {
FeedManager.getInstance().addQueueItem(DownloadService.this,
media.getItem());
}
downloadsBeingHandled -= 1;
handler.post(new Runnable() {

View File

@ -0,0 +1,63 @@
package de.danoeh.antennapod.util;
import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.preferences.UserPreferences;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
public class NetworkUtils {
private static final String TAG = "NetworkUtils";
private NetworkUtils() {
}
/**
* Returns true if the device is connected to Wi-Fi and the Wi-Fi filter for
* automatic downloads is disabled or the device is connected to a Wi-Fi
* network that is on the 'selected networks' list of the Wi-Fi filter for
* automatic downloads and false otherwise.
* */
public static boolean autodownloadNetworkAvailable(Context context) {
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo != null) {
if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
if (AppConfig.DEBUG)
Log.d(TAG, "Device is connected to Wi-Fi");
if (networkInfo.isConnected()) {
if (!UserPreferences.isEnableAutodownloadWifiFilter()) {
if (AppConfig.DEBUG)
Log.d(TAG, "Auto-dl filter is disabled");
return true;
} else {
WifiManager wm = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wm.getConnectionInfo();
List<String> selectedNetworks = Arrays
.asList(UserPreferences
.getAutodownloadSelectedNetworks());
if (selectedNetworks.contains(Integer.toString(wifiInfo
.getNetworkId()))) {
if (AppConfig.DEBUG)
Log.d(TAG,
"Current network is on the selected networks list");
return true;
}
}
}
}
}
if (AppConfig.DEBUG)
Log.d(TAG, "Network for auto-dl is not available");
return false;
}
}

View File

@ -3,10 +3,12 @@ package de.danoeh.antennapod.util.menuhandler;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.asynctask.FlattrClickWorker;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager;
import de.danoeh.antennapod.service.PlaybackService;
import de.danoeh.antennapod.storage.DownloadRequestException;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.util.ShareUtils;
@ -55,16 +57,22 @@ public class FeedItemMenuHandler {
&& requester.isDownloadingFile(selectedItem.getMedia());
boolean notLoadedAndNotLoading = hasMedia && (!downloaded)
&& (!downloading);
boolean isPlaying = hasMedia
&& selectedItem.getState() == FeedItem.State.PLAYING;
FeedItem.State state = selectedItem.getState();
if (!downloaded) {
if (!isPlaying) {
mi.setItemVisibility(R.id.skip_episode_item, false);
}
if (!downloaded || isPlaying) {
mi.setItemVisibility(R.id.play_item, false);
mi.setItemVisibility(R.id.remove_item, false);
}
if (!notLoadedAndNotLoading) {
mi.setItemVisibility(R.id.download_item, false);
}
if (!(notLoadedAndNotLoading | downloading)) {
if (!(notLoadedAndNotLoading | downloading) | isPlaying) {
mi.setItemVisibility(R.id.stream_item, false);
}
if (!downloading) {
@ -82,7 +90,8 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.share_link_item, false);
}
if (!(state == FeedItem.State.IN_PROGRESS || state == FeedItem.State.READ)) {
if (!AppConfig.DEBUG
|| !(state == FeedItem.State.IN_PROGRESS || state == FeedItem.State.READ)) {
mi.setItemVisibility(R.id.mark_unread_item, false);
}
if (!(state == FeedItem.State.NEW || state == FeedItem.State.IN_PROGRESS)) {
@ -104,6 +113,10 @@ public class FeedItemMenuHandler {
DownloadRequester requester = DownloadRequester.getInstance();
FeedManager manager = FeedManager.getInstance();
switch (menuItemId) {
case R.id.skip_episode_item:
context.sendBroadcast(new Intent(
PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
break;
case R.id.download_item:
manager.downloadFeedItem(context, selectedItem);
break;

View File

@ -188,9 +188,9 @@ public abstract class PlaybackController {
Log.d(TAG, "Trying to restore last played media");
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(activity.getApplicationContext());
long lastPlayedId = PlaybackPreferences.getLastPlayedId();
if (lastPlayedId != PlaybackPreferences.NO_MEDIA_PLAYING) {
Playable media = PlayableUtils.createInstanceFromPreferences((int) lastPlayedId, prefs);
long currentlyPlayingMedia = PlaybackPreferences.getCurrentlyPlayingMedia();
if (currentlyPlayingMedia != PlaybackPreferences.NO_MEDIA_PLAYING) {
Playable media = PlayableUtils.createInstanceFromPreferences((int) currentlyPlayingMedia, prefs);
if (media != null) {
Intent serviceIntent = new Intent(activity,
PlaybackService.class);
@ -200,7 +200,7 @@ public abstract class PlaybackController {
serviceIntent.putExtra(
PlaybackService.EXTRA_PREPARE_IMMEDIATELY, false);
boolean fileExists = media.localFileAvailable();
boolean lastIsStream = PlaybackPreferences.isLastIsStream();
boolean lastIsStream = PlaybackPreferences.getCurrentEpisodeIsStream();
if (!fileExists && !lastIsStream && media instanceof FeedMedia) {
FeedManager.getInstance().notifyMissingFeedMediaFile(
activity, (FeedMedia) media);
@ -320,6 +320,9 @@ public abstract class PlaybackController {
case PlaybackService.NOTIFICATION_TYPE_BUFFER_END:
onBufferEnd();
break;
case PlaybackService.NOTIFICATION_TYPE_PLAYBACK_END:
onPlaybackEnd();
break;
}
} else {
@ -357,6 +360,8 @@ public abstract class PlaybackController {
public abstract void onSleepTimerUpdate();
public abstract void handleError(int code);
public abstract void onPlaybackEnd();
/**
* Is called whenever the PlaybackService changes it's status. This method