diff options
author | daniel oeh <daniel.oeh@gmail.com> | 2014-12-08 19:18:34 +0100 |
---|---|---|
committer | daniel oeh <daniel.oeh@gmail.com> | 2014-12-08 19:18:34 +0100 |
commit | 9659c18d899349d9be1573fb9520defc7d3a19cd (patch) | |
tree | c3e873c60b2b9990cdf47c9b4e5fca9ba70a0557 /core | |
parent | 563ceaf39332943b1733036f5c3b9087c481d313 (diff) | |
parent | 43243c1b70b6cae7f7ce3105e171afa6f9982144 (diff) | |
download | AntennaPod-9659c18d899349d9be1573fb9520defc7d3a19cd.zip |
Merge branch 'develop'0.9.9.6
Diffstat (limited to 'core')
35 files changed, 317 insertions, 271 deletions
diff --git a/core/build.gradle b/core/build.gradle index 3c5c07313..cfe33c98c 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -5,7 +5,6 @@ android { buildToolsVersion "21.1.1" defaultConfig { - applicationId "de.danoeh.antennapod.core" minSdkVersion 10 targetSdkVersion 21 versionCode 1 @@ -35,13 +34,12 @@ dependencies { compile 'com.android.support:appcompat-v7:21.0.2' compile 'com.android.support:support-v4:21.0.2' compile 'org.apache.commons:commons-lang3:3.3.2' - compile ('org.shredzone.flattr4j:flattr4j-core:2.10') { + compile ('org.shredzone.flattr4j:flattr4j-core:2.11') { exclude group: 'org.apache.httpcomponents', module: 'httpcore' exclude group: 'org.apache.httpcomponents', module: 'httpclient' exclude group: 'org.json', module: 'json' } compile 'commons-io:commons-io:2.4' - compile 'com.nineoldandroids:library:2.4.0' compile 'com.jayway.android.robotium:robotium-solo:5.2.1' compile 'org.jsoup:jsoup:1.7.3' compile 'com.squareup.picasso:picasso:2.4.0' diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index c660cd805..3ec519844 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -19,10 +19,10 @@ <service android:name=".service.playback.PlaybackService" android:enabled="true" - android:exported="true"/> + android:exported="true" /> <service android:name=".service.GpodnetSyncService" - android:enabled="true"/> + android:enabled="true" /> <receiver android:name=".receiver.MediaButtonReceiver" @@ -47,6 +47,9 @@ </intent-filter> </receiver> + <receiver android:name=".receiver.FeedUpdateReceiver"> + </receiver> + </application> </manifest> diff --git a/core/src/main/java/com/aocate/media/MediaPlayer.java b/core/src/main/java/com/aocate/media/MediaPlayer.java index c73c5219e..79e63d03d 100644 --- a/core/src/main/java/com/aocate/media/MediaPlayer.java +++ b/core/src/main/java/com/aocate/media/MediaPlayer.java @@ -35,6 +35,8 @@ import java.util.concurrent.locks.ReentrantLock; import de.danoeh.antennapod.core.BuildConfig; public class MediaPlayer { + public static final String TAG = "com.aocate.media.MediaPlayer"; + public interface OnBufferingUpdateListener { public abstract void onBufferingUpdate(MediaPlayer arg0, int percent); } @@ -110,6 +112,36 @@ public class MediaPlayer { } /** + * Returns an explicit Intent for a service that accepts the given Intent + * or null if no such service was found. + * + * @param context The application's environment. + * @param action The Intent action to check for availability. + * @return The explicit service Intent or null if no service was found. + */ + public static Intent getPrestoServiceIntent(Context context, String action) { + final PackageManager packageManager = context.getPackageManager(); + final Intent actionIntent = new Intent(action); + List<ResolveInfo> list = packageManager.queryIntentServices(actionIntent, + PackageManager.MATCH_DEFAULT_ONLY); + if (list.size() > 0) { + ResolveInfo first = list.get(0); + if (first.serviceInfo != null) { + Intent intent = new Intent(); + intent.setComponent(new ComponentName(first.serviceInfo.packageName, + first.serviceInfo.name)); + Log.i(TAG, "Returning intent:" + intent.toString()); + return intent; + } else { + Log.e(TAG, "Found service that accepts " + action + ", but serviceInfo was null"); + return null; + } + } else { + return null; + } + } + + /** * Indicates whether the Presto library is installed * * @param context The context to use to query the package manager. diff --git a/core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java b/core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java index 702a23b0f..0e27a8014 100644 --- a/core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java +++ b/core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java @@ -83,7 +83,7 @@ public class ServiceBackedMediaPlayer extends MediaPlayerImpl { super(owningMediaPlayer, context); Log.d(SBMP_TAG, "Instantiating ServiceBackedMediaPlayer 87"); this.playMediaServiceIntent = - new Intent(INTENT_NAME); + MediaPlayer.getPrestoServiceIntent(context, INTENT_NAME); this.mPlayMediaServiceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { IPlayMedia_0_8 tmpPlayMediaInterface = IPlayMedia_0_8.Stub.asInterface((IBinder) service); @@ -135,6 +135,7 @@ public class ServiceBackedMediaPlayer extends MediaPlayerImpl { Log.d(SBMP_TAG, "Connecting PlayMediaService 124"); if (!ConnectPlayMediaService()) { + Log.e(SBMP_TAG, "bindService failed"); ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); } } @@ -149,6 +150,7 @@ public class ServiceBackedMediaPlayer extends MediaPlayerImpl { Log.d(SBMP_TAG, "Binding service"); return mContext.bindService(playMediaServiceIntent, mPlayMediaServiceConnection, Context.BIND_AUTO_CREATE); } catch (Exception e) { + Log.e(SBMP_TAG, "Could not bind with service", e); return false; } } else { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index d056917e1..42e4191f6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -44,12 +44,45 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private boolean read; private String paymentLink; private FlattrStatus flattrStatus; + + /** + * Is true if the database contains any chapters that belong to this item. This attribute is only + * written once by DBReader on initialization. + * The FeedItem might still have a non-null chapters value. In this case, the list of chapters + * has not been saved in the database yet. + * */ + private final boolean hasChapters; + + /** + * The list of chapters of this item. This might be null even if there are chapters of this item + * in the database. The 'hasChapters' attribute should be used to check if this item has any chapters. + * */ private List<Chapter> chapters; private FeedImage image; public FeedItem() { this.read = true; this.flattrStatus = new FlattrStatus(); + this.hasChapters = false; + } + + /** + * This constructor is used by DBReader. + * */ + public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId, + FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, boolean read, + String itemIdentifier) { + this.id = id; + this.title = title; + this.link = link; + this.pubDate = pubDate; + this.paymentLink = paymentLink; + this.feedId = feedId; + this.flattrStatus = flattrStatus; + this.hasChapters = hasChapters; + this.image = image; + this.read = read; + this.itemIdentifier = itemIdentifier; } /** @@ -64,6 +97,22 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr this.read = read; this.feed = feed; this.flattrStatus = new FlattrStatus(); + this.hasChapters = false; + } + + /** + * This constructor should be used for creating test objects involving chapter marks. + */ + public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed, boolean hasChapters) { + this.id = id; + this.title = title; + this.itemIdentifier = itemIdentifier; + this.link = link; + this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null; + this.read = read; + this.feed = feed; + this.flattrStatus = new FlattrStatus(); + this.hasChapters = hasChapters; } public void updateFromOther(FeedItem other) { @@ -331,4 +380,8 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public String getHumanReadableIdentifier() { return title; } + + public boolean hasChapters() { + return hasChapters; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index defcfd598..2434ee0cf 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -245,14 +245,19 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void loadChapterMarks() { - if (getChapters() == null && !localFileAvailable()) { + if (item == null && itemID != 0) { + item = DBReader.getFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), itemID); + } + // check if chapters are stored in db and not loaded yet. + if (item != null && item.hasChapters() && item.getChapters() == null) { + DBReader.loadChaptersOfFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), item); + } else if (item != null && item.getChapters() == null && !localFileAvailable()) { ChapterUtils.loadChaptersFromStreamUrl(this); if (getChapters() != null && item != null) { DBWriter.setFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), item); } } - } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index f4d44c4da..f18028e8f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -20,6 +20,7 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; +import de.danoeh.antennapod.core.ApplicationCallbacks; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; @@ -582,8 +583,7 @@ public class UserPreferences implements AlarmManager alarmManager = (AlarmManager) instance.context .getSystemService(Context.ALARM_SERVICE); PendingIntent updateIntent = PendingIntent.getBroadcast( - instance.context, 0, new Intent( - FeedUpdateReceiver.ACTION_REFRESH_FEEDS), 0); + instance.context, 0, new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); alarmManager.cancel(updateIntent); if (intervalMillis != 0) { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, intervalMillis, diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java index 6ce30763d..95dc4fb07 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java @@ -7,40 +7,37 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.util.Log; -import org.apache.commons.lang3.StringUtils; - import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBTasks; -/** Refreshes all feeds when it receives an intent */ +/** + * Refreshes all feeds when it receives an intent + */ public class FeedUpdateReceiver extends BroadcastReceiver { - private static final String TAG = "FeedUpdateReceiver"; - public static final String ACTION_REFRESH_FEEDS = "de.danoeh.antennapod.feedupdatereceiver.refreshFeeds"; - - @Override - public void onReceive(Context context, Intent intent) { - if (StringUtils.equals(intent.getAction(), ACTION_REFRESH_FEEDS)) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received intent"); - boolean mobileUpdate = UserPreferences.isAllowMobileUpdate(); - if (mobileUpdate || connectedToWifi(context)) { - DBTasks.refreshExpiredFeeds(context); - } else { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Blocking automatic update: no wifi available / no mobile updates allowed"); - } - } - } - - private boolean connectedToWifi(Context context) { - ConnectivityManager connManager = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo mWifi = connManager - .getNetworkInfo(ConnectivityManager.TYPE_WIFI); - - return mWifi.isConnected(); - } + private static final String TAG = "FeedUpdateReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Received intent"); + boolean mobileUpdate = UserPreferences.isAllowMobileUpdate(); + if (mobileUpdate || connectedToWifi(context)) { + DBTasks.refreshExpiredFeeds(context); + } else { + if (BuildConfig.DEBUG) + Log.d(TAG, + "Blocking automatic update: no wifi available / no mobile updates allowed"); + } + } + + private boolean connectedToWifi(Context context) { + ConnectivityManager connManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mWifi = connManager + .getNetworkInfo(ConnectivityManager.TYPE_WIFI); + + return mWifi.isConnected(); + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 6c0b6df74..217e6fba5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -4,8 +4,22 @@ import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.util.Log; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.feed.*; +import de.danoeh.antennapod.core.feed.Chapter; +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedImage; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.ID3Chapter; +import de.danoeh.antennapod.core.feed.SimpleChapter; +import de.danoeh.antennapod.core.feed.VorbisCommentChapter; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator; @@ -14,11 +28,6 @@ import de.danoeh.antennapod.core.util.comparator.PlaybackCompletionDateComparato import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.danoeh.antennapod.core.util.flattr.FlattrThing; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; - /** * Provides methods for reading data from the AntennaPod database. * In general, all database calls in DBReader-methods are executed on the caller's thread. @@ -203,75 +212,26 @@ public final class DBReader { if (itemlistCursor.moveToFirst()) { do { - FeedItem item = new FeedItem(); - - item.setId(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_ID)); - item.setTitle(itemlistCursor - .getString(PodDBAdapter.IDX_FI_SMALL_TITLE)); - item.setLink(itemlistCursor - .getString(PodDBAdapter.IDX_FI_SMALL_LINK)); - item.setPubDate(new Date(itemlistCursor - .getLong(PodDBAdapter.IDX_FI_SMALL_PUBDATE))); - item.setPaymentLink(itemlistCursor - .getString(PodDBAdapter.IDX_FI_SMALL_PAYMENT_LINK)); - item.setFeedId(itemlistCursor - .getLong(PodDBAdapter.IDX_FI_SMALL_FEED)); - itemIds.add(String.valueOf(item.getId())); - - item.setRead((itemlistCursor - .getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0)); - item.setItemIdentifier(itemlistCursor - .getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER)); - item.setFlattrStatus(new FlattrStatus(itemlistCursor - .getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS))); - long imageIndex = itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_IMAGE); + FeedImage image = null; if (imageIndex != 0) { - item.setImage(getFeedImage(adapter, imageIndex)); + image = getFeedImage(adapter, imageIndex); } - // extract chapters - boolean hasSimpleChapters = itemlistCursor - .getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0; - if (hasSimpleChapters) { - Cursor chapterCursor = adapter - .getSimpleChaptersOfFeedItemCursor(item); - if (chapterCursor.moveToFirst()) { - item.setChapters(new ArrayList<Chapter>()); - do { - int chapterType = chapterCursor - .getInt(PodDBAdapter.KEY_CHAPTER_TYPE_INDEX); - Chapter chapter = null; - long start = chapterCursor - .getLong(PodDBAdapter.KEY_CHAPTER_START_INDEX); - String title = chapterCursor - .getString(PodDBAdapter.KEY_TITLE_INDEX); - String link = chapterCursor - .getString(PodDBAdapter.KEY_CHAPTER_LINK_INDEX); - - switch (chapterType) { - case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: - chapter = new SimpleChapter(start, title, item, - link); - break; - case ID3Chapter.CHAPTERTYPE_ID3CHAPTER: - chapter = new ID3Chapter(start, title, item, - link); - break; - case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: - chapter = new VorbisCommentChapter(start, - title, item, link); - break; - } - if (chapter != null) { - chapter.setId(chapterCursor - .getLong(PodDBAdapter.KEY_ID_INDEX)); - item.getChapters().add(chapter); - } - } while (chapterCursor.moveToNext()); - } - chapterCursor.close(); - } + FeedItem item = new FeedItem(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_ID), + itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_TITLE), + itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_LINK), + new Date(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_PUBDATE)), + itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_PAYMENT_LINK), + itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FEED), + new FlattrStatus(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)), + itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0, + image, + (itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0), + itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER)); + + itemIds.add(String.valueOf(item.getId())); + items.add(item); } while (itemlistCursor.moveToNext()); } @@ -367,6 +327,7 @@ public final class DBReader { return feed; } + private static FeedItem getMatchingItemForMedia(long itemId, List<FeedItem> items) { for (FeedItem item : items) { @@ -689,6 +650,9 @@ public final class DBReader { if (list.size() > 0) { item = list.get(0); loadFeedDataOfFeedItemlist(context, list); + if (item.hasChapters()) { + loadChaptersOfFeedItem(adapter, item); + } } } return item; @@ -696,12 +660,13 @@ public final class DBReader { } /** - * Loads a specific FeedItem from the database. + * Loads a specific FeedItem from the database. This method should not be used for loading more + * than one FeedItem because this method might query the database several times for each item. * * @param context A context that is used for opening a database connection. * @param itemId The ID of the FeedItem - * @return The FeedItem or null if the FeedItem could not be found. All FeedComponent-attributes of the FeedItem will - * also be loaded from the database. + * @return The FeedItem or null if the FeedItem could not be found. All FeedComponent-attributes + * as well as chapter marks of the FeedItem will also be loaded from the database. */ public static FeedItem getFeedItem(final Context context, final long itemId) { if (BuildConfig.DEBUG) @@ -737,6 +702,63 @@ public final class DBReader { } /** + * Loads the list of chapters that belongs to this FeedItem if available. This method overwrites + * any chapters that this FeedItem has. If no chapters were found in the database, the chapters + * reference of the FeedItem will be set to null. + * + * @param context A context that is used for opening a database connection. + * @param item The FeedItem + */ + public static void loadChaptersOfFeedItem(final Context context, final FeedItem item) { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + loadChaptersOfFeedItem(adapter, item); + adapter.close(); + } + + static void loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { + Cursor chapterCursor = adapter + .getSimpleChaptersOfFeedItemCursor(item); + if (chapterCursor.moveToFirst()) { + item.setChapters(new ArrayList<Chapter>()); + do { + int chapterType = chapterCursor + .getInt(PodDBAdapter.KEY_CHAPTER_TYPE_INDEX); + Chapter chapter = null; + long start = chapterCursor + .getLong(PodDBAdapter.KEY_CHAPTER_START_INDEX); + String title = chapterCursor + .getString(PodDBAdapter.KEY_TITLE_INDEX); + String link = chapterCursor + .getString(PodDBAdapter.KEY_CHAPTER_LINK_INDEX); + + switch (chapterType) { + case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: + chapter = new SimpleChapter(start, title, item, + link); + break; + case ID3Chapter.CHAPTERTYPE_ID3CHAPTER: + chapter = new ID3Chapter(start, title, item, + link); + break; + case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: + chapter = new VorbisCommentChapter(start, + title, item, link); + break; + } + if (chapter != null) { + chapter.setId(chapterCursor + .getLong(PodDBAdapter.KEY_ID_INDEX)); + item.getChapters().add(chapter); + } + } while (chapterCursor.moveToNext()); + } else { + item.setChapters(null); + } + chapterCursor.close(); + } + + /** * Returns the number of downloaded episodes. * * @param context A context that is used for opening a database connection. @@ -788,7 +810,7 @@ public final class DBReader { static FeedImage getFeedImage(PodDBAdapter adapter, final long id) { Cursor cursor = adapter.getImageCursor(id); if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { - throw new SQLException("No FeedImage found at index: " + id); + return null; } FeedImage image = new FeedImage(id, cursor.getString(cursor .getColumnIndex(PodDBAdapter.KEY_TITLE)), diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index 148d886ae..f5ee9e28c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -90,7 +90,7 @@ public class DownloadRequester { return true; } - private void download(Context context, FeedFile item, File dest, + private void download(Context context, FeedFile item, FeedFile container, File dest, boolean overwriteIfExists, String username, String password, boolean deleteOnFailure, Bundle arguments) { if (!isDownloadingFile(item)) { if (!isFilenameAvailable(dest.toString()) || (deleteOnFailure && dest.exists())) { @@ -129,7 +129,8 @@ public class DownloadRequester { if (BuildConfig.DEBUG) Log.d(TAG, "Requesting download of url " + item.getDownload_url()); - item.setDownload_url(URLChecker.prepareURL(item.getDownload_url())); + String baseUrl = (container != null) ? container.getDownload_url() : null; + item.setDownload_url(URLChecker.prepareURL(item.getDownload_url(), baseUrl)); DownloadRequest request = new DownloadRequest(dest.toString(), URLChecker.prepareURL(item.getDownload_url()), item.getHumanReadableIdentifier(), @@ -171,7 +172,7 @@ public class DownloadRequester { args.putInt(REQUEST_ARG_PAGE_NR, feed.getPageNr()); args.putBoolean(REQUEST_ARG_LOAD_ALL_PAGES, loadAllPages); - download(context, feed, new File(getFeedfilePath(context), + download(context, feed, null, new File(getFeedfilePath(context), getFeedfileName(feed)), true, username, password, true, args); } } @@ -183,7 +184,8 @@ public class DownloadRequester { public synchronized void downloadImage(Context context, FeedImage image) throws DownloadRequestException { if (feedFileValid(image)) { - download(context, image, new File(getImagefilePath(context), + FeedFile container = (image.getOwner() instanceof FeedFile) ? (FeedFile) image.getOwner() : null; + download(context, image, container, new File(getImagefilePath(context), getImagefileName(image)), false, null, null, false, null); } } @@ -209,7 +211,7 @@ public class DownloadRequester { dest = new File(getMediafilePath(context, feedmedia), getMediafilename(feedmedia)); } - download(context, feedmedia, + download(context, feedmedia, feed, dest, false, username, password, false, null); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 79124521f..ce41147e1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -693,7 +693,7 @@ public class PodDBAdapter { } values.put(KEY_FEED, item.getFeed().getId()); values.put(KEY_READ, item.isRead()); - values.put(KEY_HAS_CHAPTERS, item.getChapters() != null); + values.put(KEY_HAS_CHAPTERS, item.getChapters() != null || item.hasChapters()); values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier()); values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong()); if (item.hasItemImage()) { @@ -848,7 +848,7 @@ public class PodDBAdapter { if (item.getMedia() != null) { removeFeedMedia(item.getMedia()); } - if (item.getChapters() != null) { + if (item.hasChapters() || item.getChapters() != null) { removeChaptersOfItem(item); } if (item.hasItemImage()) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java index 70e1126b9..ff9828eba 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java @@ -50,7 +50,7 @@ public class NSITunes extends Namespace { if (localName.equals(AUTHOR)) { state.getFeed().setAuthor(state.getContentBuf().toString()); } else if (localName.equals(DURATION)) { - String[] parts = state.getContentBuf().toString().split(":"); + String[] parts = state.getContentBuf().toString().trim().split(":"); try { int duration = 0; if (parts.length == 2) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndDateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndDateUtils.java index d493286ac..1ac389f08 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndDateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndDateUtils.java @@ -7,13 +7,16 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import de.danoeh.antennapod.core.BuildConfig; + /** * Parses several date formats. */ public class SyndDateUtils { private static final String TAG = "DateUtils"; - private static final String[] RFC822DATES = {"dd MMM yy HH:mm:ss Z",}; + private static final String[] RFC822DATES = {"dd MMM yy HH:mm:ss Z", + "dd MMM yy HH:mm Z"}; /** * RFC 3339 date format for UTC dates. @@ -51,17 +54,18 @@ public class SyndDateUtils { date = date.substring(date.indexOf(",") + 1).trim(); } SimpleDateFormat format = RFC822Formatter.get(); - for (int i = 0; i < RFC822DATES.length; i++) { + + for (String RFC822DATE : RFC822DATES) { try { - format.applyPattern(RFC822DATES[i]); + format.applyPattern(RFC822DATE); result = format.parse(date); break; } catch (ParseException e) { - e.printStackTrace(); + if (BuildConfig.DEBUG) Log.d(TAG, "ParserException", e); } } if (result == null) { - Log.e(TAG, "Unable to parse feed date correctly"); + Log.e(TAG, "Unable to parse feed date correctly:" + date); } return result; @@ -134,9 +138,11 @@ public class SyndDateUtils { result += Integer.valueOf(parts[idx]) * 3600000L; idx++; } - result += Integer.valueOf(parts[idx]) * 60000L; - idx++; - result += (Float.valueOf(parts[idx])) * 1000L; + if (parts.length >= 2) { + result += Integer.valueOf(parts[idx]) * 60000L; + idx++; + result += (Float.valueOf(parts[idx])) * 1000L; + } return result; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java index 4bd18c8bc..4300556d2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.util; +import android.net.Uri; import android.util.Log; import org.apache.commons.lang3.StringUtils; @@ -51,4 +52,28 @@ public final class URLChecker { return url; } } + + /** + * Checks if URL is valid and modifies it if necessary. + * This method also handles protocol relative URLs. + * + * @param url The url which is going to be prepared + * @param base The url against which the (possibly relative) url is applied. If this is null, + * the result of prepareURL(url) is returned instead. + * @return The prepared url + */ + public static String prepareURL(String url, String base) { + if (base == null) { + return prepareURL(url); + } + url = StringUtils.trim(url); + base = prepareURL(base); + Uri urlUri = Uri.parse(url); + Uri baseUri = Uri.parse(base); + if (urlUri.isRelative() && baseUri.isAbsolute()) { + return urlUri.buildUpon().scheme(baseUri.getScheme()).build().toString(); + } else { + return prepareURL(url); + } + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/UndoBarController.java b/core/src/main/java/de/danoeh/antennapod/core/util/UndoBarController.java deleted file mode 100644 index 5843c5f8f..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/util/UndoBarController.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012 Roman Nurik - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package de.danoeh.antennapod.core.util; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Parcelable; -import android.text.TextUtils; -import android.view.View; -import android.widget.TextView; -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.view.ViewHelper; -import com.nineoldandroids.view.ViewPropertyAnimator; -import de.danoeh.antennapod.core.R; - -import static com.nineoldandroids.view.ViewPropertyAnimator.animate; - -public class UndoBarController { - private View mBarView; - private TextView mMessageView; - private ViewPropertyAnimator mBarAnimator; - private Handler mHideHandler = new Handler(); - - private UndoListener mUndoListener; - - // State objects - private Parcelable mUndoToken; - private CharSequence mUndoMessage; - - public interface UndoListener { - void onUndo(Parcelable token); - } - - public UndoBarController(View undoBarView, UndoListener undoListener) { - mBarView = undoBarView; - mBarAnimator = animate(mBarView); - mUndoListener = undoListener; - - mMessageView = (TextView) mBarView.findViewById(R.id.undobar_message); - mBarView.findViewById(R.id.undobar_button) - .setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - hideUndoBar(false); - mUndoListener.onUndo(mUndoToken); - } - }); - - hideUndoBar(true); - } - - public void showUndoBar(boolean immediate, CharSequence message, Parcelable undoToken) { - mUndoToken = undoToken; - mUndoMessage = message; - mMessageView.setText(mUndoMessage); - - mHideHandler.removeCallbacks(mHideRunnable); - mHideHandler.postDelayed(mHideRunnable, - mBarView.getResources().getInteger(R.integer.undobar_hide_delay)); - - mBarView.setVisibility(View.VISIBLE); - if (immediate) { - ViewHelper.setAlpha(mBarView, 1); - } else { - mBarAnimator.cancel(); - mBarAnimator - .alpha(1) - .setDuration( - mBarView.getResources() - .getInteger(android.R.integer.config_shortAnimTime)) - .setListener(null); - } - } - - public void hideUndoBar(boolean immediate) { - mHideHandler.removeCallbacks(mHideRunnable); - if (immediate) { - mBarView.setVisibility(View.GONE); - ViewHelper.setAlpha(mBarView, 0); - mUndoMessage = null; - mUndoToken = null; - - } else { - mBarAnimator.cancel(); - mBarAnimator - .alpha(0) - .setDuration(mBarView.getResources() - .getInteger(android.R.integer.config_shortAnimTime)) - .setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mBarView.setVisibility(View.GONE); - mUndoMessage = null; - mUndoToken = null; - } - }); - } - } - - public void onSaveInstanceState(Bundle outState) { - outState.putCharSequence("undo_message", mUndoMessage); - outState.putParcelable("undo_token", mUndoToken); - } - - public void onRestoreInstanceState(Bundle savedInstanceState) { - if (savedInstanceState != null) { - mUndoMessage = savedInstanceState.getCharSequence("undo_message"); - mUndoToken = savedInstanceState.getParcelable("undo_token"); - - if (mUndoToken != null || !TextUtils.isEmpty(mUndoMessage)) { - showUndoBar(true, mUndoMessage, mUndoToken); - } - } - } - - private Runnable mHideRunnable = new Runnable() { - @Override - public void run() { - hideUndoBar(false); - } - }; -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 3b791f444..26dd2ec4c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -417,8 +417,8 @@ public abstract class PlaybackController { pauseResource = res.getResourceId(1, R.drawable.ic_pause_grey600_36dp); res.recycle(); } else { - playResource = R.drawable.ic_action_play_over_video; - pauseResource = R.drawable.ic_action_pause_over_video; + playResource = R.drawable.ic_av_play_circle_outline_80dp; + pauseResource = R.drawable.ic_av_pause_circle_outline_80dp; } switch (status) { diff --git a/core/src/main/res/drawable-hdpi/ic_action_pause_over_video.png b/core/src/main/res/drawable-hdpi/ic_action_pause_over_video.png Binary files differdeleted file mode 100755 index 64b07728f..000000000 --- a/core/src/main/res/drawable-hdpi/ic_action_pause_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-hdpi/ic_action_play_over_video.png b/core/src/main/res/drawable-hdpi/ic_action_play_over_video.png Binary files differdeleted file mode 100755 index a364ca7c2..000000000 --- a/core/src/main/res/drawable-hdpi/ic_action_play_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-hdpi/ic_av_pause_circle_outline_80dp.png b/core/src/main/res/drawable-hdpi/ic_av_pause_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..6f9df0934 --- /dev/null +++ b/core/src/main/res/drawable-hdpi/ic_av_pause_circle_outline_80dp.png diff --git a/core/src/main/res/drawable-hdpi/ic_av_play_circle_outline_80dp.png b/core/src/main/res/drawable-hdpi/ic_av_play_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..bddb0b024 --- /dev/null +++ b/core/src/main/res/drawable-hdpi/ic_av_play_circle_outline_80dp.png diff --git a/core/src/main/res/drawable-mdpi/ic_action_pause_over_video.png b/core/src/main/res/drawable-mdpi/ic_action_pause_over_video.png Binary files differdeleted file mode 100755 index f478ac321..000000000 --- a/core/src/main/res/drawable-mdpi/ic_action_pause_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_action_play_over_video.png b/core/src/main/res/drawable-mdpi/ic_action_play_over_video.png Binary files differdeleted file mode 100755 index 835ff3636..000000000 --- a/core/src/main/res/drawable-mdpi/ic_action_play_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_av_pause_circle_outline_80dp.png b/core/src/main/res/drawable-mdpi/ic_av_pause_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..08c523d48 --- /dev/null +++ b/core/src/main/res/drawable-mdpi/ic_av_pause_circle_outline_80dp.png diff --git a/core/src/main/res/drawable-mdpi/ic_av_play_circle_outline_80dp.png b/core/src/main/res/drawable-mdpi/ic_av_play_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..27738aacb --- /dev/null +++ b/core/src/main/res/drawable-mdpi/ic_av_play_circle_outline_80dp.png diff --git a/core/src/main/res/drawable-v21/overlay_button_circle_background.xml b/core/src/main/res/drawable-v21/overlay_button_circle_background.xml new file mode 100644 index 000000000..c121690df --- /dev/null +++ b/core/src/main/res/drawable-v21/overlay_button_circle_background.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <gradient + android:type="radial" + android:gradientRadius="37.5%p" + android:startColor="#000000" + android:endColor="@android:color/transparent"/> +</shape>
\ No newline at end of file diff --git a/core/src/main/res/drawable-xhdpi/ic_action_pause_over_video.png b/core/src/main/res/drawable-xhdpi/ic_action_pause_over_video.png Binary files differdeleted file mode 100755 index b0777a023..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_action_pause_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_action_play_over_video.png b/core/src/main/res/drawable-xhdpi/ic_action_play_over_video.png Binary files differdeleted file mode 100755 index 24331a48c..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_action_play_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_av_pause_circle_outline_80dp.png b/core/src/main/res/drawable-xhdpi/ic_av_pause_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..3288241e7 --- /dev/null +++ b/core/src/main/res/drawable-xhdpi/ic_av_pause_circle_outline_80dp.png diff --git a/core/src/main/res/drawable-xhdpi/ic_av_play_circle_outline_80dp.png b/core/src/main/res/drawable-xhdpi/ic_av_play_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..db7b695e9 --- /dev/null +++ b/core/src/main/res/drawable-xhdpi/ic_av_play_circle_outline_80dp.png diff --git a/core/src/main/res/drawable-xxhdpi/ic_action_pause_over_video.png b/core/src/main/res/drawable-xxhdpi/ic_action_pause_over_video.png Binary files differdeleted file mode 100755 index fa85601cf..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_action_pause_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_action_play_over_video.png b/core/src/main/res/drawable-xxhdpi/ic_action_play_over_video.png Binary files differdeleted file mode 100755 index 121be211e..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_action_play_over_video.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_av_pause_circle_outline_80dp.png b/core/src/main/res/drawable-xxhdpi/ic_av_pause_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..48e28102a --- /dev/null +++ b/core/src/main/res/drawable-xxhdpi/ic_av_pause_circle_outline_80dp.png diff --git a/core/src/main/res/drawable-xxhdpi/ic_av_play_circle_outline_80dp.png b/core/src/main/res/drawable-xxhdpi/ic_av_play_circle_outline_80dp.png Binary files differnew file mode 100644 index 000000000..b5918c0f1 --- /dev/null +++ b/core/src/main/res/drawable-xxhdpi/ic_av_play_circle_outline_80dp.png diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index 4f7ea5cf9..8003f93c0 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -17,7 +17,7 @@ <string name="downloads_completed_label">Fuldført</string> <string name="downloads_log_label">Log</string> <string name="cancel_download_label">Annuller Download</string> - <string name="playback_history_label">Afspilnings historik</string> + <string name="playback_history_label">Afspilningshistorik</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net login</string> <!--New episodes fragment--> diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index b91f1a5fd..4bd82db52 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -3,24 +3,35 @@ <!--Activitiy and fragment titles--> <string name="app_name">AntennaPod</string> <string name="feeds_label">Feed</string> + <string name="add_feed_label">Aggiungi un podcast</string> <string name="podcasts_label">PODCAST</string> <string name="episodes_label">EPISODI</string> + <string name="new_episodes_label">Episodi nuovi</string> + <string name="all_episodes_label">Tutti gli episodi</string> <string name="new_label">Nuovo</string> <string name="waiting_list_label">Lista d\'attesa</string> <string name="settings_label">Impostazioni</string> <string name="add_new_feed_label">Aggiungi podcast</string> <string name="downloads_label">Download</string> + <string name="downloads_running_label">In esecuzione</string> + <string name="downloads_completed_label">Completati</string> + <string name="downloads_log_label">Registro</string> <string name="cancel_download_label">Annulla download</string> <string name="playback_history_label">Storico delle riproduzioni</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net login</string> <!--New episodes fragment--> + <string name="recently_published_episodes_label">Pubblicati di recente</string> + <string name="episode_filter_label">Mostra solo gli episodi nuovi</string> <!--Main activity--> + <string name="drawer_open">Apri il menù</string> + <string name="drawer_close">Chiudi il menù</string> <!--Webview actions--> <string name="open_in_browser_label">Apri nel browser</string> <string name="copy_url_label">Copia URL</string> <string name="share_url_label">Condividi URL</string> <string name="copied_url_msg">URL copiato negli appunti</string> + <string name="go_to_position_label">Vai a questa posizione</string> <!--Playback history--> <string name="clear_history_label">Cancella lo storico</string> <!--Other--> @@ -49,10 +60,15 @@ <string name="auto_download_label">Includi nei download automatici</string> <!--'Add Feed' Activity labels--> <string name="feedurl_label">URL del feed</string> + <string name="etxtFeedurlHint">URL del feed o del sito web</string> <string name="txtvfeedurl_label">Aggiungi un Podcast tramite URL</string> + <string name="podcastdirectories_label">Trova un podcast nella directory</string> + <string name="browse_gpoddernet_label">Esplora gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Segna tutti come letti</string> + <string name="mark_all_read_msg">Segnati tutti gli episodi come letti</string> <string name="show_info_label">Informazioni</string> + <string name="remove_feed_label">Rimuovi un podcast</string> <string name="share_link_label">Condividi il link al sito</string> <string name="share_source_label">Condividi il link al feed</string> <string name="feed_delete_confirmation_msg">Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati.</string> @@ -61,8 +77,10 @@ <string name="download_label">Download</string> <string name="play_label">Riproduci</string> <string name="pause_label">Pausa</string> + <string name="stop_label">Ferma</string> <string name="stream_label">Stream</string> <string name="remove_label">Rimuovi</string> + <string name="remove_episode_lable">Rimuovi l\'episodio</string> <string name="mark_read_label">Segna come letto</string> <string name="mark_unread_label">Segna come non letto</string> <string name="add_to_queue_label">Aggiungi alla coda</string> @@ -84,6 +102,7 @@ <string name="download_error_unsupported_type">Tipo di feed non supportato</string> <string name="download_error_connection_error">Errore di connessione</string> <string name="download_error_unknown_host">Host sconosciuto</string> + <string name="download_error_unauthorized">Errore di autenticazione</string> <string name="cancel_all_downloads_label">Annulla tutti i download</string> <string name="download_cancelled_msg">Download annullato</string> <string name="download_report_title">Download completati</string> @@ -92,6 +111,7 @@ <string name="download_error_request_error">Request error</string> <string name="download_error_db_access">Errore di accesso al database</string> <string name="downloads_left">\u0020Download rimasti</string> + <string name="downloads_processing">Elaborazione dei download in corso</string> <string name="download_notification_title">Download podcast in corso</string> <string name="download_report_content">%1$d download con successo, %2$d ko</string> <string name="download_log_title_unknown">Titolo sconosciuto</string> @@ -99,6 +119,7 @@ <string name="download_type_media">Media file</string> <string name="download_type_image">Immagine</string> <string name="download_request_error_dialog_message_prefix">Rilevato errore durante il download del file:\u0020</string> + <string name="authentication_notification_title">Autenticazione richiesta</string> <!--Mediaplayer messages--> <string name="player_error_msg">Errore!</string> <string name="player_stopped_msg">Nessun media in riproduzione</string> @@ -189,6 +210,7 @@ <string name="pref_playback_speed_sum">Personalizza le velocità disponibili per la riproduzione audio a velocità variabile</string> <string name="pref_gpodnet_sethostname_title">Imposta l\'hostname</string> <string name="pref_gpodnet_sethostname_use_default_host">Usa l\'host di default</string> + <string name="pref_expandNotify_title">Espandi le notifiche</string> <!--Auto-Flattr dialog--> <!--Search--> <string name="search_hint">Ricerca per Feed o Episodi</string> @@ -221,6 +243,9 @@ <string name="sleep_timer_label">Timer di spegnimento</string> <string name="time_left_label">Tempo residuo:\u0020</string> <string name="time_dialog_invalid_input">Input non valido, il campo deve essere un numero intero.</string> + <string name="time_unit_seconds">secondi</string> + <string name="time_unit_minutes">minuti</string> + <string name="time_unit_hours">ore</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">CATEGORIE</string> <string name="gpodnet_toplist_header">TOP PODCAST</string> @@ -282,6 +307,9 @@ <string name="status_unread_label">L\'oggetto è nuovo</string> <string name="in_queue_label">L\'episodio è in coda</string> <string name="new_episodes_count_label">Numero dei nuovi episodi</string> + <string name="drag_handle_content_description">Trascina per cambiare la posizione di questo oggetto</string> + <string name="load_next_page_label">Carica la pagina successiva</string> <!--Feed information screen--> + <string name="authentication_label">Autenticazione</string> <!--AntennaPodSP--> </resources> |