diff options
Diffstat (limited to 'app/src/main/java')
14 files changed, 371 insertions, 38 deletions
diff --git a/app/src/main/java/org/rssin/android/FilterActivity.java b/app/src/main/java/org/rssin/android/FilterActivity.java new file mode 100644 index 0000000..145a60b --- /dev/null +++ b/app/src/main/java/org/rssin/android/FilterActivity.java @@ -0,0 +1,139 @@ +package org.rssin.android; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.support.v7.app.ActionBarActivity; +import android.os.Bundle; +import android.text.Html; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.VolleyError; + +import org.rssin.listener.FallibleListener; +import org.rssin.rss.FeedItem; +import org.rssin.rssin.FeedLoaderAndSorter; +import org.rssin.rssin.Filter; +import org.rssin.rssin.Keyword; +import org.rssin.rssin.R; + +import java.io.IOException; +import java.util.List; + +public class FilterActivity extends ActionBarActivity { + + private FiltersList filtersList; + private Filter filter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_filter); + + try { + filtersList = FiltersList.getInstance(this); + } catch (IOException e) { + Toast.makeText(this, getResources().getString(R.string.error_load_filters), Toast.LENGTH_SHORT).show(); + } + + Intent intent = getIntent(); + int filterHashCode = intent.getIntExtra("filter", -1); + + // @todo Check on -1? Shouldn't happen anyway. + filter = filtersList.getFilterFromHashCode(filterHashCode); + + final Activity activity = this; + final ListView itemsListView = (ListView) findViewById(R.id.filter_items_list); + FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(filter); + loaderAndSorter.getFilteredFeedItems(new VolleyFetcher(this), new FallibleListener<List<FeedItem>,VolleyError>() { + @Override + public void onReceive(List<FeedItem> data) { + FeedItemAdapter feedItemAdapter = new FeedItemAdapter(activity, R.layout.item_feeditem, data); + itemsListView.setAdapter(feedItemAdapter); + } + + @Override + public void onError(VolleyError error) { + Log.e("FA", "VolleyError", error); + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_filter, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + + if (id == R.id.action_settings) { + Intent intent = new Intent(getApplicationContext(), FilterSettingsActivity.class); + intent.putExtra("filter", filter.hashCode()); + startActivity(intent); + return true; + } + + return super.onOptionsItemSelected(item); + } + + /** + * Custom ArrayAdapter to display Keywords + */ + private static class FeedItemAdapter extends ArrayAdapter<FeedItem> { + Context context; + int layoutResourceId; + List<FeedItem> feedItems; + + public FeedItemAdapter(Context context, int resource, List<FeedItem> objects) { + super(context, resource, objects); + this.context = context; + layoutResourceId = resource; + feedItems = objects; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + KeywordHolder holder = null; + + if (row == null) { + LayoutInflater inflater = ((Activity) context).getLayoutInflater(); + row = inflater.inflate(layoutResourceId, parent, false); + + holder = new KeywordHolder(); + holder.title = (TextView) row.findViewById(R.id.feeditem_title); + holder.summary = (TextView) row.findViewById(R.id.feeditem_summary); + + row.setTag(holder); + } else { + holder = (KeywordHolder) row.getTag(); + } + + FeedItem feedItem = feedItems.get(position); + holder.title.setText(feedItem.getTitle()); + holder.summary.setText(Html.fromHtml(feedItem.getDescription())); + + return row; + } + + /** + * TextViews holder + */ + private static class KeywordHolder { + TextView title; + TextView summary; + } + } +} diff --git a/app/src/main/java/org/rssin/android/FiltersActivity.java b/app/src/main/java/org/rssin/android/FiltersActivity.java index b7de210..b5f8760 100644 --- a/app/src/main/java/org/rssin/android/FiltersActivity.java +++ b/app/src/main/java/org/rssin/android/FiltersActivity.java @@ -102,7 +102,7 @@ public class FiltersActivity extends ActionBarActivity { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Filter item = (Filter) parent.getItemAtPosition(position); - // @Todo open filter + openFilter(item); } }; onFilterLongClickListener = new AdapterView.OnItemLongClickListener() { @@ -175,6 +175,12 @@ public class FiltersActivity extends ActionBarActivity { startActivity(intent); } + public void openFilter(Filter f) { + Intent intent = new Intent(getApplicationContext(), FilterActivity.class); + intent.putExtra("filter", f.hashCode()); + startActivity(intent); + } + /** * Custom ArrayAdapter to display filters with our own menu item */ diff --git a/app/src/main/java/org/rssin/android/VolleyFetcher.java b/app/src/main/java/org/rssin/android/VolleyFetcher.java new file mode 100644 index 0000000..d853255 --- /dev/null +++ b/app/src/main/java/org/rssin/android/VolleyFetcher.java @@ -0,0 +1,59 @@ +package org.rssin.android; + +import android.content.Context; + +import com.android.volley.Request.Method; +import com.android.volley.RequestQueue; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.StringRequest; +import com.android.volley.toolbox.Volley; + +import org.rssin.http.Fetcher; +import org.rssin.http.Request; +import org.rssin.listener.ErrorListener; +import org.rssin.listener.Listener; + +/** + * Created by camilstaps on 21-5-15. + */ +public class VolleyFetcher implements Fetcher { + + private final Context context; + private final RequestQueue requestQueue; + + public VolleyFetcher(Context context) { + this.context = context; + requestQueue = Volley.newRequestQueue(context); + } + + @Override + public void fetch(Request request) { + fetch(request, null); + } + + @Override + public void fetch(Request request, final Listener listener) { + StringRequest stringRequest = new StringRequest( + Method.GET, + request.getURL().toString(), + new com.android.volley.Response.Listener<String>() { + @Override + public void onResponse(String s) { + try { + listener.onReceive(s); + } catch (ClassCastException e) {} + } + }, + new com.android.volley.Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError volleyError) { + try { + ((ErrorListener<VolleyError>) listener).onError(volleyError); + } catch (ClassCastException e) {} + } + }); + + requestQueue.add(stringRequest); + } + +} diff --git a/app/src/main/java/org/rssin/http/Fetcher.java b/app/src/main/java/org/rssin/http/Fetcher.java new file mode 100644 index 0000000..0052e38 --- /dev/null +++ b/app/src/main/java/org/rssin/http/Fetcher.java @@ -0,0 +1,13 @@ +package org.rssin.http; + +import org.rssin.listener.Listener; + +/** + * Load an HTTP request + */ +public interface Fetcher { + + void fetch(Request request); + void fetch(Request request, Listener listener); + +} diff --git a/app/src/main/java/org/rssin/http/Request.java b/app/src/main/java/org/rssin/http/Request.java new file mode 100644 index 0000000..b9861a5 --- /dev/null +++ b/app/src/main/java/org/rssin/http/Request.java @@ -0,0 +1,20 @@ +package org.rssin.http; + +import java.net.URL; + +/** + * Created by camilstaps on 21-5-15. + */ +public class Request { + + URL url; + + public Request(URL url) { + this.url = url; + } + + public URL getURL() { + return url; + } + +} diff --git a/app/src/main/java/org/rssin/listener/DismissListener.java b/app/src/main/java/org/rssin/listener/DismissListener.java new file mode 100644 index 0000000..cfdc51d --- /dev/null +++ b/app/src/main/java/org/rssin/listener/DismissListener.java @@ -0,0 +1,15 @@ +package org.rssin.listener; + +/** + * Created by camilstaps on 21-5-15. + */ +public class DismissListener implements Listener, RealtimeListener, ErrorListener, FallibleListener { + @Override + public void onError(Object error) {} + + @Override + public void finish() {} + + @Override + public void onReceive(Object data) {} +} diff --git a/app/src/main/java/org/rssin/listener/ErrorListener.java b/app/src/main/java/org/rssin/listener/ErrorListener.java new file mode 100644 index 0000000..5ad4f1b --- /dev/null +++ b/app/src/main/java/org/rssin/listener/ErrorListener.java @@ -0,0 +1,8 @@ +package org.rssin.listener; + +/** + * Created by camilstaps on 21-5-15. + */ +public interface ErrorListener<T> { + void onError(T error); +} diff --git a/app/src/main/java/org/rssin/listener/FallibleListener.java b/app/src/main/java/org/rssin/listener/FallibleListener.java new file mode 100644 index 0000000..4e1d113 --- /dev/null +++ b/app/src/main/java/org/rssin/listener/FallibleListener.java @@ -0,0 +1,7 @@ +package org.rssin.listener; + +/** + * Created by camilstaps on 21-5-15. + */ +public interface FallibleListener<T,E> extends Listener<T>, ErrorListener<E> { +} diff --git a/app/src/main/java/org/rssin/listener/Listener.java b/app/src/main/java/org/rssin/listener/Listener.java new file mode 100644 index 0000000..db1764c --- /dev/null +++ b/app/src/main/java/org/rssin/listener/Listener.java @@ -0,0 +1,8 @@ +package org.rssin.listener; + +/** + * Created by camilstaps on 21-5-15. + */ +public interface Listener<T> { + void onReceive(T data); +} diff --git a/app/src/main/java/org/rssin/listener/RealtimeListener.java b/app/src/main/java/org/rssin/listener/RealtimeListener.java new file mode 100644 index 0000000..82a4c91 --- /dev/null +++ b/app/src/main/java/org/rssin/listener/RealtimeListener.java @@ -0,0 +1,8 @@ +package org.rssin.listener; + +/** + * Created by camilstaps on 21-5-15. + */ +public interface RealtimeListener extends Listener { + void finish(); +} diff --git a/app/src/main/java/org/rssin/neurons/SentenceSplitter.java b/app/src/main/java/org/rssin/neurons/SentenceSplitter.java index 887439d..29e34bc 100755 --- a/app/src/main/java/org/rssin/neurons/SentenceSplitter.java +++ b/app/src/main/java/org/rssin/neurons/SentenceSplitter.java @@ -1,5 +1,6 @@ package org.rssin.neurons;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
@@ -8,7 +9,9 @@ import java.util.regex.Pattern; /**
* @author Jos.
*/
-public class SentenceSplitter {
+public class SentenceSplitter implements Serializable {
+ private static final long serialVersionUID = 0;
+
private final Pattern wordMatch = Pattern.compile("[\\w-]+");//For unicode support, add the Pattern.UNICODE_CHARACTER_CLASS flag. Works only in Java 7+.
public SentenceSplitter() {
diff --git a/app/src/main/java/org/rssin/rss/FeedLoader.java b/app/src/main/java/org/rssin/rss/FeedLoader.java index eabfebd..3220826 100644 --- a/app/src/main/java/org/rssin/rss/FeedLoader.java +++ b/app/src/main/java/org/rssin/rss/FeedLoader.java @@ -1,11 +1,13 @@ package org.rssin.rss; -import java.io.InputStream; -import java.net.HttpURLConnection; +import java.io.ByteArrayInputStream; import java.net.URL; import java.util.Date; import java.util.LinkedList; +import org.rssin.http.Fetcher; +import org.rssin.http.Request; +import org.rssin.listener.FallibleListener; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; @@ -214,25 +216,29 @@ public class FeedLoader { /** * Retrieves the XML and parses it. */ - public void fetchXML() { - try { - URL url = urlString; - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setReadTimeout(10000 /* milliseconds */); - conn.setConnectTimeout(15000 /* milliseconds */); - conn.setRequestMethod("GET"); - conn.setDoInput(true); - // Starts the query - conn.connect(); - InputStream stream = conn.getInputStream(); - xmlFactoryObject = XmlPullParserFactory.newInstance(); - XmlPullParser myparser = xmlFactoryObject.newPullParser(); - myparser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); - myparser.setInput(stream, null); - parseXMLAndStoreIt(myparser); - stream.close(); - } catch (Exception ignored) { - } + public void fetchXML(Fetcher fetcher, final FallibleListener<?,Object> listener) { + fetcher.fetch( + new Request(urlString), + new FallibleListener<String,Object>() { + @Override + public void onReceive(String data) { + try { + xmlFactoryObject = XmlPullParserFactory.newInstance(); + XmlPullParser parser = xmlFactoryObject.newPullParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); + parser.setInput(new ByteArrayInputStream(data.getBytes()), null); + parseXMLAndStoreIt(parser); + listener.onReceive(null); + } catch (XmlPullParserException e) { + listener.onError(e); + } + } + + @Override + public void onError(Object error) { + listener.onError(error); + } + }); } public void setFeed(Feed feed) { @@ -246,4 +252,5 @@ public class FeedLoader { public void setUrlString(URL urlString) { this.urlString = urlString; } + } diff --git a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java index e9d3e5d..0739e52 100755 --- a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java +++ b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java @@ -1,5 +1,9 @@ package org.rssin.rssin;
+import org.rssin.http.Fetcher;
+import org.rssin.listener.FallibleListener;
+import org.rssin.listener.Listener;
+import org.rssin.listener.RealtimeListener;
import org.rssin.neurons.FeedSorter;
import org.rssin.rss.FeedItem;
import org.rssin.rss.FeedLoader;
@@ -19,26 +23,62 @@ public class FeedLoaderAndSorter { /**
* Loads the feed(s), filters it, sorts it, and returns the result.
+ * @param fetcher
+ * @param listener
* @return The filtered & sorted list of feedtems.
*/
- public List<FeedItem> getFilteredFeedItems()
+ public void getFilteredFeedItems(Fetcher fetcher, final Listener<List<FeedItem>> listener)
{
- List<FeedItem> resultingItems = new ArrayList<FeedItem>();
- for(Feed feed : filter.getFeeds())
- {
- FeedLoader loader = new FeedLoader(feed.getURL());
- loader.fetchXML();
- for(FeedItem item : loader.getFeed().getPosts())
- {
- if(matchesKeyword(item))
- {
- resultingItems.add(item);
+ final List<FeedItem> resultingItems = new ArrayList<>();
+ final Counter counter = new Counter(filter.getFeeds().size());
+ final FeedSorter sorter = filter.getSorter();
+
+ for (Feed feed : filter.getFeeds()) {
+ final FeedLoader loader = new FeedLoader(feed.getURL());
+ loader.fetchXML(fetcher, new FallibleListener<Object, Object>() {
+ @Override
+ public void onReceive(Object data) {
+ for (FeedItem item : loader.getFeed().getPosts()) {
+ if(matchesKeyword(item)) {
+ resultingItems.add(item);
+ }
+ }
+
+ sorter.sortItems(resultingItems);
+
+ if (counter.decr().isZero() || listener.getClass() == RealtimeListener.class) {
+ listener.onReceive(resultingItems);
+ if (counter.decr().isZero() && listener.getClass() == RealtimeListener.class) {
+ ((RealtimeListener) listener).finish();
+ }
+ }
}
- }
+
+ @Override
+ public void onError(Object error) {
+ try {
+ ((FallibleListener) listener).onError(error);
+ } catch (ClassCastException e) {}
+ }
+ });
+ }
+ }
+
+ private static class Counter {
+ int count;
+
+ Counter (int initial) {
+ count = initial;
}
- FeedSorter sorter = filter.getSorter();
- return sorter.sortItems(resultingItems);
+ public Counter decr() {
+ count--;
+ return this;
+ }
+
+ public boolean isZero() {
+ return count == 0;
+ }
}
private boolean matchesKeyword(FeedItem item)
diff --git a/app/src/main/java/org/rssin/rssin/Filter.java b/app/src/main/java/org/rssin/rssin/Filter.java index 271b67d..50e3351 100755 --- a/app/src/main/java/org/rssin/rssin/Filter.java +++ b/app/src/main/java/org/rssin/rssin/Filter.java @@ -22,7 +22,7 @@ public class Filter implements Serializable { private final List<Feed> feeds; private final List<Keyword> keywords; private String title = ""; - private FeedSorter sorter; + private FeedSorter sorter = new FeedSorter(); public Filter() { feeds = new ArrayList<>(); |