diff --git a/res/values/strings.xml b/res/values/strings.xml index 0361177e7..138ca38d6 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,65 +1,71 @@ - + Podfetcher - Feeds - New - Settings - Add a new Feed + Feeds + New + Settings + Add a new Feed Downloads Cancel Download - - Confirm - Cancel + + Confirm + Cancel - - Feed URL + + Feed URL - - Download - Play - Description - Remove + + Download + Play + Description + Remove - - Download successful - Download failed - Download pending - Download running + + Download successful + Download failed + Download pending + Download running - - No feeds added yet. + + No feeds added yet. - - Paused - Error! - No media playing - Preparing... - Mark read - Mark unread - Version - Other - About - Show Log - Storage device not found - Insufficient space - File error - HTTP Data Error - Unknown Error - Show player - Add to Queue - Remove from Queue - Ready - Stream - Seeking - - Mark all read - Show information - Remove Feed - 00:00:00 - Queue - Visit Website - Support - + + Paused + Error! + No media playing + Preparing... + Mark read + Mark unread + Version + Other + About + Show Log + Storage device not found + Insufficient space + File error + HTTP Data Error + Unknown Error + Show player + Add to Queue + Remove from Queue + Ready + Stream + Seeking + + Mark all read + Show information + Remove Feed + 00:00:00 + Queue + Visit Website + Support + Parser Exception + Unsupported Feed type + Error + An error occured: + Connection error + + \ No newline at end of file diff --git a/src/de/podfetcher/activity/AddFeedActivity.java b/src/de/podfetcher/activity/AddFeedActivity.java index e43617c0d..e1da778eb 100644 --- a/src/de/podfetcher/activity/AddFeedActivity.java +++ b/src/de/podfetcher/activity/AddFeedActivity.java @@ -4,9 +4,11 @@ import android.os.Bundle; import android.widget.Button; import android.widget.EditText; import android.view.View; +import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.util.Log; @@ -16,6 +18,8 @@ import de.podfetcher.asynctask.DownloadStatus; import de.podfetcher.feed.Feed; import de.podfetcher.feed.FeedManager; import de.podfetcher.storage.DownloadRequester; +import de.podfetcher.util.ConnectionTester; +import de.podfetcher.util.DownloadError; import de.podfetcher.util.URLChecker; import de.podfetcher.service.DownloadService; @@ -52,7 +56,7 @@ public class AddFeedActivity extends SherlockActivity { requester = DownloadRequester.getInstance(); manager = FeedManager.getInstance(); - + progDialog = new ProgressDialog(this) { @Override public void onBackPressed() { @@ -61,7 +65,7 @@ public class AddFeedActivity extends SherlockActivity { } else { requester.cancelDownload(getContext(), downloadId); } - + unregisterReceiver(downloadCompleted); dismiss(); } @@ -93,7 +97,7 @@ public class AddFeedActivity extends SherlockActivity { super.onStop(); Log.d(TAG, "Stopping Activity"); } - + @Override protected void onPause() { super.onPause(); @@ -102,25 +106,48 @@ public class AddFeedActivity extends SherlockActivity { } catch (IllegalArgumentException e) { // ignore } - - } + } private void addNewFeed() { String url = etxtFeedurl.getText().toString(); url = URLChecker.prepareURL(url); if (url != null) { - Feed feed = new Feed(url, new Date()); - downloadId = requester.downloadFeed(this, feed); + final Feed feed = new Feed(url, new Date()); + final ConnectionTester conTester = new ConnectionTester(url, this, + new ConnectionTester.Callback() { + + @Override + public void onConnectionSuccessful() { + downloadId = requester.downloadFeed( + AddFeedActivity.this, feed); + + } + + @Override + public void onConnectionFailure() { + int reason = DownloadError.ERROR_CONNECTION_ERROR; + long statusId = manager.addDownloadStatus( + AddFeedActivity.this, new DownloadStatus( + feed, reason, false)); + Intent intent = new Intent(DownloadService.ACTION_DOWNLOAD_HANDLED); + intent.putExtra(DownloadService.EXTRA_DOWNLOAD_ID, downloadId); + intent.putExtra(DownloadService.EXTRA_STATUS_ID, statusId); + AddFeedActivity.this.sendBroadcast(intent); + } + }); observeDownload(feed); + new Thread(conTester).start(); + } } private void observeDownload(Feed feed) { progDialog.show(); progDialog.setMessage("Downloading Feed"); - registerReceiver(downloadCompleted, new IntentFilter(DownloadService.ACTION_DOWNLOAD_HANDLED)); + registerReceiver(downloadCompleted, new IntentFilter( + DownloadService.ACTION_DOWNLOAD_HANDLED)); } private void updateProgDialog(final String msg) { @@ -138,7 +165,20 @@ public class AddFeedActivity extends SherlockActivity { } private void handleDownloadError(DownloadStatus status) { - + final AlertDialog errorDialog = new AlertDialog.Builder(this).create(); + errorDialog.setTitle(R.string.error_label); + errorDialog.setMessage(getString(R.string.error_msg_prefix) + " " + + DownloadError.getErrorString(this, status.getReason())); + errorDialog.setButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + errorDialog.dismiss(); + } + }); + if (progDialog.isShowing()) { + progDialog.dismiss(); + } + errorDialog.show(); } private BroadcastReceiver downloadCompleted = new BroadcastReceiver() { diff --git a/src/de/podfetcher/service/DownloadService.java b/src/de/podfetcher/service/DownloadService.java index 288c4a288..3fb81c50a 100644 --- a/src/de/podfetcher/service/DownloadService.java +++ b/src/de/podfetcher/service/DownloadService.java @@ -11,6 +11,10 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.SAXException; + import de.podfetcher.activity.DownloadActivity; import de.podfetcher.activity.MediaplayerActivity; import de.podfetcher.asynctask.DownloadStatus; @@ -18,6 +22,8 @@ import de.podfetcher.feed.*; import de.podfetcher.service.PlaybackService.LocalBinder; import de.podfetcher.storage.DownloadRequester; import de.podfetcher.syndication.handler.FeedHandler; +import de.podfetcher.syndication.handler.UnsupportedFeedtypeException; +import de.podfetcher.util.DownloadError; import android.R; import android.app.NotificationManager; import android.app.PendingIntent; @@ -188,19 +194,21 @@ public class DownloadService extends Service { (FeedMedia) download); } successful = true; - queryDownloads(); + } else if (status == DownloadManager.STATUS_FAILED) { reason = c.getInt(c .getColumnIndex(DownloadManager.COLUMN_REASON)); - Log.d(TAG, "reason code is " + reason); + Log.e(TAG, "Download failed"); + Log.e(TAG, "reason code is " + reason); successful = false; long statusId = manager.addDownloadStatus(context, new DownloadStatus(download, reason, successful)); + requester.removeDownload(download); sendDownloadHandledIntent(download.getDownloadId(), statusId, false, 0); download.setDownloadId(0); } - + queryDownloads(); c.close(); } } @@ -271,25 +279,48 @@ public class DownloadService extends Service { public void run() { long imageId = 0; boolean hasImage = false; + long downloadId = feed.getDownloadId(); + int reason = 0; + boolean successful = true; FeedManager manager = FeedManager.getInstance(); FeedHandler handler = new FeedHandler(); feed.setDownloaded(true); - feed = handler.parseFeed(feed); - Log.d(TAG, feed.getTitle() + " parsed"); - // Download Feed Image if provided - if (feed.getImage() != null) { - Log.d(TAG, "Feed has image; Downloading...."); - imageId = requester.downloadImage(service, feed.getImage()); - hasImage = true; + + try { + feed = handler.parseFeed(feed); + Log.d(TAG, feed.getTitle() + " parsed"); + // Download Feed Image if provided + if (feed.getImage() != null) { + Log.d(TAG, "Feed has image; Downloading...."); + imageId = requester.downloadImage(service, feed.getImage()); + hasImage = true; + } + + feed.setDownloadId(0); + // Save information of feed in DB + manager.updateFeed(service, feed); + } catch (SAXException e) { + successful = false; + e.printStackTrace(); + reason = DownloadError.ERROR_PARSER_EXCEPTION; + } catch (IOException e) { + successful = false; + e.printStackTrace(); + reason = DownloadError.ERROR_PARSER_EXCEPTION; + } catch (ParserConfigurationException e) { + successful = false; + e.printStackTrace(); + reason = DownloadError.ERROR_PARSER_EXCEPTION; + } catch (UnsupportedFeedtypeException e) { + e.printStackTrace(); + successful = false; + reason = DownloadError.ERROR_UNSUPPORTED_TYPE; } + requester.removeDownload(feed); - cleanup(); - long statusId = manager.addDownloadStatus(service, new DownloadStatus(feed, 0, true)); - sendDownloadHandledIntent(feed.getDownloadId(), statusId, hasImage, imageId); - feed.setDownloadId(0); - // Save information of feed in DB - manager.updateFeed(service, feed); + long statusId = manager.addDownloadStatus(service, new DownloadStatus(feed, reason, successful)); + sendDownloadHandledIntent(downloadId, statusId, hasImage, imageId); queryDownloads(); } diff --git a/src/de/podfetcher/syndication/handler/FeedHandler.java b/src/de/podfetcher/syndication/handler/FeedHandler.java index 110ac2b90..f52dcbdec 100644 --- a/src/de/podfetcher/syndication/handler/FeedHandler.java +++ b/src/de/podfetcher/syndication/handler/FeedHandler.java @@ -12,25 +12,18 @@ import org.xml.sax.SAXException; import de.podfetcher.feed.Feed; public class FeedHandler { - - - public Feed parseFeed(Feed feed) { + + public Feed parseFeed(Feed feed) throws SAXException, IOException, + ParserConfigurationException, UnsupportedFeedtypeException { TypeGetter tg = new TypeGetter(); TypeGetter.Type type = tg.getType(feed); SyndHandler handler = new SyndHandler(feed, type); - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - SAXParser saxParser = factory.newSAXParser(); - saxParser.parse(new File(feed.getFile_url()), handler); - } catch (SAXException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch(ParserConfigurationException e) { - e.printStackTrace(); - } - + + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + SAXParser saxParser = factory.newSAXParser(); + saxParser.parse(new File(feed.getFile_url()), handler); + return handler.state.feed; } } diff --git a/src/de/podfetcher/syndication/handler/TypeGetter.java b/src/de/podfetcher/syndication/handler/TypeGetter.java index 71aa9970d..82bd371de 100644 --- a/src/de/podfetcher/syndication/handler/TypeGetter.java +++ b/src/de/podfetcher/syndication/handler/TypeGetter.java @@ -25,7 +25,7 @@ public class TypeGetter { private static final String ATOM_ROOT = "feed"; private static final String RSS_ROOT = "rss"; - public Type getType(Feed feed) { + public Type getType(Feed feed) throws UnsupportedFeedtypeException { XmlPullParserFactory factory; try { factory = XmlPullParserFactory.newInstance(); @@ -47,7 +47,7 @@ public class TypeGetter { return Type.RSS20; } else { Log.d(TAG, "Type is invalid"); - return Type.INVALID; + throw new UnsupportedFeedtypeException(Type.INVALID); } } else { eventType = xpp.next(); @@ -60,7 +60,7 @@ public class TypeGetter { e.printStackTrace(); } Log.d(TAG, "Type is invalid"); - return Type.INVALID; + throw new UnsupportedFeedtypeException(Type.INVALID); } private Reader createReader(Feed feed) { diff --git a/src/de/podfetcher/syndication/handler/UnsupportedFeedtypeException.java b/src/de/podfetcher/syndication/handler/UnsupportedFeedtypeException.java new file mode 100644 index 000000000..2ca6f02b0 --- /dev/null +++ b/src/de/podfetcher/syndication/handler/UnsupportedFeedtypeException.java @@ -0,0 +1,29 @@ +package de.podfetcher.syndication.handler; + +import de.podfetcher.syndication.handler.TypeGetter.Type; + +public class UnsupportedFeedtypeException extends Exception { + private static final long serialVersionUID = 9105878964928170669L; + private TypeGetter.Type type; + + public UnsupportedFeedtypeException(Type type) { + super(); + this.type = type; + + } + + public TypeGetter.Type getType() { + return type; + } + + @Override + public String getMessage() { + if (type == TypeGetter.Type.INVALID) { + return "Invalid type"; + } else { + return "Type " + type + " not supported"; + } + } + + +} diff --git a/src/de/podfetcher/util/ConnectionTester.java b/src/de/podfetcher/util/ConnectionTester.java new file mode 100644 index 000000000..80370292f --- /dev/null +++ b/src/de/podfetcher/util/ConnectionTester.java @@ -0,0 +1,66 @@ +package de.podfetcher.util; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; + +import android.content.Context; +import android.util.Log; + +/** Tests a connection before downloading something. */ +public class ConnectionTester implements Runnable { + private static final String TAG = "ConnectionTester"; + private String strUrl; + private Context context; + private int connectTimeout; + private int readTimeout; + private Callback callback; + private int reason; + + public ConnectionTester(String url, Context context, Callback callback) { + super(); + this.strUrl = url; + this.context = context; + this.callback = callback; + connectTimeout = 500; + readTimeout = connectTimeout; + } + + + + @Override + public void run() { + Log.d(TAG, "Testing connection"); + try { + URL url = new URL(strUrl); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.connect(); + callback.onConnectionSuccessful(); + Log.d(TAG, "Connection seems to work"); + } catch (MalformedURLException e) { + e.printStackTrace(); + reason = DownloadError.ERROR_CONNECTION_ERROR; + Log.d(TAG, "Connection failed"); + callback.onConnectionFailure(); + } catch (IOException e) { + e.printStackTrace(); + reason = DownloadError.ERROR_CONNECTION_ERROR; + Log.d(TAG, "Connection failed"); + callback.onConnectionFailure(); + } + } + + + public static abstract class Callback { + public abstract void onConnectionSuccessful(); + public abstract void onConnectionFailure(); + } + + public int getReason() { + return reason; + } + + +} diff --git a/src/de/podfetcher/util/DownloadError.java b/src/de/podfetcher/util/DownloadError.java index d808d2ac2..366bb3d3f 100644 --- a/src/de/podfetcher/util/DownloadError.java +++ b/src/de/podfetcher/util/DownloadError.java @@ -6,6 +6,11 @@ import android.content.Context; /** Utility class for Download Errors. */ public class DownloadError { + public static final int ERROR_PARSER_EXCEPTION = 1; + public static final int ERROR_UNSUPPORTED_TYPE = 2; + public static final int ERROR_CONNECTION_ERROR = 3; + + /** Get a human-readable string for a specific error code. */ public static String getErrorString(Context context, int code) { int resId; @@ -19,6 +24,15 @@ public class DownloadError { case DownloadManager.ERROR_HTTP_DATA_ERROR: resId = R.string.download_error_http_data_error; break; + case ERROR_PARSER_EXCEPTION: + resId = R.string.download_error_parser_exception; + break; + case ERROR_UNSUPPORTED_TYPE: + resId = R.string.download_error_unsupported_type; + break; + case ERROR_CONNECTION_ERROR: + resId = R.string.download_error_connection_error; + break; default: resId = R.string.download_error_error_unknown; }