diff --git a/app/build.gradle b/app/build.gradle
index 13249cb..b81cee2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -21,7 +21,7 @@ repositories {
android {
compileSdkVersion 23
- buildToolsVersion "23.0.2"
+ buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.bixlabs.smssolidario"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a570b18..2fa4044 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -36,6 +36,11 @@
android:label="@string/title_activity_settings"
android:screenOrientation="portrait" >
+
+
diff --git a/app/src/main/java/com/bixlabs/smssolidario/activity/HistoryActivity.java b/app/src/main/java/com/bixlabs/smssolidario/activity/HistoryActivity.java
new file mode 100644
index 0000000..32234a1
--- /dev/null
+++ b/app/src/main/java/com/bixlabs/smssolidario/activity/HistoryActivity.java
@@ -0,0 +1,107 @@
+package com.bixlabs.smssolidario.activity;
+
+import android.app.ProgressDialog;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.Loader;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.ViewFlipper;
+
+import com.bixlabs.smssolidario.R;
+import com.bixlabs.smssolidario.adapters.HistoryCursorAdapter;
+import com.bixlabs.smssolidario.persistency.DatabaseHelper;
+import com.bixlabs.smssolidario.persistency.HistoryLoader;
+
+public class HistoryActivity extends AppCompatActivity
+ implements LoaderManager.LoaderCallbacks {
+
+ private ViewFlipper viewFlipper;
+ private ListView historyListview;
+ private HistoryCursorAdapter historyAdapter;
+ private DatabaseHelper databaseHelper;
+ private ProgressDialog progressDialog;
+
+ // Dismiss the Progress Dialog and make the ViewFlipper visible
+ // inside a Handler (which runs on the UI thread).
+ private final Handler progressDialogHandler = new Handler(new Handler.Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ if (historyAdapter.getCount() == 0) {
+ viewFlipper.setDisplayedChild(1);
+ } else {
+ viewFlipper.setDisplayedChild(0);
+ }
+ viewFlipper.setVisibility(View.VISIBLE);
+ progressDialog.dismiss();
+ return true;
+ }
+ });
+
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_history);
+
+ // Set the actionbar title and home button
+ final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_main);
+ toolbar.setTitle(R.string.donations_history);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ progressDialog = ProgressDialog.show(this, getString(R.string.history_progressdialog_title),
+ getString(R.string.history_progressdialog_message), true, false);
+
+ viewFlipper = (ViewFlipper) this.findViewById(R.id.view_flipper_history);
+ historyListview = (ListView) this.findViewById(R.id.list_history);
+ historyAdapter = new HistoryCursorAdapter(this, null);
+ historyListview.setAdapter(historyAdapter);
+
+ databaseHelper = new DatabaseHelper(getApplicationContext());
+
+ // Make the ViewFlipper invisible until the loader has finished loading data
+ viewFlipper.setVisibility(View.INVISIBLE);
+
+ // Initialize the loader
+ getSupportLoaderManager().initLoader(0, null, this);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem menuItem) {
+ if (menuItem.getItemId() == android.R.id.home) {
+ finish();
+ }
+ return super.onOptionsItemSelected(menuItem);
+ }
+
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ return new HistoryLoader(getApplicationContext(), databaseHelper);
+ }
+
+ @Override
+ public void onLoadFinished(Loader loader, final Cursor data) {
+ // We can't swap the cursor inside the Handler because the DB
+ // would be already closed by that time. The good thing is that
+ // swapping takes a few milliseconds (tested with 10.000 rows of data) so
+ // it's completely transparent to the user.
+ historyAdapter.swapCursor(data);
+
+ // Send a delayed message to the ProgressDialog handler to avoid dialog flickering
+ // in case the data is loaded too fast. From a user perspective it introduces
+ // consistency.
+ progressDialogHandler.sendEmptyMessageDelayed(0, 1200); // 1.2 second
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {
+ historyAdapter.swapCursor(null);
+ }
+}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/activity/MainActivity.java b/app/src/main/java/com/bixlabs/smssolidario/activity/MainActivity.java
index 2a4292d..0a14387 100644
--- a/app/src/main/java/com/bixlabs/smssolidario/activity/MainActivity.java
+++ b/app/src/main/java/com/bixlabs/smssolidario/activity/MainActivity.java
@@ -2,14 +2,14 @@
import android.Manifest;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
-import android.content.Intent;
-import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
@@ -24,6 +24,9 @@
import android.widget.ViewFlipper;
import com.awesomego.widget.ToggleButton;
+import com.bixlabs.smssolidario.BuildConfig;
+import com.bixlabs.smssolidario.R;
+import com.bixlabs.smssolidario.SmsAnalyticsApplication;
import com.crashlytics.android.Crashlytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
@@ -35,9 +38,6 @@
import org.joda.time.DateTime;
import io.fabric.sdk.android.Fabric;
-import com.bixlabs.smssolidario.BuildConfig;
-import com.bixlabs.smssolidario.R;
-import com.bixlabs.smssolidario.SmsAnalyticsApplication;
import static com.bixlabs.smssolidario.classes.Constants.COMPANY_NAME;
import static com.bixlabs.smssolidario.classes.Constants.DEFAULT_ACTIVE;
@@ -123,14 +123,18 @@ public boolean onOptionsItemSelected(MenuItem item) {
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
- //noinspection SimplifiableIfStatement
- if (id == R.id.action_settings) {
- checkPermissions();
- }
-
- if (id == R.id.action_about) {
- showAbout();
- }
+ switch (id) {
+ case R.id.action_settings:
+ checkPermissions();
+ break;
+ case R.id.action_about:
+ showAbout();
+ break;
+ case R.id.action_history:
+ Intent historyIntent = new Intent(this, HistoryActivity.class);
+ startActivity(historyIntent);
+ break;
+ }
return super.onOptionsItemSelected(item);
}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/activity/SettingsActivity.java b/app/src/main/java/com/bixlabs/smssolidario/activity/SettingsActivity.java
index ff7ae78..64be861 100644
--- a/app/src/main/java/com/bixlabs/smssolidario/activity/SettingsActivity.java
+++ b/app/src/main/java/com/bixlabs/smssolidario/activity/SettingsActivity.java
@@ -6,8 +6,10 @@
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.os.Build;
+import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
@@ -16,7 +18,6 @@
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.annotation.LayoutRes;
-import android.os.Bundle;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.MenuInflater;
@@ -27,8 +28,19 @@
import android.widget.TimePicker;
import android.widget.Toast;
+import com.bixlabs.smssolidario.R;
+import com.bixlabs.smssolidario.classes.Scheduler;
+
+import net.danlew.android.joda.JodaTimeAndroid;
+
+import org.joda.time.DateTime;
+
+import java.util.ArrayList;
+import java.util.List;
+
import static com.bixlabs.smssolidario.classes.Constants.DEFAULT_HOUR;
import static com.bixlabs.smssolidario.classes.Constants.DEFAULT_MINUTES;
+import static com.bixlabs.smssolidario.classes.Constants.ORGANIZATION_INFO;
import static com.bixlabs.smssolidario.classes.Constants.PREF_ACTIVE;
import static com.bixlabs.smssolidario.classes.Constants.PREF_CONFIGURED;
import static com.bixlabs.smssolidario.classes.Constants.PREF_DAY;
@@ -37,16 +49,6 @@
import static com.bixlabs.smssolidario.classes.Constants.PREF_MINUTE;
import static com.bixlabs.smssolidario.classes.Constants.PREF_MONTH;
import static com.bixlabs.smssolidario.classes.Constants.PREF_YEAR;
-import static com.bixlabs.smssolidario.classes.Constants.ORGANIZATION_INFO;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-
-
-import net.danlew.android.joda.JodaTimeAndroid;
-
-import org.joda.time.DateTime;
-
-import com.bixlabs.smssolidario.R;
-import com.bixlabs.smssolidario.classes.Scheduler;
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener,
android.support.v7.widget.Toolbar.OnMenuItemClickListener{
@@ -113,6 +115,19 @@ public boolean onPreferenceClick(Preference preference) {
phonePreference = findPreference(NUMBER_KEY);
hideMessageAndPhonePreferences();
+ // Load the organizations and add them to the preferences
+ ListPreference organizations = (ListPreference) findPreference(ORGANIZATION_KEY);
+ String[] orgs = getResources().getStringArray(R.array.organizations);
+ List entries = new ArrayList<>();
+ List values = new ArrayList<>();
+ for (String org : orgs) {
+ String[] splittedOrg = org.split("\\|", 2);
+ values.add(splittedOrg[0]);
+ entries.add(splittedOrg[1]);
+ }
+ organizations.setEntries(entries.toArray(new String[entries.size()]));
+ organizations.setEntryValues(values.toArray(new String[values.size()]));
+
JodaTimeAndroid.init(this);
getPreferencesFromUser();
@@ -364,10 +379,13 @@ protected Dialog onCreateDialog(int id) {
if (id == DATE_DIALOG_ID) {
DatePickerDialog datePickerDialog = new DatePickerDialog(this, dPickerListener, expirationYear, expirationMonth, expirationDay);
datePickerDialog.getDatePicker().setMinDate(DateTime.now().getMillis() - 1000);
+ datePickerDialog.setTitle(R.string.dialog_datepicker_title);
return datePickerDialog;
}
else if (id == TIME_DIALOG_ID) {
- return new TimePickerDialog(this, timePickerListener, expirationHour, expirationMinute, true);
+ TimePickerDialog timePickerDialog = new TimePickerDialog(this, timePickerListener, expirationHour, expirationMinute, true);
+ timePickerDialog.setTitle(R.string.dialog_timepicker_title);
+ return timePickerDialog;
}
return null;
}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/adapters/HistoryCursorAdapter.java b/app/src/main/java/com/bixlabs/smssolidario/adapters/HistoryCursorAdapter.java
new file mode 100644
index 0000000..c88ea97
--- /dev/null
+++ b/app/src/main/java/com/bixlabs/smssolidario/adapters/HistoryCursorAdapter.java
@@ -0,0 +1,62 @@
+package com.bixlabs.smssolidario.adapters;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.bixlabs.smssolidario.R;
+import com.bixlabs.smssolidario.persistency.DatabaseHelper;
+
+/**
+ * History ListView Adapter
+ */
+public class HistoryCursorAdapter extends CursorAdapter {
+ private int COL_ORGANIZATION = 0;
+ private int COL_DATE = 0;
+
+ public HistoryCursorAdapter(Context context, Cursor c) {
+ super(context, c, 0);
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ View view = LayoutInflater.from(context).inflate(R.layout.item_history, parent, false);
+ ViewHolder holder = new ViewHolder(view);
+ view.setTag(holder);
+ return view;
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor c) {
+ if (c != null) {
+ COL_ORGANIZATION = c.getColumnIndex(DatabaseHelper.COLUMN_HISTORY_ORG);
+ COL_DATE = c.getColumnIndex(DatabaseHelper.COLUMN_HISTORY_DATE);
+ }
+ return super.swapCursor(c);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ ViewHolder holder = (ViewHolder) view.getTag();
+
+ String organizationName = cursor.getString(COL_ORGANIZATION);
+ String timestamp = cursor.getString(COL_DATE);
+
+ holder.organization.setText(organizationName);
+ holder.date.setText(timestamp);
+ }
+
+ private static class ViewHolder {
+ final TextView organization;
+ final TextView date;
+
+ ViewHolder(View view) {
+ organization = (TextView) view.findViewById(R.id.item_history_organization);
+ date = (TextView) view.findViewById(R.id.item_history_date);
+ }
+ }
+}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/classes/AlertReceiver.java b/app/src/main/java/com/bixlabs/smssolidario/classes/AlertReceiver.java
index 4115f24..380f5d2 100644
--- a/app/src/main/java/com/bixlabs/smssolidario/classes/AlertReceiver.java
+++ b/app/src/main/java/com/bixlabs/smssolidario/classes/AlertReceiver.java
@@ -8,17 +8,17 @@
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.TaskStackBuilder;
import android.telephony.SmsManager;
import android.widget.Toast;
-import net.danlew.android.joda.JodaTimeAndroid;
-
-import org.joda.time.DateTime;
-
import com.bixlabs.smssolidario.R;
import com.bixlabs.smssolidario.controllers.AlarmController;
import com.bixlabs.smssolidario.controllers.MessageController;
+import com.bixlabs.smssolidario.persistency.HistoryDataSource;
+
+import net.danlew.android.joda.JodaTimeAndroid;
+
+import org.joda.time.DateTime;
import static com.bixlabs.smssolidario.classes.Constants.DEFAULT_ACTIVE;
import static com.bixlabs.smssolidario.classes.Constants.DEFAULT_ALLOWED_PREMIUM;
@@ -48,6 +48,7 @@ public class AlertReceiver extends BroadcastReceiver {
String phoneNumber, textMessage;
SharedPreferences.Editor editor;
MessageController msgController;
+ HistoryDataSource historyDataSource;
@Override
public void onReceive(Context context, Intent intent) {
@@ -65,6 +66,8 @@ public void onReceive(Context context, Intent intent) {
// This is the case when the message is sent
case Activity.RESULT_OK:
settings = PreferenceManager.getDefaultSharedPreferences(context);
+ phoneNumber = settings.getString(PREF_PHONE, DEFAULT_PHONE);
+
boolean allowedPremium = settings.getBoolean(PREF_ALLOWED_PREMIUM, DEFAULT_ALLOWED_PREMIUM);
// If the messages were sent successfully then we don't
// Need to show again the validation dialog
@@ -84,6 +87,12 @@ public void onReceive(Context context, Intent intent) {
editor.putInt(PREF_SMS_TO_SEND, messagesToSend);
editor.putBoolean(PREF_ERROR, false);
editor.apply();
+
+ // Add the newly sent message to the History DB
+ historyDataSource = new HistoryDataSource(context);
+ historyDataSource.addToHistory(Utils.getOrganizationNameFromNumber(phoneNumber,
+ context.getResources().getStringArray(R.array.organizations)));
+
// If the day changes we stop sending messages to prevent spending wrong credit
DateTime actualTime = DateTime.now();
DateTime actualExpirationDate = DateTime.now();
@@ -91,7 +100,6 @@ public void onReceive(Context context, Intent intent) {
boolean stopForChangeOfDay = actualTime.getDayOfMonth() != expirationDay;
boolean stopForMax = messagesToSend == 0;
if (!stopForMax && !stopForChangeOfDay) {
- phoneNumber = settings.getString(PREF_PHONE, DEFAULT_PHONE);
textMessage = settings.getString(PREF_MESSAGE, DEFAULT_MESSAGE);
msgController = MessageController.getInstance();
msgController.sendMessage(phoneNumber, textMessage, context);
diff --git a/app/src/main/java/com/bixlabs/smssolidario/classes/SimpleCursorLoader.java b/app/src/main/java/com/bixlabs/smssolidario/classes/SimpleCursorLoader.java
new file mode 100644
index 0000000..3068fa6
--- /dev/null
+++ b/app/src/main/java/com/bixlabs/smssolidario/classes/SimpleCursorLoader.java
@@ -0,0 +1,126 @@
+package com.bixlabs.smssolidario.classes;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.content.AsyncTaskLoader;
+import android.util.Log;
+
+/**
+ * CursorLoader that doesn't require of a ContentProvider.
+ * This was based on the CursorLoader class.
+ */
+public abstract class SimpleCursorLoader extends AsyncTaskLoader {
+ private Cursor mCursor;
+
+ public SimpleCursorLoader(Context context) {
+ // Loaders may be used across multiple Activities (assuming they aren't
+ // bound to the LoaderManager), so NEVER hold a reference to the context
+ // directly. Doing so will cause you to leak an entire Activity's context.
+ // The superclass constructor will store a reference to the Application
+ // Context instead, and can be retrieved with a call to getContext().
+ super(context);
+ }
+
+ /* Runs on a worker thread */
+ @Override
+ public abstract Cursor loadInBackground();
+
+ /* Runs on the UI thread */
+ /**
+ * Called when there is new data to deliver to the client. The superclass will
+ * deliver it to the registered listener (i.e. the LoaderManager), which will
+ * forward the results to the client through a call to onLoadFinished.
+ */
+ @Override
+ public void deliverResult(Cursor cursor) {
+ if (isReset()) {
+ // The loader has been reset; ignore the result and invalidate the data.
+ // This can happen when the Loader is reset while an asynchronous query
+ // is working in the background. That is, when the background thread
+ // finishes its work and attempts to deliver the results to the client,
+ // it will see here that the Loader has been reset and discard any
+ // resources associated with the new data as necessary
+ releaseResource(cursor);
+ return;
+ }
+
+ // Hold a reference to the old data so it doesn't get garbage collected.
+ // We must protect it until the new data has been delivered.
+ Cursor oldCursor = mCursor;
+ mCursor = cursor;
+
+ if (isStarted()) {
+ // If the loader is in a started state, have the superclass deliver the
+ // result to the client.
+ super.deliverResult(cursor);
+ }
+
+ // Invalidate the old data as we don't need it anymore
+ if (oldCursor != null && oldCursor != cursor) {
+ releaseResource(oldCursor);
+ }
+ }
+
+ /**
+ * Starts an asynchronous load of the data. When the result is ready the callbacks
+ * will be called on the UI thread. If a previous load has been completed and is still valid
+ * the result may be passed to the callbacks immediately.
+ *
+ * Must be called from the UI thread
+ */
+ @Override
+ protected void onStartLoading() {
+ if (mCursor != null) {
+ deliverResult(mCursor);
+ }
+
+ // If the method onContentchanged() of the Loader is called, it will cause
+ // the next call to takeContentChanged() to return true. If this is ever
+ // the case (or if the current data is null), we force a new load.
+ if (takeContentChanged() || mCursor == null) {
+ forceLoad();
+ }
+ }
+
+ /**
+ * Must be called from the UI thread
+ */
+ @Override
+ protected void onStopLoading() {
+ // The Loader has been put in a stopped state, so we should attempt to
+ // cancel the current load (if there is one).
+ cancelLoad();
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+
+ // Ensure the loader is stopped
+ onStopLoading();
+
+ // At this point we can release the resources
+ releaseResource(mCursor);
+ mCursor = null;
+ }
+
+ @Override
+ public void onCanceled(Cursor cursor) {
+ // Attempt to cancel the current asynchronous load.
+ super.onCanceled(cursor);
+
+ // The load has been canceled, so we should release the resources
+ releaseResource(cursor);
+ }
+
+
+ /**
+ * Helper method to take care of releasing resources.
+ */
+ private void releaseResource(Cursor cursor) {
+ if (cursor != null && cursor.isClosed()) {
+ cursor.close();
+ Log.d(SimpleCursorLoader.class.getSimpleName(), "Cursor has been closed");
+ }
+ }
+}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/classes/Utils.java b/app/src/main/java/com/bixlabs/smssolidario/classes/Utils.java
new file mode 100644
index 0000000..b1f9259
--- /dev/null
+++ b/app/src/main/java/com/bixlabs/smssolidario/classes/Utils.java
@@ -0,0 +1,50 @@
+package com.bixlabs.smssolidario.classes;
+
+import java.sql.Date;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Utility methods
+ */
+public class Utils {
+
+ /**
+ * Get an organization name based on its phone number
+ * @param phoneNumber The phone number
+ * @param organizations The organizations list
+ * @return The organization name as String
+ */
+ public static String getOrganizationNameFromNumber(String phoneNumber, String[] organizations) {
+ String organizationName = null;
+
+ for (Map.Entry organization : Constants.ORGANIZATION_INFO.entrySet() ) {
+ if (phoneNumber.equals(organization.getValue()[1])) {
+ for(String orgs : organizations) {
+ String[] splittedOrg = orgs.split("\\|", 2);
+ if (splittedOrg[0].equals(organization.getKey())) {
+ organizationName = splittedOrg[1];
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return organizationName;
+ }
+
+ /**
+ * Private helper method to convert timestamps to formatted dates
+ * @param dateInMillis The timestamp
+ * @return The formatted date as String
+ */
+ public static String formatDate(Long dateInMillis) {
+ DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault());
+ Date netDate = (new Date(dateInMillis));
+ return sdf.format(netDate);
+ }
+
+}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/persistency/DatabaseHelper.java b/app/src/main/java/com/bixlabs/smssolidario/persistency/DatabaseHelper.java
new file mode 100644
index 0000000..63b5953
--- /dev/null
+++ b/app/src/main/java/com/bixlabs/smssolidario/persistency/DatabaseHelper.java
@@ -0,0 +1,63 @@
+package com.bixlabs.smssolidario.persistency;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+
+/**
+ * Database Helper class
+ */
+public class DatabaseHelper extends SQLiteOpenHelper {
+
+ private static final String DATABASE_NAME = "sms_solidario.db";
+ private static final int DATABASE_VERSION = 1;
+
+ // Tables
+ public static final String TABLE_HISTORY = "history";
+
+ // Columns
+ public static final String COLUMN_HISTORY_ID = "_id";
+ public static final String COLUMN_HISTORY_ORG = "organization";
+ public static final String COLUMN_HISTORY_DATE = "date";
+
+ /*
+ Table History:
+ ------------------------------------------
+ | _id | organization | date
+ ------------------------------------------
+ | 1 | Animales sin hogar | El 12/08/2016 a las 20:30 hrs.
+ | 2 | Aldeas Infantiles | El 12/09/2016 a las 20:30 hrs.
+ ------------------------------------------
+ */
+ private static final String TABLE_HISTORY_CREATE =
+ TABLE_HISTORY + "( " +
+ COLUMN_HISTORY_ID + " integer primary key autoincrement, " +
+ COLUMN_HISTORY_ORG + " text not null, " +
+ COLUMN_HISTORY_DATE + " text not null" +
+ ");";
+
+ private static final String DATABASE_CREATE = "create table " + TABLE_HISTORY_CREATE;
+
+ public DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(DATABASE_CREATE);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.w(DatabaseHelper.class.getName(), "Upgrading database from version " + oldVersion + " to "
+ + newVersion + ", which will destroy all old data");
+
+ // Drop table if exists and re-create it
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY);
+
+ onCreate(db);
+ }
+
+}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/persistency/HistoryDataSource.java b/app/src/main/java/com/bixlabs/smssolidario/persistency/HistoryDataSource.java
new file mode 100644
index 0000000..9a078e5
--- /dev/null
+++ b/app/src/main/java/com/bixlabs/smssolidario/persistency/HistoryDataSource.java
@@ -0,0 +1,32 @@
+package com.bixlabs.smssolidario.persistency;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.bixlabs.smssolidario.classes.Utils;
+
+/**
+ * Donations History DAO
+ */
+public class HistoryDataSource {
+ private DatabaseHelper databaseHelper;
+
+ public HistoryDataSource(Context ctx) {
+ databaseHelper = new DatabaseHelper(ctx);
+ }
+
+ /**
+ * Adds a new entry to the History table
+ * @param organizationName The name of the organization which we donated
+ */
+ public void addToHistory(String organizationName) {
+ SQLiteDatabase database = databaseHelper.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(DatabaseHelper.COLUMN_HISTORY_ORG, organizationName);
+ values.put(DatabaseHelper.COLUMN_HISTORY_DATE, Utils.formatDate(System.currentTimeMillis()));
+ database.insert(DatabaseHelper.TABLE_HISTORY, null, values);
+ database.close();
+ }
+
+}
diff --git a/app/src/main/java/com/bixlabs/smssolidario/persistency/HistoryLoader.java b/app/src/main/java/com/bixlabs/smssolidario/persistency/HistoryLoader.java
new file mode 100644
index 0000000..31b3d1c
--- /dev/null
+++ b/app/src/main/java/com/bixlabs/smssolidario/persistency/HistoryLoader.java
@@ -0,0 +1,31 @@
+package com.bixlabs.smssolidario.persistency;
+
+import android.content.Context;
+import android.database.Cursor;
+
+import com.bixlabs.smssolidario.classes.SimpleCursorLoader;
+
+public final class HistoryLoader extends SimpleCursorLoader {
+ private DatabaseHelper mDatabaseHelper;
+ private String[] allColumns = { DatabaseHelper.COLUMN_HISTORY_ID,
+ DatabaseHelper.COLUMN_HISTORY_ORG, DatabaseHelper.COLUMN_HISTORY_DATE};
+
+ public HistoryLoader(Context context, DatabaseHelper helper) {
+ super(context);
+ this.mDatabaseHelper = helper;
+ }
+
+ @Override
+ public Cursor loadInBackground() {
+ return mDatabaseHelper.getReadableDatabase()
+ .query(DatabaseHelper.TABLE_HISTORY, allColumns, null, null, null, null, null);
+ }
+
+ @Override
+ public void deliverResult(Cursor cursor) {
+ super.deliverResult(cursor);
+
+ // Close the underlying DB connection and release it.
+ mDatabaseHelper.close();
+ }
+}
diff --git a/app/src/main/res/layout/activity_history.xml b/app/src/main/res/layout/activity_history.xml
new file mode 100644
index 0000000..5df1356
--- /dev/null
+++ b/app/src/main/res/layout/activity_history.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 1cd8daa..12c57e6 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -8,7 +8,7 @@
android:background="@color/white"
android:orientation="vertical"
android:weightSum="1"
- tools:context=".MainActivity" >
+ tools:context=".activity.MainActivity" >
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 021df23..034c3bb 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- tools:context=".SettingsActivity" >
+ tools:context=".activity.SettingsActivity" >
diff --git a/app/src/main/res/layout/activity_splash_screen.xml b/app/src/main/res/layout/activity_splash_screen.xml
index dafb2ed..289a7e0 100644
--- a/app/src/main/res/layout/activity_splash_screen.xml
+++ b/app/src/main/res/layout/activity_splash_screen.xml
@@ -3,7 +3,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff6464"
- tools:context=".SplashScreenActivity" >
+ tools:context=".activity.SplashScreenActivity" >
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/activity_main.xml b/app/src/main/res/menu/activity_main.xml
index 8e256fc..f808952 100644
--- a/app/src/main/res/menu/activity_main.xml
+++ b/app/src/main/res/menu/activity_main.xml
@@ -7,9 +7,16 @@
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never"/>
+
+
+
diff --git a/app/src/main/res/values/organizations.xml b/app/src/main/res/values/organizations.xml
index b347d40..4b863fd 100644
--- a/app/src/main/res/values/organizations.xml
+++ b/app/src/main/res/values/organizations.xml
@@ -1,22 +1,12 @@
- - Animales sin hogar
- - Fundacion Alvarez Caldeiro Barcia
- - Unicef
- - Orquestas Juveniles
- - Peluffo Giguens
- - Aldeas Infantiles
- - Personalizada
+ - ASH|Animales sin hogar
+ - FACB|Funcacion Alvarez Caldeiro Barcia
+ - UNCF|Unicef
+ - OJ|Orquestas Juveniles
+ - PG|Peluffo Giguens
+ - AI|Aldeas Infantiles
+ - Personalizada|Personalizada
-
- - ASH
- - FACB
- - UNCF
- - OJ
- - PG
- - AI
- - Personalizada
-
-
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d4903d0..96c9a34 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -49,4 +49,20 @@
Ser donante validado :)
¡Gracias por ser parte!
Próximo envío automático:
+ Historial de donaciones
+ Selecciona una fecha
+ Selecciona una hora
+ Aún no has colaborado.\n¿Qué esperas para hacerlo?
+ Organización que recibirá la donación
+ Nuevo número
+ Mensaje
+ Ingrese texto
+ Cantidad máxima de SMS
+ Seleccionar fecha
+ Hora de envío
+ Notificar al enviar
+ Selecciona una ONG
+ Ingresa un número de teléfono
+ Cargando
+ Un momento por favor...
diff --git a/app/src/main/res/xml/preference_settings.xml b/app/src/main/res/xml/preference_settings.xml
index b9c4d2a..6c3d444 100644
--- a/app/src/main/res/xml/preference_settings.xml
+++ b/app/src/main/res/xml/preference_settings.xml
@@ -8,42 +8,40 @@
+ android:summary="@string/preferences_organization"
+ android:title="@string/preferences_organization_title" />
+ android:title="@string/preferences_new_number_title" />
+ android:title="@string/preferences_message" />
+ android:title="@string/preferences_date" />
+ android:title="@string/preferences_time" />
+ android:title="@string/preferences_notify" />