diff --git a/.classpath b/.classpath
index 5176974..28e3f84 100644
--- a/.classpath
+++ b/.classpath
@@ -5,5 +5,7 @@
+
+
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e361d00..dd1b200 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -5,15 +5,16 @@
android:versionName="1.0" >
-
+
+
+
+
+
-
-
-
-
-
@@ -38,13 +39,25 @@
android:label="@string/title_activity_sign_up"
android:parentActivityName="com.codepath.beacon.ui.LoginActivity" >
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/libs/Parse-1.5.1.jar.properties b/libs/Parse-1.5.1.jar.properties
new file mode 100644
index 0000000..c55a8b8
--- /dev/null
+++ b/libs/Parse-1.5.1.jar.properties
@@ -0,0 +1 @@
+doc=Parse-1.5.1-javadoc
diff --git a/res/drawable-hdpi/ic_add.png b/res/drawable-hdpi/ic_add.png
new file mode 100644
index 0000000..71838eb
Binary files /dev/null and b/res/drawable-hdpi/ic_add.png differ
diff --git a/res/drawable-hdpi/ic_beacon_btn.png b/res/drawable-hdpi/ic_beacon_btn.png
new file mode 100644
index 0000000..6e4cf60
Binary files /dev/null and b/res/drawable-hdpi/ic_beacon_btn.png differ
diff --git a/res/drawable-hdpi/ic_empty.png b/res/drawable-hdpi/ic_empty.png
new file mode 100644
index 0000000..bb87a4e
Binary files /dev/null and b/res/drawable-hdpi/ic_empty.png differ
diff --git a/res/drawable-hdpi/ic_notification.png b/res/drawable-hdpi/ic_notification.png
new file mode 100644
index 0000000..277a918
Binary files /dev/null and b/res/drawable-hdpi/ic_notification.png differ
diff --git a/res/drawable-mdpi/ic_add.png b/res/drawable-mdpi/ic_add.png
new file mode 100644
index 0000000..b9f5b7b
Binary files /dev/null and b/res/drawable-mdpi/ic_add.png differ
diff --git a/res/drawable-mdpi/ic_beacon_btn.png b/res/drawable-mdpi/ic_beacon_btn.png
new file mode 100644
index 0000000..f88ed98
Binary files /dev/null and b/res/drawable-mdpi/ic_beacon_btn.png differ
diff --git a/res/drawable-mdpi/ic_empty.png b/res/drawable-mdpi/ic_empty.png
new file mode 100644
index 0000000..877a609
Binary files /dev/null and b/res/drawable-mdpi/ic_empty.png differ
diff --git a/res/drawable-mdpi/ic_notification.png b/res/drawable-mdpi/ic_notification.png
new file mode 100644
index 0000000..404200d
Binary files /dev/null and b/res/drawable-mdpi/ic_notification.png differ
diff --git a/res/drawable-xhdpi/ic_add.png b/res/drawable-xhdpi/ic_add.png
new file mode 100644
index 0000000..2f056a1
Binary files /dev/null and b/res/drawable-xhdpi/ic_add.png differ
diff --git a/res/drawable-xhdpi/ic_beacon_btn.png b/res/drawable-xhdpi/ic_beacon_btn.png
new file mode 100644
index 0000000..08bb0da
Binary files /dev/null and b/res/drawable-xhdpi/ic_beacon_btn.png differ
diff --git a/res/drawable-xhdpi/ic_empty.png b/res/drawable-xhdpi/ic_empty.png
new file mode 100644
index 0000000..1dd395a
Binary files /dev/null and b/res/drawable-xhdpi/ic_empty.png differ
diff --git a/res/drawable-xhdpi/ic_notification.png b/res/drawable-xhdpi/ic_notification.png
new file mode 100644
index 0000000..6deff83
Binary files /dev/null and b/res/drawable-xhdpi/ic_notification.png differ
diff --git a/res/drawable-xxhdpi/ic_add.png b/res/drawable-xxhdpi/ic_add.png
new file mode 100644
index 0000000..201b949
Binary files /dev/null and b/res/drawable-xxhdpi/ic_add.png differ
diff --git a/res/drawable-xxhdpi/ic_beacon_btn.png b/res/drawable-xxhdpi/ic_beacon_btn.png
new file mode 100644
index 0000000..fb8ca8c
Binary files /dev/null and b/res/drawable-xxhdpi/ic_beacon_btn.png differ
diff --git a/res/drawable-xxhdpi/ic_empty.png b/res/drawable-xxhdpi/ic_empty.png
new file mode 100644
index 0000000..14218d7
Binary files /dev/null and b/res/drawable-xxhdpi/ic_empty.png differ
diff --git a/res/drawable-xxhdpi/ic_notification.png b/res/drawable-xxhdpi/ic_notification.png
new file mode 100644
index 0000000..b8cad50
Binary files /dev/null and b/res/drawable-xxhdpi/ic_notification.png differ
diff --git a/res/layout/activity_my_recipe.xml b/res/layout/activity_my_recipe.xml
new file mode 100644
index 0000000..6e619d0
--- /dev/null
+++ b/res/layout/activity_my_recipe.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/res/layout/activity_recipe_detail.xml b/res/layout/activity_recipe_detail.xml
new file mode 100644
index 0000000..7616328
--- /dev/null
+++ b/res/layout/activity_recipe_detail.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/fragment_empty_list.xml b/res/layout/fragment_empty_list.xml
new file mode 100644
index 0000000..9f951fb
--- /dev/null
+++ b/res/layout/fragment_empty_list.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/res/layout/fragment_recipe_list.xml b/res/layout/fragment_recipe_list.xml
new file mode 100644
index 0000000..c9b9f83
--- /dev/null
+++ b/res/layout/fragment_recipe_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/recipe_item.xml b/res/layout/recipe_item.xml
new file mode 100644
index 0000000..64928f5
--- /dev/null
+++ b/res/layout/recipe_item.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/menu/my_recipe.xml b/res/menu/my_recipe.xml
new file mode 100644
index 0000000..11ef350
--- /dev/null
+++ b/res/menu/my_recipe.xml
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 40dff42..73e4a72 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -15,10 +15,23 @@
New User?
"Sign up here"
SignUpActivity
-
Refresh
Looking for devices. Please wait..
No devices found
-
+ BeaconFriendlyName
+ Approaching
+ send notification
+ On
+ RecipeDetailActivity
+ IF
+ Then
+ "Activated on:"
+ Date
+ Triggered:
+ Count
+ Distance:
+ Beacon Distance
+ Receive Notification with this beacon
+ Beacon Name and UUID
diff --git a/src/com/codepath/beacon/BeaconApplication.java b/src/com/codepath/beacon/BeaconApplication.java
index d932b43..be951e6 100644
--- a/src/com/codepath/beacon/BeaconApplication.java
+++ b/src/com/codepath/beacon/BeaconApplication.java
@@ -1,14 +1,12 @@
package com.codepath.beacon;
-import com.parse.Parse;
-import com.parse.ParseException;
-import com.parse.ParseObject;
-import com.parse.ParseUser;
-import com.parse.SaveCallback;
-
import android.app.Application;
import android.util.Log;
+import com.codepath.beacon.models.Recipe;
+import com.parse.Parse;
+import com.parse.ParseObject;
+
public class BeaconApplication extends Application {
private static final String LOG_TAG = BeaconApplication.class.getSimpleName();
private static final String APP_ID = "KopNnh31P28DZMDp9njtWRDpgUkn2qwrMBNZ53VJ";
@@ -19,6 +17,7 @@ public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d(LOG_TAG, "onCreate(). Initializing Parse");
+ ParseObject.registerSubclass(Recipe.class);
Parse.initialize(this, APP_ID, CLIENT_KEY);
}
}
diff --git a/src/com/codepath/beacon/activity/MyRecipeActivity.java b/src/com/codepath/beacon/activity/MyRecipeActivity.java
new file mode 100644
index 0000000..89500b9
--- /dev/null
+++ b/src/com/codepath/beacon/activity/MyRecipeActivity.java
@@ -0,0 +1,42 @@
+package com.codepath.beacon.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Window;
+
+import com.codepath.beacon.R;
+import com.codepath.beacon.fragments.RecipeListFragment;
+import com.codepath.beacon.scan.BleActivity;
+
+public class MyRecipeActivity extends FragmentActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.activity_my_recipe);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ // TODO: hardcode the userID for now, will pass in additional parameters
+ RecipeListFragment newFragment = RecipeListFragment.newInstance("rcao");
+ transaction.replace(R.id.flrecipelist, newFragment);
+ transaction.commit();
+
+ }
+
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.my_recipe, menu);
+ return true;
+ }
+
+ public void onAddAction(MenuItem mi) {
+
+ Intent scanIntent = new Intent(this, BleActivity.class);
+ startActivity(scanIntent);
+ }
+}
diff --git a/src/com/codepath/beacon/activity/RecipeDetailActivity.java b/src/com/codepath/beacon/activity/RecipeDetailActivity.java
new file mode 100644
index 0000000..d102bfb
--- /dev/null
+++ b/src/com/codepath/beacon/activity/RecipeDetailActivity.java
@@ -0,0 +1,41 @@
+package com.codepath.beacon.activity;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+import com.codepath.beacon.R;
+import com.codepath.beacon.models.Recipe;
+
+public class RecipeDetailActivity extends Activity {
+ private Recipe recipe;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_recipe_detail);
+ populateRecipeDetail(recipe);
+ }
+
+ private void populateRecipeDetail(Recipe recipe) {
+ // populate recipe detail page with recipe data
+ String fn = getIntent().getStringExtra("fn");
+ String UUID = getIntent().getStringExtra("UUID");
+ String activationDate = getIntent().getStringExtra("activationDate");;
+ String triggerCount = getIntent().getStringExtra("triggerCount");
+ boolean status = getIntent().getBooleanExtra("status", false);
+
+ TextView tvActivationDate = (TextView) findViewById(R.id.tvActivationDate);
+ tvActivationDate.setText(activationDate);
+ TextView tvTriggeredCount = (TextView) findViewById(R.id.tvTriggeredCount);
+ tvTriggeredCount.setText(triggerCount);
+ ToggleButton tbStatus = (ToggleButton) findViewById(R.id.tbStatus);
+ tbStatus.setChecked(status);
+ TextView tvBeaconnameandUUID = (TextView) findViewById(R.id.tvBeaconnameandUUID);
+ tvBeaconnameandUUID.setText(fn+"---"+UUID);
+
+ //TODO: Need to call 3rd party lib to get distance or other beacon related information
+ TextView tvBeaconDistance = (TextView) findViewById(R.id.tvBeaconDistance);
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/codepath/beacon/adapter/RecipeArrayAdapter.java b/src/com/codepath/beacon/adapter/RecipeArrayAdapter.java
new file mode 100644
index 0000000..876c0cc
--- /dev/null
+++ b/src/com/codepath/beacon/adapter/RecipeArrayAdapter.java
@@ -0,0 +1,85 @@
+package com.codepath.beacon.adapter;
+
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+import com.codepath.beacon.R;
+import com.codepath.beacon.activity.RecipeDetailActivity;
+import com.codepath.beacon.models.Recipe;
+
+public class RecipeArrayAdapter extends ArrayAdapter {
+ private final int REQUEST_CODE = 20;
+ public RecipeArrayAdapter(Context context, List recipes) {
+ super(context, R.layout.recipe_item, recipes);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ Recipe recipe = (Recipe) getItem(position);
+ View v;
+
+ if (convertView == null) {
+ LayoutInflater inflator = LayoutInflater.from(getContext());
+ v = inflator.inflate(R.layout.recipe_item, parent, false);
+ } else {
+ v = convertView;
+ }
+
+ // find the views within template
+ TextView tvBeaconName = (TextView) v.findViewById(R.id.tvbeaconname);
+ TextView tvTrigger = (TextView) v.findViewById(R.id.tvtrigger);
+ TextView tvNotification = (TextView) v.findViewById(R.id.tvnotification);
+ ToggleButton tbTrigger = (ToggleButton) v.findViewById(R.id.tbtrigger);
+
+ //TODO add image to the list later
+ /* ImageView ivBeaconImage = (ImageView) v.findViewById(R.id.ivbeaconimage);
+ ivBeaconImage.setImageResource(android.R.color.transparent);
+ ImageLoader imageLoader = ImageLoader.getInstance();
+
+ // populate views with recipe data
+ imageLoader.displayImage("http://www.pendragon-it.com/wp-content/uploads/2014/06/ibeacon-660x375.png", ivBeaconImage);
+ */
+
+ tvBeaconName.setText(recipe.getFriendlyName());
+ tvTrigger.setText(recipe.getTrigger());
+ tvNotification.setText(recipe.getNotification());
+ tbTrigger.setChecked(recipe.isStatus());
+
+ // pass recipe to activity view
+ v.setTag(recipe);
+
+ v.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ Recipe recipe = (Recipe) v.getTag();
+ String fn = recipe.getFriendlyName();
+ String UUID = recipe.getUUID();
+ SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
+ String activationDate = df.format(recipe.getActivationDate());
+ String triggerCount = Integer.toString(recipe.getTriggeredCount());
+ boolean status = recipe.isStatus();
+
+ Intent i = new Intent(getContext(), RecipeDetailActivity.class);
+ i.putExtra("fn", fn);
+ i.putExtra("UUID", UUID);
+ i.putExtra("activationDate", activationDate);
+ i.putExtra("triggerCount", triggerCount);
+ i.putExtra("status", status);
+ getContext().startActivity(i);
+ }
+ });
+
+ return v;
+
+ }
+
+}
diff --git a/src/com/codepath/beacon/fragments/RecipeListFragment.java b/src/com/codepath/beacon/fragments/RecipeListFragment.java
new file mode 100644
index 0000000..06a2d7e
--- /dev/null
+++ b/src/com/codepath/beacon/fragments/RecipeListFragment.java
@@ -0,0 +1,127 @@
+package com.codepath.beacon.fragments;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.codepath.beacon.R;
+import com.codepath.beacon.adapter.RecipeArrayAdapter;
+import com.codepath.beacon.models.Recipe;
+import com.codepath.beacon.util.EndlessScrollListener;
+import com.parse.FindCallback;
+import com.parse.ParseException;
+import com.parse.ParseObject;
+import com.parse.ParseQuery;
+import com.parse.ParseUser;
+
+public class RecipeListFragment extends Fragment {
+ protected ArrayList recipes;
+ protected ArrayAdapter aRecipes;
+ protected ListView lvRecipes;
+ protected int repCount =20;
+
+ public static RecipeListFragment newInstance(String userID) {
+ RecipeListFragment recipeListFragment = new RecipeListFragment();
+ Bundle args = new Bundle();
+ args.putString("user_id", userID);
+ recipeListFragment.setArguments(args);
+ return recipeListFragment;
+ }
+
+ protected void findMyRecipes(final String max_id, final boolean refresh) {
+
+ ParseQuery query = ParseQuery.getQuery(Recipe.class);
+ ParseUser currentUser = ParseUser.getCurrentUser();
+ query.addDescendingOrder("FN");
+ // query.whereEqualTo("owner", ParseUser.getCurrentUser());
+ if (!max_id.equals("0"))
+ query.whereGreaterThan("FN", max_id);
+
+ // Execute the find asynchronously
+ query.findInBackground(new FindCallback() {
+ public void done(List itemList, ParseException e) {
+ if (e == null) {
+ // Access the array of results here
+ recipes = new ArrayList(itemList);
+ aRecipes.addAll(recipes);
+ } else {
+ Log.d("item", "Error: " + e.getMessage());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ recipes = new ArrayList();
+ aRecipes = new RecipeArrayAdapter(getActivity(), recipes);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ // Defines the xml file for the fragment
+ View view = inflater.inflate(R.layout.fragment_recipe_list, container, false);
+ lvRecipes = (ListView) view.findViewById(R.id.lvRecipes);
+ lvRecipes.setAdapter(aRecipes);
+ findMyRecipes("0", false);
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ // Attach the listener to the AdapterView onCreate
+ lvRecipes.setOnScrollListener(new EndlessScrollListener() {
+ public void onLoadMore(int page, int totalItemsCount) {
+ // Triggered only when new data needs to be appended to the list
+ customLoadMoreDataFromApi(totalItemsCount);
+ }
+ });
+
+/* lvRecipes.setOnRefreshListener(new OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ findMyRecipes("0", true);
+ }
+ }); */
+ }
+
+ // Append more data into the adapter
+ public void customLoadMoreDataFromApi(int offset) {
+ String max_id;
+
+ int recipeLen = recipes.size();
+ if ((recipeLen > 0) && (recipeLen < offset-1)){
+ max_id = ((Recipe) recipes.get(recipeLen-1)).getFriendlyName();
+ findMyRecipes(max_id, false);
+ }
+ }
+
+ public void insertRecipetoTop(Recipe r) {
+ aRecipes.insert(r, 0);
+ lvRecipes.setSelection(0);
+ }
+
+ // should be called when an async task started
+ public void showProgressBar() {
+ getActivity().setProgressBarIndeterminateVisibility(true);
+ }
+
+ // Should be called when an async task has finished
+ public void hideProgressBar() {
+ getActivity().setProgressBarIndeterminateVisibility(false);
+ }
+
+}
diff --git a/src/com/codepath/beacon/models/Recipe.java b/src/com/codepath/beacon/models/Recipe.java
new file mode 100644
index 0000000..2b1348b
--- /dev/null
+++ b/src/com/codepath/beacon/models/Recipe.java
@@ -0,0 +1,112 @@
+package com.codepath.beacon.models;
+
+import java.util.Date;
+
+import com.parse.ParseClassName;
+import com.parse.ParseObject;
+import com.parse.ParseUser;
+
+@ParseClassName("Recipe")
+public class Recipe extends ParseObject {
+
+ private String notification;
+
+ public Recipe() {
+ super();
+ }
+
+ public Recipe(String fn, String UUID) {
+ super();
+ setFriendlyName(fn);
+ setUUID(UUID);
+ }
+
+ public String getFriendlyName() {
+ return getString("FN");
+ }
+ public void setFriendlyName(String friendlyName) {
+ put("FN", friendlyName);
+ }
+
+ public Date getActivationDate() {
+ return getDate("activationdate");
+ }
+
+ public void setActivationDate(Date activationDate) {
+ put("activationdate", activationDate);
+ }
+
+ public String getUUID() {
+ return getString("UUID");
+ }
+ public void setUUID(String UUID) {
+ put("UUID", UUID);
+ }
+
+ public boolean isPushNotification() {
+ return getBoolean("notification");
+ }
+
+ public void setPushNotification(boolean pushNotification) {
+ put("notification", pushNotification);
+ }
+
+ public boolean isSms() {
+ return getBoolean("sms");
+ }
+
+ public void setSms(boolean sms) {
+ put("sms", sms);
+ }
+
+ public String getContactNum() {
+ return getString("contactnumber");
+ }
+
+ public void setContactNum(String contactNum) {
+ put("contactnumber", contactNum);
+ }
+
+ public String getNotification() {
+ if (isPushNotification())
+ notification = "Notification";
+ if (isSms())
+ notification = "SMS";
+ return notification;
+ }
+
+ public boolean isStatus() {
+ return getBoolean("status");
+ }
+
+ public void setStatus(boolean status) {
+ put("status", status);
+ }
+
+ public String getTrigger() {
+ return getString("trigger");
+ }
+
+ public void setTrigger(String trigger) {
+ put("trigger", trigger);
+ }
+
+ public int getTriggeredCount() {
+ return getInt("triggercount");
+ }
+
+ public void setTriggeredCount(int triggeredCount) {
+ put("triggercount", triggeredCount);
+ }
+
+ public void setOwner(ParseUser user) {
+ put("owner", user);
+ }
+
+ // Get the user for this comment
+ public ParseUser getOwner() {
+ return getParseUser("owner");
+ }
+
+}
+
diff --git a/src/com/codepath/beacon/util/EndlessScrollListener.java b/src/com/codepath/beacon/util/EndlessScrollListener.java
new file mode 100644
index 0000000..52747b3
--- /dev/null
+++ b/src/com/codepath/beacon/util/EndlessScrollListener.java
@@ -0,0 +1,72 @@
+package com.codepath.beacon.util;
+
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+
+
+public abstract class EndlessScrollListener implements OnScrollListener {
+ // The minimum amount of items to have below your current scroll position
+ // before loading more.
+ private int visibleThreshold = 5;
+ // The current offset index of data you have loaded
+ private int currentPage = 0;
+ // The total number of items in the dataset after the last load
+ private int previousTotalItemCount = 0;
+ // True if we are still waiting for the last set of data to load.
+ private boolean loading = true;
+ // Sets the starting page index
+ private int startingPageIndex = 0;
+
+ public EndlessScrollListener() {
+ }
+
+ public EndlessScrollListener(int visibleThreshold) {
+ this.visibleThreshold = visibleThreshold;
+ }
+
+ public EndlessScrollListener(int visibleThreshold, int startPage) {
+ this.visibleThreshold = visibleThreshold;
+ this.startingPageIndex = startPage;
+ this.currentPage = startPage;
+ }
+
+ // This happens many times a second during a scroll, so be wary of the code you place here.
+ // We are given a few useful parameters to help us work out if we need to load some more data,
+ // but first we check if we are waiting for the previous load to finish.
+ @Override
+ public void onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount)
+ {
+ // If the total item count is zero and the previous isn't, assume the
+ // list is invalidated and should be reset back to initial state
+ if (totalItemCount < previousTotalItemCount) {
+ this.currentPage = this.startingPageIndex;
+ this.previousTotalItemCount = totalItemCount;
+ if (totalItemCount == 0) { this.loading = true; }
+ }
+
+ // If it’s still loading, we check to see if the dataset count has
+ // changed, if so we conclude it has finished loading and update the current page
+ // number and total item count.
+ if (loading && (totalItemCount > previousTotalItemCount)) {
+ loading = false;
+ previousTotalItemCount = totalItemCount;
+ currentPage++;
+ }
+
+ // If it isn’t currently loading, we check to see if we have breached
+ // the visibleThreshold and need to reload more data.
+ // If we do need to reload some more data, we execute onLoadMore to fetch the data.
+ if (!loading && (totalItemCount - visibleItemCount)<=(firstVisibleItem + visibleThreshold)) {
+ onLoadMore(currentPage + 1, totalItemCount);
+ loading = true;
+ }
+ }
+
+ // Defines the process for actually loading more data based on page
+ public abstract void onLoadMore(int page, int totalItemsCount);
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ // Don't take any action on changed
+ }
+}
diff --git a/src/com/codepath/beacon/util/ParseRelativeDate.java b/src/com/codepath/beacon/util/ParseRelativeDate.java
new file mode 100644
index 0000000..e72c7cf
--- /dev/null
+++ b/src/com/codepath/beacon/util/ParseRelativeDate.java
@@ -0,0 +1,28 @@
+package com.codepath.beacon.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import android.net.ParseException;
+import android.text.format.DateUtils;
+
+
+public class ParseRelativeDate {
+ //getRelativeTimeAgo("Mon Apr 01 21:16:23 +0000 2014");
+ public String getRelativeTimeAgo(String rawJsonDate) throws java.text.ParseException {
+ String twitterFormat = "EEE MMM dd HH:mm:ss ZZZZZ yyyy";
+ SimpleDateFormat sf = new SimpleDateFormat(twitterFormat, Locale.ENGLISH);
+ sf.setLenient(true);
+
+ String relativeDate = "";
+ try {
+ long dateMillis = sf.parse(rawJsonDate).getTime();
+ relativeDate = DateUtils.getRelativeTimeSpanString(dateMillis,
+ System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS).toString();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ return relativeDate;
+ }
+}