From e642fd72bcf507bb2258c8224e207b55061db08a Mon Sep 17 00:00:00 2001
From: Camil Staps
Date: Mon, 6 Apr 2015 21:41:41 +0200
Subject: initial commit
---
.../java/com/camilstaps/taize/ApplicationTest.java | 13 +
app/src/main/AndroidManifest.xml | 32 +++
.../main/java/com/camilstaps/common/Listener.java | 20 ++
.../java/com/camilstaps/common/NullListener.java | 14 +
.../java/com/camilstaps/rss/RetrieveFeedTask.java | 37 +++
.../main/java/com/camilstaps/rss/RssParser.java | 293 +++++++++++++++++++
app/src/main/java/com/camilstaps/taize/Bible.java | 86 ++++++
.../main/java/com/camilstaps/taize/BibleText.java | 73 +++++
.../java/com/camilstaps/taize/MainActivity.java | 165 +++++++++++
.../camilstaps/taize/NavigationDrawerFragment.java | 317 +++++++++++++++++++++
.../com/camilstaps/taize/SettingsActivity.java | 66 +++++
app/src/main/java/com/camilstaps/taize/Taize.java | 224 +++++++++++++++
app/src/main/res/drawable-hdpi/drawer_shadow.9.png | Bin 0 -> 161 bytes
app/src/main/res/drawable-hdpi/ic_drawer.png | Bin 0 -> 2829 bytes
app/src/main/res/drawable-mdpi/drawer_shadow.9.png | Bin 0 -> 142 bytes
app/src/main/res/drawable-mdpi/ic_drawer.png | Bin 0 -> 2820 bytes
.../main/res/drawable-xhdpi/drawer_shadow.9.png | Bin 0 -> 174 bytes
app/src/main/res/drawable-xhdpi/ic_drawer.png | Bin 0 -> 2836 bytes
.../main/res/drawable-xxhdpi/drawer_shadow.9.png | Bin 0 -> 208 bytes
app/src/main/res/drawable-xxhdpi/ic_drawer.png | Bin 0 -> 202 bytes
app/src/main/res/layout/activity_main.xml | 40 +++
app/src/main/res/layout/fragment_main.xml | 12 +
.../main/res/layout/fragment_navigation_drawer.xml | 5 +
app/src/main/res/menu/global.xml | 5 +
app/src/main/res/menu/main.xml | 8 +
app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3418 bytes
app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2206 bytes
app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4842 bytes
app/src/main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7718 bytes
app/src/main/res/values-w820dp/dimens.xml | 6 +
app/src/main/res/values/dimens.xml | 9 +
app/src/main/res/values/preference_values.xml | 152 ++++++++++
app/src/main/res/values/strings.xml | 13 +
app/src/main/res/values/styles.xml | 8 +
app/src/main/res/xml/preferences.xml | 27 ++
35 files changed, 1625 insertions(+)
create mode 100644 app/src/androidTest/java/com/camilstaps/taize/ApplicationTest.java
create mode 100644 app/src/main/AndroidManifest.xml
create mode 100644 app/src/main/java/com/camilstaps/common/Listener.java
create mode 100644 app/src/main/java/com/camilstaps/common/NullListener.java
create mode 100644 app/src/main/java/com/camilstaps/rss/RetrieveFeedTask.java
create mode 100644 app/src/main/java/com/camilstaps/rss/RssParser.java
create mode 100644 app/src/main/java/com/camilstaps/taize/Bible.java
create mode 100644 app/src/main/java/com/camilstaps/taize/BibleText.java
create mode 100644 app/src/main/java/com/camilstaps/taize/MainActivity.java
create mode 100644 app/src/main/java/com/camilstaps/taize/NavigationDrawerFragment.java
create mode 100644 app/src/main/java/com/camilstaps/taize/SettingsActivity.java
create mode 100644 app/src/main/java/com/camilstaps/taize/Taize.java
create mode 100644 app/src/main/res/drawable-hdpi/drawer_shadow.9.png
create mode 100644 app/src/main/res/drawable-hdpi/ic_drawer.png
create mode 100644 app/src/main/res/drawable-mdpi/drawer_shadow.9.png
create mode 100644 app/src/main/res/drawable-mdpi/ic_drawer.png
create mode 100644 app/src/main/res/drawable-xhdpi/drawer_shadow.9.png
create mode 100644 app/src/main/res/drawable-xhdpi/ic_drawer.png
create mode 100644 app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png
create mode 100644 app/src/main/res/drawable-xxhdpi/ic_drawer.png
create mode 100644 app/src/main/res/layout/activity_main.xml
create mode 100644 app/src/main/res/layout/fragment_main.xml
create mode 100644 app/src/main/res/layout/fragment_navigation_drawer.xml
create mode 100644 app/src/main/res/menu/global.xml
create mode 100644 app/src/main/res/menu/main.xml
create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png
create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png
create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png
create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png
create mode 100644 app/src/main/res/values-w820dp/dimens.xml
create mode 100644 app/src/main/res/values/dimens.xml
create mode 100644 app/src/main/res/values/preference_values.xml
create mode 100644 app/src/main/res/values/strings.xml
create mode 100644 app/src/main/res/values/styles.xml
create mode 100644 app/src/main/res/xml/preferences.xml
(limited to 'app/src')
diff --git a/app/src/androidTest/java/com/camilstaps/taize/ApplicationTest.java b/app/src/androidTest/java/com/camilstaps/taize/ApplicationTest.java
new file mode 100644
index 0000000..215c930
--- /dev/null
+++ b/app/src/androidTest/java/com/camilstaps/taize/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.camilstaps.taize;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..6ae08cb
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/camilstaps/common/Listener.java b/app/src/main/java/com/camilstaps/common/Listener.java
new file mode 100644
index 0000000..36319c6
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/common/Listener.java
@@ -0,0 +1,20 @@
+package com.camilstaps.common;
+
+/**
+ * Abstract class for something listening for some object
+ * @author Camil Staps
+ */
+public abstract class Listener {
+
+ /**
+ * To be called when the data is successfully retrieved
+ * @param data
+ */
+ public abstract void success(T data);
+
+ /**
+ * To be called when the data could not be retrieved
+ */
+ public abstract void failure();
+
+}
diff --git a/app/src/main/java/com/camilstaps/common/NullListener.java b/app/src/main/java/com/camilstaps/common/NullListener.java
new file mode 100644
index 0000000..c22e76d
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/common/NullListener.java
@@ -0,0 +1,14 @@
+package com.camilstaps.common;
+
+/**
+ * Listener that discards all data and errors.
+ * @author Camil Staps
+ */
+public class NullListener extends Listener {
+
+ @Override
+ public void success(T data) { }
+
+ @Override
+ public void failure() { }
+}
diff --git a/app/src/main/java/com/camilstaps/rss/RetrieveFeedTask.java b/app/src/main/java/com/camilstaps/rss/RetrieveFeedTask.java
new file mode 100644
index 0000000..543c9d6
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/rss/RetrieveFeedTask.java
@@ -0,0 +1,37 @@
+package com.camilstaps.rss;
+
+import android.os.AsyncTask;
+
+import com.camilstaps.common.Listener;
+
+/**
+ * Asynchronously retrieve an RSS feed
+ * @author Camil Staps
+ */
+public class RetrieveFeedTask extends AsyncTask {
+
+ Listener listener;
+
+ public void setRssDownloadListener(Listener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ protected RssParser doInBackground(String... params) {
+ try {
+ RssParser parser = new RssParser(params[0]);
+ return parser;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(RssParser results) {
+ if (results != null) {
+ listener.success(results);
+ } else {
+ listener.failure();
+ }
+ }
+}
diff --git a/app/src/main/java/com/camilstaps/rss/RssParser.java b/app/src/main/java/com/camilstaps/rss/RssParser.java
new file mode 100644
index 0000000..2c32abd
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/rss/RssParser.java
@@ -0,0 +1,293 @@
+package com.camilstaps.rss;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import android.util.Log;
+
+/**
+ * RSS parser
+ *
+ * See: http://stackoverflow.com/a/24985128/1544337
+ *
+ * Usage:
+ * RssParser parser = new RssParser(feedUrl);
+ * Log.i("LOG", "Description: " + parser.getItem(3).description); //4th item's description
+ *
+ * @author Camil Staps
+ */
+public class RssParser extends DefaultHandler {
+
+ private StringBuilder content;
+ private boolean inChannel;
+ private boolean inImage;
+ private boolean inItem;
+
+ private ArrayList- items = new ArrayList
- ();
+ private Channel channel = new Channel();
+
+ private Item lastItem;
+
+
+ public RssParser(String url) {
+ try {
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ SAXParser sp = spf.newSAXParser();
+ XMLReader xr = sp.getXMLReader();
+ URL sourceUrl = new URL(url);
+ xr.setContentHandler(this);
+ xr.parse(new InputSource(sourceUrl.openStream()));
+ }
+ catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ }
+ catch (SAXException e) {
+ e.printStackTrace();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public class Item {
+
+ public String title;
+ public String description;
+ public String link;
+ public String category;
+ public String pubDate;
+ public String guid;
+ }
+
+
+ public class Channel {
+
+ public String title;
+ public String description;
+ public String link;
+ public String lastBuildDate;
+ public String generator;
+ public String imageUrl;
+ public String imageTitle;
+ public String imageLink;
+ public String imageWidth;
+ public String imageHeight;
+ public String imageDescription;
+ public String language;
+ public String copyright;
+ public String pubDate;
+ public String category;
+ public String ttl;
+ }
+
+
+ @Override
+ public void startDocument() throws SAXException {
+ Log.i("LOG", "StartDocument");
+ }
+
+
+ @Override
+ public void endDocument() throws SAXException {
+ Log.i("LOG", "EndDocument");
+ }
+
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ if (localName.equalsIgnoreCase("image")) {
+ inImage = true;
+ }
+
+ if (localName.equalsIgnoreCase("channel")) {
+ inChannel = true;
+ }
+
+ if (localName.equalsIgnoreCase("item")) {
+ lastItem = new Item();
+ items.add(lastItem);
+ inItem = true;
+ }
+
+ content = new StringBuilder();
+ }
+
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (localName.equalsIgnoreCase("image")) {
+ inImage = false;
+ }
+
+ if (localName.equalsIgnoreCase("channel")) {
+ inChannel = false;
+ }
+
+ if (localName.equalsIgnoreCase("item")) {
+ inItem = false;
+ }
+
+ if (localName.equalsIgnoreCase("title")) {
+ if (content == null) {
+ return;
+ }
+
+ if (inItem) {
+ lastItem.title = content.toString();
+ } else if (inImage) {
+ channel.imageTitle = content.toString();
+ } else if (inChannel) {
+ channel.title = content.toString();
+ }
+
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("description")) {
+ if (content == null) {
+ return;
+ }
+
+ if (inItem) {
+ lastItem.description = content.toString();
+ } else if (inImage) {
+ channel.imageDescription = content.toString();
+ } else if (inChannel) {
+ channel.description = content.toString();
+ }
+
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("link")) {
+ if (content == null) {
+ return;
+ }
+
+ if (inItem) {
+ lastItem.link = content.toString();
+ } else if (inImage) {
+ channel.imageLink = content.toString();
+ } else if (inChannel) {
+ channel.link = content.toString();
+ }
+
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("category")) {
+ if (content == null) {
+ return;
+ }
+
+ if (inItem) {
+ lastItem.category = content.toString();
+ } else if (inChannel) {
+ channel.category = content.toString();
+ }
+
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("pubDate")) {
+ if (content == null) {
+ return;
+ }
+
+ if (inItem) {
+ lastItem.pubDate = content.toString();
+ } else if (inChannel) {
+ channel.pubDate = content.toString();
+ }
+
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("guid")) {
+ if (content == null) {
+ return;
+ }
+
+ lastItem.guid = content.toString();
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("url")) {
+ if (content == null) {
+ return;
+ }
+
+ channel.imageUrl = content.toString();
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("width")) {
+ if (content == null) {
+ return;
+ }
+
+ channel.imageWidth = content.toString();
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("height")) {
+ if (content == null) {
+ return;
+ }
+
+ channel.imageHeight = content.toString();
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("language")) {
+ if (content == null) {
+ return;
+ }
+
+ channel.language = content.toString();
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("copyright")) {
+ if (content == null) {
+ return;
+ }
+
+ channel.copyright = content.toString();
+ content = null;
+ }
+
+ if (localName.equalsIgnoreCase("ttl")) {
+ if (content == null) {
+ return;
+ }
+
+ channel.ttl = content.toString();
+ content = null;
+ }
+ }
+
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (content == null) {
+ return;
+ }
+
+ content.append(ch, start, length);
+ }
+
+
+ public Item getItem(int index) {
+ return items.get(index);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/camilstaps/taize/Bible.java b/app/src/main/java/com/camilstaps/taize/Bible.java
new file mode 100644
index 0000000..451c7cb
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/taize/Bible.java
@@ -0,0 +1,86 @@
+package com.camilstaps.taize;
+
+import android.content.Context;
+import android.preference.PreferenceManager;
+
+import com.android.volley.Request;
+import com.android.volley.RequestQueue;
+import com.android.volley.Response;
+import com.android.volley.toolbox.StringRequest;
+import com.android.volley.toolbox.Volley;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.URLEncoder;
+import java.util.Iterator;
+
+/**
+ * Use the Bible API of getbible.net
+ *
+ * @author Camil Staps
+ */
+public class Bible {
+
+ /**
+ * Base URL of the API
+ */
+ private static final String BASE_URL = "https://getbible.net/json?";
+
+ /**
+ * Request data from the API
+ * @param context context to handle from
+ * @param query_string Query string with parameters for the API
+ * @param listener listener; passed on to Volley, for processing the result
+ * @param errorListener errorListener for when some error occurs
+ */
+ private static void request(Context context, String query_string, Response.Listener listener, Response.ErrorListener errorListener) {
+ RequestQueue queue = Volley.newRequestQueue(context);
+ StringRequest request = new StringRequest(Request.Method.GET, BASE_URL + "v=" + getVersion(context) + "&" + query_string, listener, errorListener);
+ queue.add(request);
+ }
+
+ /**
+ * Get the Bible version (i.e., the translation) from the preferences of the user
+ * @param context context to handle from
+ * @return the version from the preferences
+ */
+ public static String getVersion(Context context) {
+ return PreferenceManager.getDefaultSharedPreferences(context).getString(SettingsActivity.SettingsFragment.PREF_VERSION_BIBLE, context.getResources().getString(R.string.pref_version_bible_default));
+ }
+
+ /**
+ * Get a passage from the API
+ * @param context context to handle from
+ * @param passage indicator for the passage, using English full book names (i.e. "Mark 7:13-18")
+ * @param listener listener; passed on to Volley, for processing the result
+ * @param errorListener errorListener for when some error occurs
+ */
+ public static void getPassage(Context context, String passage, final Response.Listener listener, final Response.ErrorListener errorListener) {
+ request(context, "p=" + URLEncoder.encode(passage), new Response.Listener() {
+ @Override
+ public void onResponse(String s) {
+ StringBuilder passage = new StringBuilder();
+ try {
+ JSONObject response = new JSONObject(s.substring( 1, s.length() - 2));
+ JSONArray books = response.getJSONArray("book");
+ for (int b = 0; b < books.length(); b++) {
+ JSONObject chapter = books.getJSONObject(b).getJSONObject("chapter");
+ Iterator> verses = chapter.keys();
+ while (verses.hasNext()) {
+ String verse_number = (String) verses.next();
+ JSONObject verse = chapter.getJSONObject(verse_number);
+ passage.append(verse.getString("verse")).append(" ");
+ }
+ }
+ } catch (JSONException e) {
+ passage.append("No Bible text found.");
+ }
+
+ listener.onResponse(passage.toString());
+ }
+ }, errorListener);
+ }
+
+}
diff --git a/app/src/main/java/com/camilstaps/taize/BibleText.java b/app/src/main/java/com/camilstaps/taize/BibleText.java
new file mode 100644
index 0000000..db73a78
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/taize/BibleText.java
@@ -0,0 +1,73 @@
+package com.camilstaps.taize;
+
+import android.content.Context;
+
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+
+/**
+ * Class for holding some text in the Bible
+ *
+ * @author Camil Staps
+ */
+public class BibleText {
+
+ private String book;
+ private int start_chap, end_chap, start_verse, end_verse;
+
+ /**
+ * Constructor for a bible text consisting of a single verse
+ * @param book
+ * @param chapter
+ * @param verse
+ */
+ public BibleText(String book, int chapter, int verse) {
+ this.book = book;
+ start_chap = end_chap = chapter;
+ start_verse = end_verse = verse;
+ }
+
+ /**
+ * Constructor for a bible text consisting of a "verse range"
+ * @param book
+ * @param start_chap
+ * @param start_verse
+ * @param end_chap
+ * @param end_verse
+ */
+ public BibleText(String book, int start_chap, int start_verse, int end_chap, int end_verse) {
+ this.book = book;
+ this.start_chap = start_chap;
+ this.end_chap = end_chap;
+ this.start_verse = start_verse;
+ this.end_verse = end_verse;
+ }
+
+ /**
+ * Get the text (without verse numbers, line breaks, etc.) of this passage
+ * @param context
+ * @param listener
+ * @param errorListener
+ */
+ public void getText(Context context, Response.Listener listener, Response.ErrorListener errorListener) {
+ String passage = "";
+
+ if (start_chap == end_chap) {
+ if (start_verse == end_verse) {
+ passage = book + " " + start_chap + ":" + start_verse;
+ } else {
+ passage = book + " " + start_chap + ":" + start_verse + "-" + end_verse;
+ }
+ } else {
+ StringBuilder passageBuilder = new StringBuilder();
+ passageBuilder.append(book + " " + start_chap + ":" + start_verse);
+ for (int i = start_chap + 1; i <= end_chap; i++)
+ passageBuilder.append(";" + i);
+ passageBuilder.append("-" + end_verse);
+ passage = passageBuilder.toString();
+ }
+
+ Bible.getPassage(context, passage, listener, errorListener);
+ }
+
+}
diff --git a/app/src/main/java/com/camilstaps/taize/MainActivity.java b/app/src/main/java/com/camilstaps/taize/MainActivity.java
new file mode 100644
index 0000000..b3bf748
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/taize/MainActivity.java
@@ -0,0 +1,165 @@
+package com.camilstaps.taize;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.ActionBar;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.support.v4.widget.DrawerLayout;
+import android.widget.TextView;
+
+
+public class MainActivity extends ActionBarActivity
+ implements NavigationDrawerFragment.NavigationDrawerCallbacks {
+
+ /**
+ * Fragment managing the behaviors, interactions and presentation of the navigation drawer.
+ */
+ private NavigationDrawerFragment mNavigationDrawerFragment;
+
+ /**
+ * Used to store the last screen title. For use in {@link #restoreActionBar()}.
+ */
+ private CharSequence mTitle;
+
+ private String reading;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mNavigationDrawerFragment = (NavigationDrawerFragment)
+ getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
+ mTitle = getTitle();
+
+ // Set up the drawer.
+ mNavigationDrawerFragment.setUp(
+ R.id.navigation_drawer,
+ (DrawerLayout) findViewById(R.id.drawer_layout));
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ super.onSaveInstanceState(savedInstanceState);
+ savedInstanceState.putString("textview_dailyreading", ((TextView) findViewById(R.id.textDailyReading)).getText().toString());
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ ((TextView) findViewById(R.id.textDailyReading)).setText(savedInstanceState.getString("textview_dailyreading"));
+ }
+
+ @Override
+ public void onNavigationDrawerItemSelected(int position) {
+ // update the main content by replacing fragments
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ fragmentManager.beginTransaction()
+ .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
+ .commit();
+ }
+
+ public void onSectionAttached(int number) {
+ switch (number) {
+ case 1:
+ mTitle = getString(R.string.title_section1);
+ break;
+ case 2:
+ mTitle = getString(R.string.title_section2);
+ break;
+ }
+ }
+
+ public void restoreActionBar() {
+ ActionBar actionBar = getSupportActionBar();
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+ actionBar.setDisplayShowTitleEnabled(true);
+ actionBar.setTitle(mTitle);
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ if (!mNavigationDrawerFragment.isDrawerOpen()) {
+ // Only show items in the action bar relevant to this screen
+ // if the drawer is not showing. Otherwise, let the drawer
+ // decide what to show in the action bar.
+ getMenuInflater().inflate(R.menu.main, menu);
+ restoreActionBar();
+ return true;
+ }
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ Intent intent = new Intent(this, SettingsActivity.class);
+ startActivity(intent);
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * A placeholder fragment containing a simple view.
+ */
+ public static class PlaceholderFragment extends Fragment {
+ /**
+ * The fragment argument representing the section number for this
+ * fragment.
+ */
+ private static final String ARG_SECTION_NUMBER = "section_number";
+
+ /**
+ * Returns a new instance of this fragment for the given section
+ * number.
+ */
+ public static PlaceholderFragment newInstance(int sectionNumber) {
+ PlaceholderFragment fragment = new PlaceholderFragment();
+ Bundle args = new Bundle();
+ args.putInt(ARG_SECTION_NUMBER, sectionNumber);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ public PlaceholderFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_main, container, false);
+
+ return rootView;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ ((MainActivity) activity).onSectionAttached(getArguments().getInt(ARG_SECTION_NUMBER));
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/camilstaps/taize/NavigationDrawerFragment.java b/app/src/main/java/com/camilstaps/taize/NavigationDrawerFragment.java
new file mode 100644
index 0000000..3bb1556
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/taize/NavigationDrawerFragment.java
@@ -0,0 +1,317 @@
+package com.camilstaps.taize;
+
+import android.support.v7.app.ActionBarActivity;
+import android.app.Activity;
+import android.support.v7.app.ActionBar;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.text.Html;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.volley.VolleyError;
+import com.camilstaps.common.Listener;
+
+/**
+ * Fragment used for managing interactions for and presentation of a navigation drawer.
+ * See the
+ * design guidelines for a complete explanation of the behaviors implemented here.
+ */
+public class NavigationDrawerFragment extends Fragment {
+
+ /**
+ * Remember the position of the selected item.
+ */
+ private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
+
+ /**
+ * Per the design guidelines, you should show the drawer on launch until the user manually
+ * expands it. This shared preference tracks this.
+ */
+ private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
+
+ /**
+ * A pointer to the current callbacks instance (the Activity).
+ */
+ private NavigationDrawerCallbacks mCallbacks;
+
+ /**
+ * Helper component that ties the action bar to the navigation drawer.
+ */
+ private ActionBarDrawerToggle mDrawerToggle;
+
+ private DrawerLayout mDrawerLayout;
+ private ListView mDrawerListView;
+ private View mFragmentContainerView;
+
+ private int mCurrentSelectedPosition = 0;
+ private boolean mFromSavedInstanceState;
+ private boolean mUserLearnedDrawer;
+
+ public NavigationDrawerFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Read in the flag indicating whether or not the user has demonstrated awareness of the
+ // drawer. See PREF_USER_LEARNED_DRAWER for details.
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
+
+ if (savedInstanceState != null) {
+ mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
+ mFromSavedInstanceState = true;
+ }
+
+ // Select either the default item (0) or the last selected item.
+ selectItem(mCurrentSelectedPosition);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ // Indicate that this fragment would like to influence the set of actions in the action bar.
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mDrawerListView = (ListView) inflater.inflate(
+ R.layout.fragment_navigation_drawer, container, false);
+ mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ selectItem(position);
+ }
+ });
+ mDrawerListView.setAdapter(new ArrayAdapter(
+ getActionBar().getThemedContext(),
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ new String[]{
+ getString(R.string.title_section1),
+ getString(R.string.title_section2),
+ }));
+ mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
+ return mDrawerListView;
+ }
+
+ public boolean isDrawerOpen() {
+ return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
+ }
+
+ /**
+ * Users of this fragment must call this method to set up the navigation drawer interactions.
+ *
+ * @param fragmentId The android:id of this fragment in its activity's layout.
+ * @param drawerLayout The DrawerLayout containing this fragment's UI.
+ */
+ public void setUp(int fragmentId, DrawerLayout drawerLayout) {
+ mFragmentContainerView = getActivity().findViewById(fragmentId);
+ mDrawerLayout = drawerLayout;
+
+ // set a custom shadow that overlays the main content when the drawer opens
+ mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
+ // set up the drawer's list view with items and click listener
+
+ ActionBar actionBar = getActionBar();
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setHomeButtonEnabled(true);
+
+ // ActionBarDrawerToggle ties together the the proper interactions
+ // between the navigation drawer and the action bar app icon.
+ mDrawerToggle = new ActionBarDrawerToggle(
+ getActivity(), /* host Activity */
+ mDrawerLayout, /* DrawerLayout object */
+ R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
+ R.string.navigation_drawer_open, /* "open drawer" description for accessibility */
+ R.string.navigation_drawer_close /* "close drawer" description for accessibility */
+ ) {
+ @Override
+ public void onDrawerClosed(View drawerView) {
+ super.onDrawerClosed(drawerView);
+ if (!isAdded()) {
+ return;
+ }
+
+ getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
+ }
+
+ @Override
+ public void onDrawerOpened(View drawerView) {
+ super.onDrawerOpened(drawerView);
+ if (!isAdded()) {
+ return;
+ }
+
+ if (!mUserLearnedDrawer) {
+ // The user manually opened the drawer; store this flag to prevent auto-showing
+ // the navigation drawer automatically in the future.
+ mUserLearnedDrawer = true;
+ SharedPreferences sp = PreferenceManager
+ .getDefaultSharedPreferences(getActivity());
+ sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
+ }
+
+ getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
+ }
+ };
+
+ // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
+ // per the navigation drawer design guidelines.
+ if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
+ mDrawerLayout.openDrawer(mFragmentContainerView);
+ }
+
+ // Defer code dependent on restoration of previous instance state.
+ mDrawerLayout.post(new Runnable() {
+ @Override
+ public void run() {
+ mDrawerToggle.syncState();
+ }
+ });
+
+ mDrawerLayout.setDrawerListener(mDrawerToggle);
+ }
+
+ private void selectItem(int position) {
+ mCurrentSelectedPosition = position;
+ if (mDrawerListView != null) {
+ mDrawerListView.setItemChecked(position, true);
+ }
+ if (mDrawerLayout != null) {
+ mDrawerLayout.closeDrawer(mFragmentContainerView);
+ }
+ if (mCallbacks != null) {
+ mCallbacks.onNavigationDrawerItemSelected(position);
+ }
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mCallbacks = (NavigationDrawerCallbacks) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mCallbacks = null;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ // Forward the new configuration the drawer toggle component.
+ mDrawerToggle.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ // If the drawer is open, show the global app actions in the action bar. See also
+ // showGlobalContextActionBar, which controls the top-left area of the action bar.
+ if (mDrawerLayout != null && isDrawerOpen()) {
+ inflater.inflate(R.menu.global, menu);
+ showGlobalContextActionBar();
+ }
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (mDrawerToggle.onOptionsItemSelected(item)) {
+ return true;
+ }
+
+ if (item.getItemId() == R.id.action_update) {
+ //Toast.makeText(getActivity(), "Example action.", Toast.LENGTH_SHORT).show();
+
+ final TextView reading = (TextView) getActivity().findViewById(R.id.textDailyReading);
+
+ Taize.getDailyReading(getActivity(), new Listener() {
+ @Override
+ public void success(String data) {
+ reading.setText(Html.fromHtml(data));
+ }
+
+ @Override
+ public void failure() {
+ reading.setText("Error fetching reading.");
+ }
+ });
+
+ reading.append("\n\n");
+
+ Taize.getDailyReadingBibleText(getActivity(), new Listener() {
+ @Override
+ public void success(String data) {
+ Log.i("LOG", "Success.");
+ Log.i("LOG", data);
+ reading.append(Html.fromHtml(data));
+ }
+
+ @Override
+ public void failure() {
+ Log.i("LOG", "Failure.");
+ }
+ });
+
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Per the navigation drawer design guidelines, updates the action bar to show the global app
+ * 'context', rather than just what's in the current screen.
+ */
+ private void showGlobalContextActionBar() {
+ ActionBar actionBar = getActionBar();
+ actionBar.setDisplayShowTitleEnabled(true);
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+ actionBar.setTitle(R.string.app_name);
+ }
+
+ private ActionBar getActionBar() {
+ return ((ActionBarActivity) getActivity()).getSupportActionBar();
+ }
+
+ /**
+ * Callbacks interface that all activities using this fragment must implement.
+ */
+ public static interface NavigationDrawerCallbacks {
+ /**
+ * Called when an item in the navigation drawer is selected.
+ */
+ void onNavigationDrawerItemSelected(int position);
+ }
+}
diff --git a/app/src/main/java/com/camilstaps/taize/SettingsActivity.java b/app/src/main/java/com/camilstaps/taize/SettingsActivity.java
new file mode 100644
index 0000000..c8f3b3d
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/taize/SettingsActivity.java
@@ -0,0 +1,66 @@
+package com.camilstaps.taize;
+
+
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+
+import com.camilstaps.common.NullListener;
+
+public class SettingsActivity extends PreferenceActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
+ }
+
+ private static Preference.OnPreferenceChangeListener onPreferenceChangeListener = new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference pref, Object newValue) {
+ String stringValue = newValue.toString();
+
+ if (pref instanceof ListPreference) {
+ ListPreference listPref = (ListPreference) pref;
+ int index = listPref.findIndexOfValue(stringValue);
+ pref.setSummary(index >= 0 ? listPref.getEntries()[index] : null); // .getEntry() seems to cause problems
+ } else {
+ pref.setSummary(stringValue);
+ }
+
+ // If the preference actually changed ...
+ if (!PreferenceManager.getDefaultSharedPreferences(pref.getContext()).getString(pref.getKey(), "").equals(stringValue)) {
+ if (pref.getKey().equals(SettingsFragment.PREF_LANGUAGE_READINGS)) { // If we select a new language, set the fetch time to 0 to refetch on next request
+ Taize.forceNewDailyReading(pref.getContext(), new NullListener());
+ } else if (pref.getKey().equals(SettingsFragment.PREF_VERSION_BIBLE)) { // If we select a new bible, set the fetch time to 0 to refetch on next request
+ Taize.forceNewDailyReadingBibleText(pref.getContext(), new NullListener());
+ }
+ }
+
+ return true;
+ }
+ };
+
+ private static void bindSummaryToValue(Preference pref) {
+ pref.setOnPreferenceChangeListener(onPreferenceChangeListener);
+ onPreferenceChangeListener.onPreferenceChange(pref, PreferenceManager.getDefaultSharedPreferences(pref.getContext()).getString(pref.getKey(), pref.getSummary().toString()));
+ }
+
+ public static class SettingsFragment extends PreferenceFragment {
+ public static final String PREF_LANGUAGE_READINGS = "pref_language_reading";
+ public static final String PREF_VERSION_BIBLE = "pref_version_bible";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.preferences);
+
+ bindSummaryToValue(findPreference(PREF_LANGUAGE_READINGS));
+ bindSummaryToValue(findPreference(PREF_VERSION_BIBLE));
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/camilstaps/taize/Taize.java b/app/src/main/java/com/camilstaps/taize/Taize.java
new file mode 100644
index 0000000..edfe9e7
--- /dev/null
+++ b/app/src/main/java/com/camilstaps/taize/Taize.java
@@ -0,0 +1,224 @@
+package com.camilstaps.taize;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+import com.camilstaps.common.Listener;
+import com.camilstaps.common.NullListener;
+import com.camilstaps.rss.RetrieveFeedTask;
+import com.camilstaps.rss.RssParser;
+
+import java.util.concurrent.ExecutionException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Class specific to methods for Taize
+ * @author Camil Staps
+ */
+public class Taize {
+
+ private static final String url_reading_feed = "http://www.taize.fr/readingrss.php";
+ private static final String url_reading_feed_en = "http://www.taize.fr/readingrss.php?lang=en";
+
+ /**
+ * Force fetching a new bible text for the daily reading
+ * @see this#getDailyReadingBibleText
+ * @param context
+ * @param listener
+ */
+ public static void forceNewDailyReadingBibleText(final Context context, final Listener listener) {
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ editor.putLong("dailyreadingbiblefetch", 0);
+ editor.putLong("englishdailyreadingfetch", 0);
+ editor.commit();
+ getDailyReadingBibleText(context, listener);
+ }
+
+ /**
+ * Fetch the bible text corresponding to the daily reading
+ * @see this#forceNewDailyReadingBibleText
+ * @param context
+ * @param listener
+ */
+ public static void getDailyReadingBibleText(final Context context, final Listener listener) {
+ if (System.currentTimeMillis() - PreferenceManager.getDefaultSharedPreferences(context).getLong("dailyreadingbiblefetch", 0) > 3600000) {
+
+ getEnglishDailyReading(context, new Listener() {
+ @Override
+ public void success(String reading) {
+
+ Log.i("LOG", "Matching: " + reading);
+
+ Pattern bible_ref = Pattern.compile("\\((\\d? ?[a-zA-Z]+) (\\d{1,2}):(\\d+)-?(\\d+?)\\)");
+ Matcher bible_ref_m = bible_ref.matcher(reading);
+
+ if (!bible_ref_m.find()) {
+ failure();
+ return;
+ }
+
+ BibleText text = new BibleText(bible_ref_m.group(1), Integer.parseInt(bible_ref_m.group(2)), Integer.parseInt(bible_ref_m.group(3)), Integer.parseInt(bible_ref_m.group(2)), Integer.parseInt(bible_ref_m.group(4)));
+
+ text.getText(context, new Response.Listener() {
+ @Override
+ public void onResponse(String s) {
+ Log.i("LOG", "Bible text: " + s);
+ PreferenceManager.getDefaultSharedPreferences(context).edit().putString("dailyreadingbible", s).apply();
+ listener.success(s);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError volleyError) {
+ Log.e("NET", "Failed to fetch bible text.");
+ }
+ });
+
+ }
+
+ @Override
+ public void failure() {
+ listener.failure();
+ }
+ });
+
+ PreferenceManager.getDefaultSharedPreferences(context).edit().putLong("dailyreadingbiblefetch", System.currentTimeMillis()).apply();
+
+ } else {
+
+ listener.success(PreferenceManager.getDefaultSharedPreferences(context).getString("dailyreadingbible", "No bible text found."));
+
+ }
+ }
+
+ /**
+ * Force fetching a new English daily reading
+ * @see this#getEnglishDailyReading
+ * @param context
+ * @param listener
+ */
+ private static void forceNewEnglishDailyReading(final Context context, final Listener listener) {
+ PreferenceManager.getDefaultSharedPreferences(context).edit().putLong("englishdailyreadingfetch", 0).commit();
+ getEnglishDailyReading(context, listener);
+ }
+
+ /**
+ * Get the English daily reading (needed for the English Bible reference)
+ * @see this#forceNewEnglishDailyReading
+ * @param context
+ * @param listener
+ */
+ private static void getEnglishDailyReading(final Context context, final Listener listener) {
+ if (System.currentTimeMillis() - PreferenceManager.getDefaultSharedPreferences(context).getLong("englishdailyreadingfetch", 0) > 3600000) {
+
+ RetrieveFeedTask retrieve = new RetrieveFeedTask();
+ retrieve.setRssDownloadListener(new Listener() {
+ @Override
+ public void success(RssParser parser) {
+ try {
+ String reading = parser.getItem(0).description.trim();
+
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ editor.putString("englishdailyreading", reading);
+ editor.putLong("englishdailyreadingfetch", System.currentTimeMillis());
+ editor.apply();
+
+ listener.success(reading);
+ } catch (Exception e) {
+ failure();
+ }
+ }
+
+ @Override
+ public void failure() {
+ Log.i("LOG", "Failed to update.");
+ listener.failure();
+ }
+ });
+
+ try {
+ retrieve.execute(url_reading_feed_en).get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+
+ } else {
+
+ listener.success(PreferenceManager.getDefaultSharedPreferences(context).getString("englishdailyreading", "No daily reading found."));
+
+ }
+ }
+
+ /**
+ * Force fetching a new daily reading
+ * @see this#getDailyReading
+ * @param context
+ * @param listener
+ */
+ public static void forceNewDailyReading(final Context context, final Listener listener) {
+ PreferenceManager.getDefaultSharedPreferences(context).edit().putLong("dailyreadingfetch", 0).commit();
+ getDailyReading(context, listener);
+ }
+
+ /**
+ * Fetch the daily reading
+ * @see this#forceNewDailyReading
+ * @param context
+ * @param listener
+ */
+ public static void getDailyReading(final Context context, final Listener listener) {
+ if (System.currentTimeMillis() - PreferenceManager.getDefaultSharedPreferences(context).getLong("dailyreadingfetch", 0) > 3600000) {
+
+ RetrieveFeedTask retrieve = new RetrieveFeedTask();
+ retrieve.setRssDownloadListener(new Listener() {
+ @Override
+ public void success(RssParser parser) {
+ try {
+ String reading = parser.getItem(0).description.trim();
+
+ if (!reading.equals(PreferenceManager.getDefaultSharedPreferences(context).getString("dailyreading", ""))) {
+ forceNewDailyReadingBibleText(context, new NullListener());
+ }
+
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ editor.putString("dailyreading", reading);
+ editor.putLong("dailyreadingfetch", System.currentTimeMillis());
+ editor.apply();
+
+ listener.success(reading);
+ } catch (Exception e) {
+ failure();
+ }
+ }
+
+ @Override
+ public void failure() {
+ Log.i("LOG", "Failed to update.");
+ listener.failure();
+ }
+ });
+
+ try {
+ retrieve.execute(url_reading_feed + "?lang=" + PreferenceManager.getDefaultSharedPreferences(context).getString(SettingsActivity.SettingsFragment.PREF_LANGUAGE_READINGS, "en")).get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+
+ } else {
+
+ listener.success(PreferenceManager.getDefaultSharedPreferences(context).getString("dailyreading", "No daily reading found."));
+
+ }
+ }
+
+ //http://www.taize.fr/pdcrss.xml
+
+}
diff --git a/app/src/main/res/drawable-hdpi/drawer_shadow.9.png b/app/src/main/res/drawable-hdpi/drawer_shadow.9.png
new file mode 100644
index 0000000..236bff5
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/drawer_shadow.9.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_drawer.png b/app/src/main/res/drawable-hdpi/ic_drawer.png
new file mode 100644
index 0000000..c59f601
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_drawer.png differ
diff --git a/app/src/main/res/drawable-mdpi/drawer_shadow.9.png b/app/src/main/res/drawable-mdpi/drawer_shadow.9.png
new file mode 100644
index 0000000..ffe3a28
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/drawer_shadow.9.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_drawer.png b/app/src/main/res/drawable-mdpi/ic_drawer.png
new file mode 100644
index 0000000..1ed2c56
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_drawer.png differ
diff --git a/app/src/main/res/drawable-xhdpi/drawer_shadow.9.png b/app/src/main/res/drawable-xhdpi/drawer_shadow.9.png
new file mode 100644
index 0000000..fabe9d9
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/drawer_shadow.9.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_drawer.png b/app/src/main/res/drawable-xhdpi/ic_drawer.png
new file mode 100644
index 0000000..a5fa74d
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_drawer.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png b/app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png
new file mode 100644
index 0000000..b91e9d7
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_drawer.png b/app/src/main/res/drawable-xxhdpi/ic_drawer.png
new file mode 100644
index 0000000..9c4685d
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_drawer.png differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..17ea429
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml
new file mode 100644
index 0000000..ef0bd84
--- /dev/null
+++ b/app/src/main/res/layout/fragment_main.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_navigation_drawer.xml b/app/src/main/res/layout/fragment_navigation_drawer.xml
new file mode 100644
index 0000000..c05742d
--- /dev/null
+++ b/app/src/main/res/layout/fragment_navigation_drawer.xml
@@ -0,0 +1,5 @@
+
diff --git a/app/src/main/res/menu/global.xml b/app/src/main/res/menu/global.xml
new file mode 100644
index 0000000..326a6a7
--- /dev/null
+++ b/app/src/main/res/menu/global.xml
@@ -0,0 +1,5 @@
+
diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml
new file mode 100644
index 0000000..1ee42b7
--- /dev/null
+++ b/app/src/main/res/menu/main.xml
@@ -0,0 +1,8 @@
+
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..074e7a0
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,9 @@
+
+
+ 16dp
+ 16dp
+
+
+ 240dp
+
diff --git a/app/src/main/res/values/preference_values.xml b/app/src/main/res/values/preference_values.xml
new file mode 100644
index 0000000..754ec9e
--- /dev/null
+++ b/app/src/main/res/values/preference_values.xml
@@ -0,0 +1,152 @@
+
+
+ Settings
+
+
+ Language of the readings
+ en
+ English
+
+
- English
+ - čeština
+ - dansk
+ - Deutsch
+ - Español
+ - eesti
+ - suomi
+ - français
+ - hrvatski
+ - magyar
+ - Indonesia
+ - italiano
+ - 日本語
+ - 한국어
+ - lietuvių
+ - Nederlands
+ - norsk
+ - polski
+ - Português
+ - русский
+ - slovenčina
+ - slovenščina
+ - svenska
+ - 中文
+
+
+ - en
+ - cs
+ - da
+ - de
+ - es
+ - et
+ - fi
+ - fr
+ - hr
+ - hu
+ - id
+ - it
+ - ja
+ - ko
+ - lt
+ - nl
+ - no
+ - pl
+ - pt
+ - ru
+ - sk
+ - sl
+ - sv
+ - zh
+
+
+ Bible
+ kjv
+ King James Version
+
+ - Afrikaans: Ou Vertaling
+ - Albanian: Albanian
+ - Amharic: Haile Selassie Amharic Bible
+ - Arabic: Smith and Van Dyke
+ - Chinese: NCV Traditional
+ - Chinese: Union Simplified
+ - Chinese: NCV Simplified
+ - Chinese: Union Traditional
+ - Croatian: Croatian
+ - Danish: Danish
+ - Dutch: Dutch Staten Vertaling
+ - English: King James Version
+ - English: KJV Easy Read
+ - English: American Standard Version
+ - English: Amplified Version
+ - English: Basic English Bible
+ - English: Darby
+ - English: New American Standard
+ - English: Young\'s Literal Translation
+ - English: World English Bible
+ - English: Webster\'s Bible
+ - Esperanto: Esperanto
+ - Estonian: Estonian
+ - Finnish: Finnish Bible
+ - French: Martin
+ - German: Luther
+ - Greek: Greek Modern
+ - Greek: Textus Receptus
+ - Hebrew: Aleppo Codex
+ - Hungarian: Hungarian Karoli
+ - Italian: Giovanni Diodati Bible
+ - Korean: Korean
+ - Norwegian: Bibelselskap
+ - Portuguese: Almeida Atualizada
+ - Russian: Synodal Translation
+ - Spanish: Reina Valera
+ - Swahili: Swahili
+ - Swedish: Swedish
+ - Turkish: Turkish
+ - Vietnamese: Vietnamese
+ - Xhosa: Xhosa
+
+
+ - aov
+ - albanian
+ - hsab
+ - arabicsv
+ - cnt
+ - cus
+ - cns
+ - cut
+ - croatia
+ - danish
+ - statenvertaling
+ - kjv
+ - akjv
+ - asv
+ - amp
+ - basicenglish
+ - darby
+ - nasb
+ - ylt
+ - web
+ - wb
+ - esperanto
+ - estonian
+ - finnish1776
+ - martin
+ - luther1912
+ - moderngreek
+ - text
+ - aleppo
+ - karoli
+ - giovanni
+ - korean
+ - bibelselskap
+ - almeida
+ - synodal
+ - valera
+ - swahili
+ - swedish
+ - turkish
+ - vietnamese
+ - xhosa
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..32383f1
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,13 @@
+
+ Taizé
+
+ Daily Reading
+ Daily Meditation
+
+ Open navigation drawer
+ Close navigation drawer
+
+ Update
+
+ Settings
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..766ab99
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
new file mode 100644
index 0000000..1525761
--- /dev/null
+++ b/app/src/main/res/xml/preferences.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
--
cgit v1.2.3