diff options
author | Camil Staps | 2015-05-22 01:08:45 +0200 |
---|---|---|
committer | Camil Staps | 2015-05-22 01:08:45 +0200 |
commit | 76f2a89d39fda44553fdd8e71524fd27ce104c48 (patch) | |
tree | f769501403195d73705f82c32d357ded9eb6593b /app/src/main | |
parent | Added writeObject & readObject methods (diff) |
Store Filters and FeedSorters separately in Internal Storage
Diffstat (limited to 'app/src/main')
17 files changed, 250 insertions, 107 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4e125b5..e4f63c3 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,8 +3,6 @@ package="org.rssin.rssin" > <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:allowBackup="true" diff --git a/app/src/main/java/org/rssin/android/FilterActivity.java b/app/src/main/java/org/rssin/android/FilterActivity.java index 145a60b..1e114ad 100644 --- a/app/src/main/java/org/rssin/android/FilterActivity.java +++ b/app/src/main/java/org/rssin/android/FilterActivity.java @@ -3,6 +3,7 @@ package org.rssin.android; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.os.Debug; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.text.Html; @@ -39,6 +40,8 @@ public class FilterActivity extends ActionBarActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_filter); + long startTime = System.currentTimeMillis(); + try { filtersList = FiltersList.getInstance(this); } catch (IOException e) { @@ -50,11 +53,14 @@ public class FilterActivity extends ActionBarActivity { // @todo Check on -1? Shouldn't happen anyway. filter = filtersList.getFilterFromHashCode(filterHashCode); + filter.ensureFeedSorter(InternalStorageProvider.getInstance(this)); + + setTitle(filter.getTitle()); 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>() { + 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); @@ -63,6 +69,7 @@ public class FilterActivity extends ActionBarActivity { @Override public void onError(VolleyError error) { + Toast.makeText(getBaseContext(), getResources().getString(R.string.error_net_load), Toast.LENGTH_SHORT).show(); Log.e("FA", "VolleyError", error); } }); diff --git a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java index dccad12..b0791a3 100644 --- a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java +++ b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java @@ -10,6 +10,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -71,7 +72,7 @@ public class FilterSettingsActivity extends ActionBarActivity { filtersList.save(); keywordAdapter.notifyDataSetChanged(); return true; - } catch (IOException e) { + } catch (Exception e) { filter.getKeywords().add(keyword); keywordAdapter.notifyDataSetChanged(); Toast.makeText(getBaseContext(), getResources().getString(R.string.error_save_filters), Toast.LENGTH_SHORT).show(); @@ -103,7 +104,7 @@ public class FilterSettingsActivity extends ActionBarActivity { try { filtersList.save(); finish(); - } catch (IOException e) { + } catch (Exception e) { Toast.makeText(this, getResources().getString(R.string.error_delete_filter), Toast.LENGTH_SHORT).show(); } return true; @@ -159,7 +160,7 @@ public class FilterSettingsActivity extends ActionBarActivity { filter.setTitle(value); filtersList.save(); setTitle(); - } catch (IOException e) { + } catch (Exception e) { Toast.makeText(getBaseContext(), getResources().getString(R.string.error_save_filters), Toast.LENGTH_SHORT).show(); } setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); @@ -190,16 +191,18 @@ public class FilterSettingsActivity extends ActionBarActivity { public void addKeyword(View v) { EditText editText = (EditText) findViewById(R.id.filter_settings_add_keyword); String keyword = editText.getText().toString(); - editText.setText(""); Keyword k = new Keyword(keyword); filter.getKeywords().add(k); try { - filtersList.save(); + filter.store(InternalStorageProvider.getInstance()); keywordAdapter.notifyDataSetChanged(); - } catch (IOException e) { + editText.setText(""); + } catch (Exception e) { filter.getKeywords().remove(k); keywordAdapter.notifyDataSetChanged(); + Toast.makeText(this, getResources().getString(R.string.error_save_filters), Toast.LENGTH_SHORT).show(); + Log.e("FSA", e.getMessage(), e); } } @@ -227,7 +230,7 @@ public class FilterSettingsActivity extends ActionBarActivity { filtersList.save(); feedAdapter.notifyDataSetChanged(); return true; - } catch (IOException e) { + } catch (Exception e) { Toast.makeText(getActivity(), getResources().getString(R.string.error_save_filters), Toast.LENGTH_SHORT).show(); filter.getFeeds().add(feed); return false; @@ -251,7 +254,7 @@ public class FilterSettingsActivity extends ActionBarActivity { filtersList.save(); feedAdapter.notifyDataSetChanged(); editText.setText(""); - } catch (IOException e) { + } catch (Exception e) { Toast.makeText(getActivity(), getResources().getString(R.string.error_save_filters), Toast.LENGTH_SHORT).show(); filter.getFeeds().remove(feed); } diff --git a/app/src/main/java/org/rssin/android/FiltersActivity.java b/app/src/main/java/org/rssin/android/FiltersActivity.java index 63c667d..ab7061b 100755 --- a/app/src/main/java/org/rssin/android/FiltersActivity.java +++ b/app/src/main/java/org/rssin/android/FiltersActivity.java @@ -63,17 +63,9 @@ public class FiltersActivity extends ActionBarActivity { finish(); } - //putDummyFilter(); - final FilterAdapter adapter = new FilterAdapter(this, R.layout.item_filter, filtersList.getFilters()); filtersView.setAdapter(adapter); -// try { -// filtersList.save(); -// } catch (IOException ex) { -// Toast.makeText(this, getResources().getString(R.string.error_save_filters), Toast.LENGTH_SHORT).show(); -// } - setupListeners(); } @@ -146,7 +138,7 @@ public class FiltersActivity extends ActionBarActivity { filtersList.getFilters().add(f); filtersList.save(); openFilterSettings(f); - } catch (IOException e) { + } catch (Exception e) { Toast.makeText(getBaseContext(), getResources().getString(R.string.error_save_filters), Toast.LENGTH_SHORT).show(); } setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); @@ -232,21 +224,4 @@ public class FiltersActivity extends ActionBarActivity { } } - /** - * Dummy filter for testing - */ - private void putDummyFilter() { - filtersList.getFilters().clear(); - - Filter filter = new Filter("Filter test"); - filter.getKeywords().add(new Keyword("Test")); - try { - filter.getFeeds().add(new Feed("http://nu.nl/algemeen.rss", "Feed test 1")); - } catch (MalformedURLException e) {} - try { - filter.getFeeds().add(new Feed("http://nu.nl/sport.rss", "Feed test 2")); - } catch (MalformedURLException e) {} - filtersList.getFilters().add(filter); - } - } diff --git a/app/src/main/java/org/rssin/android/FiltersList.java b/app/src/main/java/org/rssin/android/FiltersList.java index 129cc27..020e1e0 100755 --- a/app/src/main/java/org/rssin/android/FiltersList.java +++ b/app/src/main/java/org/rssin/android/FiltersList.java @@ -1,55 +1,30 @@ package org.rssin.android; import android.content.Context; -import android.os.Debug; -import android.preference.PreferenceManager; -import android.util.Base64; -import android.util.Log; -import android.util.TimingLogger; import org.rssin.rssin.Filter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; import java.util.List; /** - * A list of filters that can be saved in sharedpreferences + * A list of filters that can be saved in internal storage * @author Camil Staps */ public class FiltersList { - private static final String PREF_KEY = "filters_list"; - private static FiltersList instance; private final List<Filter> filters; - private final Context context; /** - * Fetch from sharedPreferences - * @param context + * Fetch from internal storage + * @param context needed to get to internal storage * @throws IOException if data is corrupted, and deserializing fails */ protected FiltersList(Context context) throws IOException { - String filters = PreferenceManager.getDefaultSharedPreferences(context).getString(PREF_KEY, null); - if (filters == null) { - this.filters = new ArrayList<>(); - } else { - List<Filter> filters_list; - try { - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.decode(filters, Base64.DEFAULT))); - filters_list = (List) ois.readObject(); - } catch (ClassNotFoundException ex) { - filters_list = new ArrayList<>(); - } - this.filters = filters_list; - } - this.context = context; + InternalStorageProvider internalStorageProvider = InternalStorageProvider.getInstance(context); + filters = internalStorageProvider.allFilters(); } public static FiltersList getInstance(Context context) throws IOException { @@ -67,27 +42,21 @@ public class FiltersList { } /** - * Save in sharedPreferences - * @throws IOException if serializing failed + * Save all filters in internal storage + * @throws Exception if serializing or saving failed */ - public synchronized void save() throws IOException { - long startTime = System.currentTimeMillis(); - Log.d("FiltersList", "Start saving..."); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(filters); - oos.close(); - - Log.d("FiltersList", "Serializing took " + ( System.currentTimeMillis() - startTime) + "ms"); - - String string = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT); - - Log.d("FiltersList", "Converting to base64 took " + ( System.currentTimeMillis() - startTime) + "ms"); - - PreferenceManager.getDefaultSharedPreferences(context).edit().putString(PREF_KEY, string).commit(); - - Log.d("FiltersList", "Saving took " + ( System.currentTimeMillis() - startTime) + "ms"); + public synchronized void save() throws Exception { + Exception e = null; + for (Filter filter : filters) { + try { + filter.store(InternalStorageProvider.getInstance()); + } catch (Exception ex) { + e = ex; + } + } + if (e != null) { + throw e; + } } public Filter getFilterFromHashCode(int hashcode) { diff --git a/app/src/main/java/org/rssin/android/InternalStorageProvider.java b/app/src/main/java/org/rssin/android/InternalStorageProvider.java new file mode 100644 index 0000000..1d700e1 --- /dev/null +++ b/app/src/main/java/org/rssin/android/InternalStorageProvider.java @@ -0,0 +1,112 @@ +package org.rssin.android; + +import android.content.Context; +import android.util.Log; + +import org.rssin.neurons.FeedSorter; +import org.rssin.rssin.Filter; +import org.rssin.storage.FilterStorageProvider; +import org.rssin.storage.Storable; +import org.rssin.storage.StorageProvider; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by camilstaps on 21-5-15. + */ +public class InternalStorageProvider implements StorageProvider<String, Storable>, FilterStorageProvider<String> { + protected static final String PREFIX = "storage_", PREFIX_FILTER = "f_", PREFIX_FEEDSORTER = "fs_"; + + private static InternalStorageProvider instance; + + private final Context context; + + private InternalStorageProvider(Context context) { + this.context = context; + } + + public static InternalStorageProvider getInstance(Context context) { + if (instance == null) + instance = new InternalStorageProvider(context); + return instance; + } + + public static InternalStorageProvider getInstance() { + return instance; + } + + @Override + public synchronized void store(String key, Storable element) throws FileNotFoundException, IOException { + FileOutputStream fos = context.openFileOutput(getFilename(key, element), Context.MODE_PRIVATE); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(element); + oos.close(); + fos.close(); + } + + @Override + public Storable fetch(String key, Class className) throws ClassCastException, FileNotFoundException, IOException { + return fetchFromFilename(getFilename(key, className)); + } + + public Storable fetchFromFilename(String fileName) throws ClassCastException, FileNotFoundException, IOException { + FileInputStream fis = context.openFileInput(fileName); + ObjectInputStream ois = new ObjectInputStream(fis); + try { + return (Storable) ois.readObject(); + } catch (ClassNotFoundException e) { + return null; + } + } + + @Override + public String uniqueKey() { + return Integer.toString((int) System.currentTimeMillis()); + } + + protected String getFilename(String key, Storable object) { + return getFilename(key, object.getClass()); + } + + protected String getFilename(String key, Class className) { + if (className == Filter.class) { + return PREFIX + PREFIX_FILTER + sanitize(key); + } else if (className == FeedSorter.class){ + return PREFIX + PREFIX_FEEDSORTER + sanitize(key); + } else { + return PREFIX + sanitize(key); + } + } + + public static String sanitize(String key) { + return key.replaceAll("\\W+", ""); + } + + @Override + public List<Filter> allFilters() { + List<Filter> filters = new ArrayList<>(); + for (String fileName : context.fileList()) { + Log.d("ISP", "File: " + fileName); + try { + filters.add((Filter) fetchFromFilename(fileName)); + } catch (ClassCastException | IOException e) {} + } + return filters; + } + + @Override + public Filter getFilter(String key) { + try { + return (Filter) fetch(key, Filter.class); + } catch (ClassCastException | IOException e) { + return null; + } + } +} diff --git a/app/src/main/java/org/rssin/neurons/FeedSorter.java b/app/src/main/java/org/rssin/neurons/FeedSorter.java index d567e63..910057f 100755 --- a/app/src/main/java/org/rssin/neurons/FeedSorter.java +++ b/app/src/main/java/org/rssin/neurons/FeedSorter.java @@ -1,11 +1,10 @@ package org.rssin.neurons;
-import android.util.Log;
-
import org.rssin.rss.FeedItem;
+import org.rssin.storage.Storable;
+import org.rssin.tools.SerializationTools;
import java.io.IOException;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -18,7 +17,7 @@ import java.util.TimeZone; /**
* @author Jos.
*/
-public class FeedSorter implements Serializable {
+public class FeedSorter implements Storable {
private static final long serialVersionUID = 0;
private final SentenceSplitter splitter = new SentenceSplitter();
diff --git a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java index 68ddddd..0f5c31b 100755 --- a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java +++ b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java @@ -1,11 +1,9 @@ package org.rssin.neurons;
-import android.util.Log;
+import org.rssin.tools.SerializationTools;
import java.io.IOException;
import java.io.Serializable;
-import java.util.Hashtable;
-import java.util.List;
/**
* @author Jos
diff --git a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java index 0540652..2cbe284 100755 --- a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java +++ b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java @@ -1,7 +1,8 @@ package org.rssin.neurons;
import android.annotation.SuppressLint;
-import android.util.Log;
+
+import org.rssin.tools.SerializationTools;
import java.io.IOException;
import java.io.Serializable;
diff --git a/app/src/main/java/org/rssin/neurons/Neuron.java b/app/src/main/java/org/rssin/neurons/Neuron.java index ec4bf2c..6a4970a 100755 --- a/app/src/main/java/org/rssin/neurons/Neuron.java +++ b/app/src/main/java/org/rssin/neurons/Neuron.java @@ -1,6 +1,6 @@ package org.rssin.neurons;
-import android.util.Log;
+import org.rssin.tools.SerializationTools;
import java.io.IOException;
import java.io.Serializable;
diff --git a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java index 0739e52..4113436 100755 --- a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java +++ b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java @@ -7,6 +7,7 @@ import org.rssin.listener.RealtimeListener; import org.rssin.neurons.FeedSorter;
import org.rssin.rss.FeedItem;
import org.rssin.rss.FeedLoader;
+import org.rssin.storage.StorageProvider;
import java.util.ArrayList;
import java.util.List;
@@ -23,15 +24,14 @@ 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.
+ * @param fetcher HTTP Fetcher
+ * @param listener Listener for when the fetcher finishes
*/
public void getFilteredFeedItems(Fetcher fetcher, final Listener<List<FeedItem>> listener)
{
final List<FeedItem> resultingItems = new ArrayList<>();
final Counter counter = new Counter(filter.getFeeds().size());
- final FeedSorter sorter = filter.getSorter();
+ final FeedSorter sorter = filter.getFeedSorter();
for (Feed feed : filter.getFeeds()) {
final FeedLoader loader = new FeedLoader(feed.getURL());
diff --git a/app/src/main/java/org/rssin/rssin/Filter.java b/app/src/main/java/org/rssin/rssin/Filter.java index 50e3351..77b114e 100755 --- a/app/src/main/java/org/rssin/rssin/Filter.java +++ b/app/src/main/java/org/rssin/rssin/Filter.java @@ -2,7 +2,10 @@ package org.rssin.rssin; import android.text.TextUtils; +import org.rssin.android.InternalStorageProvider; import org.rssin.neurons.FeedSorter; +import org.rssin.storage.Storable; +import org.rssin.storage.StorageProvider; import java.io.Serializable; import java.util.ArrayList; @@ -12,7 +15,7 @@ import java.util.List; * Filter holder * @author Camil Staps */ -public class Filter implements Serializable { +public class Filter implements Storable { private static final long serialVersionUID = 0; @@ -22,7 +25,9 @@ public class Filter implements Serializable { private final List<Feed> feeds; private final List<Keyword> keywords; private String title = ""; - private FeedSorter sorter = new FeedSorter(); + + private Object storageKey; + private transient FeedSorter feedSorter; public Filter() { feeds = new ArrayList<>(); @@ -76,8 +81,23 @@ public class Filter implements Serializable { this.title = title.trim(); } - public FeedSorter getSorter() { - return sorter; + public FeedSorter getFeedSorter() { + return feedSorter; + } + + public synchronized void ensureFeedSorter(StorageProvider storageProvider) { + if (storageKey == null) { + storageKey = storageProvider.uniqueKey(); + } + + try { + feedSorter = (FeedSorter) storageProvider.fetch(storageKey, FeedSorter.class); + } catch (Exception e) { + feedSorter = new FeedSorter(); + try { + storageProvider.store(storageKey, feedSorter); + } catch (Exception e1) {} + } } @Override @@ -90,4 +110,16 @@ public class Filter implements Serializable { return sb.toString().hashCode(); } + + public synchronized void store(StorageProvider storageProvider) throws Exception { + if (storageKey == null) { + storageKey = storageProvider.uniqueKey(); + } + storageProvider.store(storageKey, this); + } + + public synchronized void storeFeedSorter(StorageProvider storageProvider) throws Exception { + ensureFeedSorter(storageProvider); + storageProvider.store(storageKey, feedSorter); + } } diff --git a/app/src/main/java/org/rssin/storage/FilterStorageProvider.java b/app/src/main/java/org/rssin/storage/FilterStorageProvider.java new file mode 100644 index 0000000..8032d07 --- /dev/null +++ b/app/src/main/java/org/rssin/storage/FilterStorageProvider.java @@ -0,0 +1,13 @@ +package org.rssin.storage; + +import org.rssin.rssin.Filter; + +import java.util.List; + +/** + * Created by camilstaps on 21-5-15. + */ +public interface FilterStorageProvider<K> { + List<Filter> allFilters(); + Filter getFilter(K key); +} diff --git a/app/src/main/java/org/rssin/storage/Storable.java b/app/src/main/java/org/rssin/storage/Storable.java new file mode 100644 index 0000000..feb850a --- /dev/null +++ b/app/src/main/java/org/rssin/storage/Storable.java @@ -0,0 +1,9 @@ +package org.rssin.storage; + +import java.io.Serializable; + +/** + * Created by camilstaps on 21-5-15. + */ +public interface Storable extends Serializable { +} diff --git a/app/src/main/java/org/rssin/storage/StorageProvider.java b/app/src/main/java/org/rssin/storage/StorageProvider.java new file mode 100644 index 0000000..ba62028 --- /dev/null +++ b/app/src/main/java/org/rssin/storage/StorageProvider.java @@ -0,0 +1,27 @@ +package org.rssin.storage; + +/** + * Created by camilstaps on 21-5-15. + */ +public interface StorageProvider<K,E extends Storable> { + /** + * Store an element + * @param key + * @param element + * @return + */ + void store(K key, E element) throws Exception; + + /** + * Fetch an element + * @param key + * @return + */ + E fetch(K key, Class className) throws Exception; + + /** + * Get a new, unique, usable key + * @return + */ + K uniqueKey(); +} diff --git a/app/src/main/java/org/rssin/neurons/SerializationTools.java b/app/src/main/java/org/rssin/tools/SerializationTools.java index 41e79f2..0886ded 100755 --- a/app/src/main/java/org/rssin/neurons/SerializationTools.java +++ b/app/src/main/java/org/rssin/tools/SerializationTools.java @@ -1,4 +1,4 @@ -package org.rssin.neurons;
+package org.rssin.tools;
import java.io.IOException;
import java.io.ObjectInputStream;
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3c6a364..da60e14 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,6 +10,7 @@ <string name="title_activity_filters">Filters</string> <string name="title_activity_filter_settings">Filter</string> + <string name="title_activity_filter">Filter</string> <string name="filters_action_add">Add</string> @@ -26,7 +27,6 @@ <string name="error_delete_filter">Couldn\'t delete filter</string> <string name="error_invalid_url">Invalid URL</string> - <string name="title_activity_filter">FilterActivity</string> - <string name="hello_world">Hello world!</string> + <string name="error_net_load">Internet problem</string> </resources> |