diff --git a/App/build.gradle b/App/build.gradle index af691d99..f43e1ae1 100755 --- a/App/build.gradle +++ b/App/build.gradle @@ -14,8 +14,8 @@ android { defaultConfig { minSdkVersion 15 targetSdkVersion 22 - versionCode 422 - versionName "4.2.2" + versionCode 423 + versionName "4.2.3" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/MainApplication.java b/App/src/main/java/cc/softwarefactory/lokki/android/MainApplication.java index 40e7b3c2..cde74cb7 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/MainApplication.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/MainApplication.java @@ -11,25 +11,18 @@ import android.support.v4.util.LruCache; import android.util.Log; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.android.gms.maps.GoogleMap; -import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; -import cc.softwarefactory.lokki.android.models.BuzzPlace; import cc.softwarefactory.lokki.android.models.Contact; -import cc.softwarefactory.lokki.android.models.JSONMap; import cc.softwarefactory.lokki.android.models.MainUser; import cc.softwarefactory.lokki.android.models.Place; import cc.softwarefactory.lokki.android.models.User; import cc.softwarefactory.lokki.android.utilities.AnalyticsUtils; -import cc.softwarefactory.lokki.android.utilities.JsonUtils; import cc.softwarefactory.lokki.android.utilities.PreferenceUtils; public class MainApplication extends Application { @@ -156,8 +149,6 @@ public void setIdMapping(Map idMapping) { public static boolean locationDisabledPromptShown; - public static List buzzPlaces; - public static boolean firstTimeZoom = true; @Override @@ -196,8 +187,6 @@ protected int sizeOf(String key, Bitmap bitmap) { .build()); } - buzzPlaces = new ArrayList<>(); - user = new MainUser(this); super.onCreate(); diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/activities/BuzzActivity.java b/App/src/main/java/cc/softwarefactory/lokki/android/activities/BuzzActivity.java index eddf42f4..09b59b8b 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/activities/BuzzActivity.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/activities/BuzzActivity.java @@ -7,22 +7,20 @@ import android.util.Log; import org.json.JSONException; -import org.json.JSONObject; -import java.util.Iterator; - -import cc.softwarefactory.lokki.android.MainApplication; import cc.softwarefactory.lokki.android.R; -import cc.softwarefactory.lokki.android.fragments.PlacesFragment; -import cc.softwarefactory.lokki.android.models.BuzzPlace; -import cc.softwarefactory.lokki.android.utilities.Utils; +import cc.softwarefactory.lokki.android.models.Place; +import cc.softwarefactory.lokki.android.services.PlaceService; public class BuzzActivity extends AppCompatActivity { private static final String TAG = "BuzzActivity"; + private PlaceService placeService; + @Override protected void onStart() { super.onStart(); + placeService = new PlaceService(this); try { checkForActiveBuzzes(); } catch (JSONException e) { @@ -30,41 +28,18 @@ protected void onStart() { } } - public static void removeBuzz(String id) { - for (Iterator it = MainApplication.buzzPlaces.iterator(); it.hasNext();) { - BuzzPlace buzzPlace = it.next(); - if (buzzPlace.getPlaceId().equals(id)) - MainApplication.buzzPlaces.remove(buzzPlace); - } - } - - public static void setBuzz(String id, int buzzCount) { - removeBuzz(id); - BuzzPlace buzzPlace = new BuzzPlace(); - buzzPlace.setPlaceId(id); - buzzPlace.setBuzzCount(buzzCount); - MainApplication.buzzPlaces.add(buzzPlace); - } - - public static BuzzPlace getBuzz(String id) { - for (BuzzPlace buzzPlace : MainApplication.buzzPlaces) { - if (buzzPlace.getPlaceId().equals(id)) - return buzzPlace; - } - return null; - } - private void checkForActiveBuzzes() throws JSONException { Log.d(TAG, "Checking for active buzzes..."); - for (BuzzPlace buzzPlace : MainApplication.buzzPlaces) { - if (buzzPlace.isActivated()) - openBuzzTerminationDialog(buzzPlace); + for (Place place : placeService.getPlacesWithBuzz()) { + if (place.getBuzzObject().isActivated()) { + openBuzzTerminationDialog(place); return; + } } this.finish(); } - public void openBuzzTerminationDialog(final BuzzPlace placeBuzz) { + public void openBuzzTerminationDialog(final Place place) { Log.d(TAG, "Opening termination dialog"); final Activity thisActivity = this; Dialog buzzTerminationDialog = new android.app.AlertDialog.Builder(this) @@ -74,7 +49,8 @@ public void openBuzzTerminationDialog(final BuzzPlace placeBuzz) { public void onClick(DialogInterface dialogInterface, int which) { try { Log.d(TAG, "Removed buzz"); - setBuzz(placeBuzz.getPlaceId(), 0); + Place.Buzz buzz = place.getBuzzObject(); + buzz.setBuzzCount(0); thisActivity.finish(); } catch (Exception e) { Log.e(TAG, "Unable to terminate buzzing."); diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/activities/MainActivity.java b/App/src/main/java/cc/softwarefactory/lokki/android/activities/MainActivity.java index b81ca92b..9a943899 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/activities/MainActivity.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/activities/MainActivity.java @@ -57,6 +57,7 @@ import cc.softwarefactory.lokki.android.androidServices.LocationService; import cc.softwarefactory.lokki.android.models.Contact; import cc.softwarefactory.lokki.android.services.ContactService; +import cc.softwarefactory.lokki.android.services.PlaceService; import cc.softwarefactory.lokki.android.utilities.AnalyticsUtils; import cc.softwarefactory.lokki.android.utilities.PreferenceUtils; import cc.softwarefactory.lokki.android.utilities.ServerApi; @@ -86,6 +87,8 @@ public class MainActivity extends AppCompatActivity implements NavigationDrawerF private ContactService contactService; private List phoneContacts; + private PlaceService placeService; + //Is this activity currently paused? private boolean paused = true; @@ -123,6 +126,8 @@ public void onClick(View v) { contactService = new ContactService(this); phoneContacts = contactService.getPhoneContacts(); + + placeService = new PlaceService(this); } /** @@ -288,7 +293,7 @@ private void unbindLocationService(){ * Call setLocationServiceAccuracyLevel() afterwards to send it to the service. */ private void setBackgroundLocationAccuracy(){ - if (MainApplication.buzzPlaces.size() > 0){ + if (placeService.getPlacesWithBuzz().size() > 0){ currentAccuracy = LocationService.LocationAccuracy.BGACCURATE; } else { diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/androidServices/LocationService.java b/App/src/main/java/cc/softwarefactory/lokki/android/androidServices/LocationService.java index d100421c..ee57dd01 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/androidServices/LocationService.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/androidServices/LocationService.java @@ -33,7 +33,6 @@ import cc.softwarefactory.lokki.android.R; import cc.softwarefactory.lokki.android.activities.BuzzActivity; import cc.softwarefactory.lokki.android.activities.MainActivity; -import cc.softwarefactory.lokki.android.models.BuzzPlace; import cc.softwarefactory.lokki.android.models.Place; import cc.softwarefactory.lokki.android.services.PlaceService; import cc.softwarefactory.lokki.android.utilities.PreferenceUtils; @@ -336,22 +335,22 @@ private void showArrivalNotification() { } class VibrationThread implements Runnable { - private String id; + private Place place; - VibrationThread(String id) { - this.id = id; + VibrationThread(Place place) { + this.place = place; } @Override public void run() { - BuzzPlace buzzPlace = BuzzActivity.getBuzz(id); + Place.Buzz buzz = place.getBuzzObject(); try { - while (buzzPlace != null && buzzPlace.getBuzzCount() > 0) { + while (buzz != null && buzz.getBuzzCount() > 0) { Log.d(TAG, "Vibrating..."); Vibrator v = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE); v.vibrate(1000); Thread.sleep(2500); - buzzPlace.decBuzzCount(); + buzz.decBuzzCount(); } } catch (InterruptedException e) { e.printStackTrace(); @@ -359,40 +358,29 @@ public void run() { } } - private void triggerBuzzing(final BuzzPlace buzzPlace) throws JSONException { - if (buzzPlace.getBuzzCount() <= 0 || buzzPlace.isActivated()) return; + private void triggerBuzzing(Place place) { + Place.Buzz buzz = place.getBuzzObject(); + if (buzz.isActivated() || buzz.getBuzzCount() <= 0) return; + + buzz.setActivated(true); - buzzPlace.setActivated(false); Intent i = new Intent(); i.setClass(this, BuzzActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); showArrivalNotification(); - Log.d(TAG, "Starting vibration..."); - new Thread(new VibrationThread(buzzPlace.getPlaceId())).start(); + new Thread(new VibrationThread(place)).start(); } private void checkBuzzPlaces() { - for (BuzzPlace buzzPlace : MainApplication.buzzPlaces) { - try { - String placeId = buzzPlace.getPlaceId(); - Place place = placeService.getPlaceById(placeId); - //create android location from Place location information - Location placeLocation = new Location(placeId); - placeLocation.setLatitude(place.getLocation().getLat()); - placeLocation.setLongitude((place.getLocation().getLon())); - if (placeLocation.distanceTo(lastLocation) < place.getLocation().getAcc()) - triggerBuzzing(buzzPlace); - else { - buzzPlace.setBuzzCount(5); - buzzPlace.setActivated(false); - } - } catch (JSONException e) { - Log.e(TAG,"Error in checking buzz places" + e); + for (Place place : placeService.getPlacesWithBuzz()) { + if (place.getLocation().convertToAndroidLocation().distanceTo(lastLocation) < place.getLocation().getAcc()) { + triggerBuzzing(place); + } else { + place.setBuzzObject(PlaceService.createBuzz()); } } - } @Override diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/fragments/PlacesFragment.java b/App/src/main/java/cc/softwarefactory/lokki/android/fragments/PlacesFragment.java index cf7fcb5f..f6ad9328 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/fragments/PlacesFragment.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/fragments/PlacesFragment.java @@ -42,9 +42,7 @@ import cc.softwarefactory.lokki.android.MainApplication; import cc.softwarefactory.lokki.android.R; -import cc.softwarefactory.lokki.android.activities.BuzzActivity; import cc.softwarefactory.lokki.android.androidServices.DataService; -import cc.softwarefactory.lokki.android.models.BuzzPlace; import cc.softwarefactory.lokki.android.models.Contact; import cc.softwarefactory.lokki.android.models.Place; import cc.softwarefactory.lokki.android.models.Person; @@ -135,17 +133,14 @@ public void onClick(View v) { } }); Log.d(TAG, "Setting up checkbox callback"); - final String placeId = place.getId(); + + aq.id(R.id.buzz_checkBox).checked(place.isBuzz()); aq.id(R.id.buzz_checkBox).clicked(new View.OnClickListener() { @Override public void onClick(final View view) { if (((CheckBox) view).isChecked()) { - // This ensures that automatic UI refresh won't uncheck the checkbox - // while the the dialog is still open. - BuzzActivity.setBuzz(placeId, 0); - Dialog dialog = new AlertDialog.Builder(getActivity()) .setMessage(R.string.confirm_buzz) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @@ -154,13 +149,13 @@ public void onClick(DialogInterface dialogInterface, int which) { AnalyticsUtils.eventHit(getString(R.string.analytics_category_ux), getString(R.string.analytics_action_click), getString(R.string.analytics_label_buzz_turn_on)); - BuzzActivity.setBuzz(placeId, 5); + placeService.setBuzz(place, true); + ((CheckBox) view).setChecked(true); } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { - BuzzActivity.removeBuzz(placeId); ((CheckBox) view).setChecked(false); placesFragment.showPlaces(); // Update UI for tests AnalyticsUtils.eventHit(getString(R.string.analytics_category_ux), @@ -171,17 +166,12 @@ public void onClick(DialogInterface dialogInterface, int which) { dialog.setCanceledOnTouchOutside(false); dialog.show(); } else { - BuzzActivity.removeBuzz(placeId); + placeService.setBuzz(place, false); } } }); - for (BuzzPlace buzzPlace : MainApplication.buzzPlaces) { - if (buzzPlace.getPlaceId().equals(placeId)) - aq.id(R.id.buzz_checkBox).checked(true); - } - Log.d(TAG, "Place name: " + place.getName()); Log.d(TAG, "peopleInsidePlace? " + peopleInsidePlace.containsKey(place)); @@ -420,7 +410,6 @@ private void calculatePeopleInside(Place place) { // Compare location float distance = placeLocation.distanceTo(contactLocation); if (distance < placeLocation.getAccuracy()) { - //Log.d(TAG, email + " is in place: " + placeLocation.getProvider()); peopleInThisPlace.add(contact); } } diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/models/BuzzPlace.java b/App/src/main/java/cc/softwarefactory/lokki/android/models/BuzzPlace.java deleted file mode 100644 index afa1a006..00000000 --- a/App/src/main/java/cc/softwarefactory/lokki/android/models/BuzzPlace.java +++ /dev/null @@ -1,37 +0,0 @@ -package cc.softwarefactory.lokki.android.models; - -public class BuzzPlace { - private String placeId; - private int buzzCount; - private boolean activated; - - public String getPlaceId() { - return placeId; - } - - public void setPlaceId(String placeId) { - this.placeId = placeId; - } - - public int getBuzzCount() { - return buzzCount; - } - - public void setBuzzCount(int buzzCount) { - this.buzzCount = buzzCount; - } - - public void decBuzzCount() { - if (this.buzzCount > 0) - buzzCount--; - } - - public boolean isActivated() { - return activated; - } - - public void setActivated(boolean activated) { - this.activated = activated; - } -} - diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/models/Place.java b/App/src/main/java/cc/softwarefactory/lokki/android/models/Place.java index 787f27d7..9cf9095d 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/models/Place.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/models/Place.java @@ -1,17 +1,45 @@ package cc.softwarefactory.lokki.android.models; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonIgnore; /** * Model Class for Tracking Place on Map */ -@JsonIgnoreProperties(ignoreUnknown = true) public class Place implements Comparable { + public static class Buzz { + private int buzzCount; + private boolean activated; + + public int getBuzzCount() { + return buzzCount; + } + + public void setBuzzCount(int buzzCount) { + this.buzzCount = buzzCount; + } + + public void decBuzzCount() { + if (this.buzzCount > 0) + buzzCount--; + } + + public boolean isActivated() { + return activated; + } + + public void setActivated(boolean activated) { + this.activated = activated; + } + } private String id; private String name; private String img; private UserLocation location; + private boolean buzz; + + @JsonIgnore + private Buzz buzzObject; public String getId() { return id; @@ -49,6 +77,22 @@ public void setImg(String img) { this.img = img; } + public boolean isBuzz() { + return buzz; + } + + public void setBuzz(boolean buzz) { + this.buzz = buzz; + } + + public Buzz getBuzzObject() { + return buzzObject; + } + + public void setBuzzObject(Buzz buzzObject) { + this.buzzObject = buzzObject; + } + @Override public String toString() { return getName(); diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/services/ApiService.java b/App/src/main/java/cc/softwarefactory/lokki/android/services/ApiService.java index 48ffb080..6ecd9cb8 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/services/ApiService.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/services/ApiService.java @@ -77,6 +77,11 @@ protected void put(String uri, JSONObject param, AjaxCallback callback) createAjaxWithBody("put", uri, callback, param); } + //TODO construct a put without body using HttpEntity instead of sending empty object + protected void put(String uri, AjaxCallback callback) { + createAjaxWithBody("put", uri, callback, new JSONObject()); + } + protected void delete(String uri, AjaxCallback callback) { createAjax("delete", uri, callback); } diff --git a/App/src/main/java/cc/softwarefactory/lokki/android/services/PlaceService.java b/App/src/main/java/cc/softwarefactory/lokki/android/services/PlaceService.java index 6bf7e2e5..7e260f6f 100644 --- a/App/src/main/java/cc/softwarefactory/lokki/android/services/PlaceService.java +++ b/App/src/main/java/cc/softwarefactory/lokki/android/services/PlaceService.java @@ -15,8 +15,11 @@ import org.json.JSONException; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import cc.softwarefactory.lokki.android.MainApplication; import cc.softwarefactory.lokki.android.R; @@ -29,6 +32,19 @@ public class PlaceService extends ApiService { + private static Map placesWithBuzz; + + public List getPlacesWithBuzz() { + if (placesWithBuzz == null) return new ArrayList<>(); + return new ArrayList<>(placesWithBuzz.keySet()); + } + + public static Place.Buzz createBuzz() { + Place.Buzz buzz = new Place.Buzz(); + buzz.setBuzzCount(5); + return buzz; + } + public PlaceService(Context context) { super(context); } @@ -67,6 +83,15 @@ public void callback(String url, String json, AjaxStatus status) { try { MainApplication.places = JsonUtils.createListFromJson(json.toString(), Place.class); updateCache(); + + placesWithBuzz = new HashMap<>(); + for (Place place : MainApplication.places) { + if (place.isBuzz()) { + place.setBuzzObject(createBuzz()); + placesWithBuzz.put(place, true); + } + } + Intent intent = new Intent("PLACES-UPDATE"); LocalBroadcastManager.getInstance(context).sendBroadcast(intent); } catch (IOException e) { @@ -196,11 +221,30 @@ public void callback(String url, String result, AjaxStatus status) { }); } - public Place getPlaceById(String id) { - for (Place place : MainApplication.places) { - if (place.getId() == id) return place; + public void setBuzz(final Place place, boolean isBuzz) { + Log.d(TAG, "setPuzz"); + + place.setBuzz(isBuzz); + placesWithBuzz.remove(place); + if (place.isBuzz()) { + place.setBuzzObject(createBuzz()); + placesWithBuzz.put(place, true); } - Log.e(TAG, "couldn't find place by id: " + id); - return null; + updateCache(); + + put(restPath + "/" + place.getId() + "/buzz/" + isBuzz, new AjaxCallback() { + @Override + public void callback(String url, String result, AjaxStatus status) { + ServerApi.logStatus("buzzPlace", status); + + if (status.getError() != null) { + displayPlaceError(status); + return; + } + + Intent intent = new Intent("PLACES-UPDATE"); + LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + } + }); } } diff --git a/App/src/test/java/cc/softwarefactory/lokki/android/espresso/BuzzTest.java b/App/src/test/java/cc/softwarefactory/lokki/android/espresso/BuzzTest.java index d247ad7e..a2b268b6 100644 --- a/App/src/test/java/cc/softwarefactory/lokki/android/espresso/BuzzTest.java +++ b/App/src/test/java/cc/softwarefactory/lokki/android/espresso/BuzzTest.java @@ -1,23 +1,20 @@ package cc.softwarefactory.lokki.android.espresso; -import android.support.test.espresso.ViewAssertion; -import android.support.test.espresso.matcher.ViewMatchers; import android.util.Log; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.squareup.okhttp.mockwebserver.MockResponse; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; -import java.util.ArrayList; import java.util.Date; +import java.util.List; -import cc.softwarefactory.lokki.android.MainApplication; import cc.softwarefactory.lokki.android.R; import cc.softwarefactory.lokki.android.espresso.utilities.MockJsonUtils; import cc.softwarefactory.lokki.android.espresso.utilities.TestUtils; +import cc.softwarefactory.lokki.android.models.Place; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; @@ -42,7 +39,6 @@ public class BuzzTest extends LoggedInBaseTest { public void setUp() throws Exception { super.setUp(); - MainApplication.buzzPlaces = new ArrayList<>(); } private void enterContactsScreen() { @@ -90,6 +86,10 @@ public void setBuzzToTestplace1() throws JSONException, JsonProcessingException enterPlacesScreen(); openDialogForTestplace1(); onView(withText(R.string.yes)).perform(click()); + + List places = MockJsonUtils.getPlaces(); + places.get(0).setBuzz(true); + getMockDispatcher().setPlacesResponse(new MockResponse().setBody(new ObjectMapper().writeValueAsString(places))); } public void testConfirmBuzzworks() throws JSONException, JsonProcessingException { diff --git a/App/src/test/java/cc/softwarefactory/lokki/android/espresso/utilities/MockJsonUtils.java b/App/src/test/java/cc/softwarefactory/lokki/android/espresso/utilities/MockJsonUtils.java index a263aff4..c4dff2a8 100644 --- a/App/src/test/java/cc/softwarefactory/lokki/android/espresso/utilities/MockJsonUtils.java +++ b/App/src/test/java/cc/softwarefactory/lokki/android/espresso/utilities/MockJsonUtils.java @@ -40,8 +40,7 @@ public static String getContactsJson() throws JSONException, JsonProcessingExcep } - - public static String getPlacesJson() throws JSONException, JsonProcessingException { + public static List getPlaces() { List places = new ArrayList<>(); Place place = new Place(); @@ -66,7 +65,12 @@ public static String getPlacesJson() throws JSONException, JsonProcessingExcepti places.add(place); places.add(place2); - return new ObjectMapper().writeValueAsString(places); + + return places; + } + + public static String getPlacesJson() throws JSONException, JsonProcessingException { + return new ObjectMapper().writeValueAsString(getPlaces()); } public static String getEmptyDashboardJson() throws JSONException {