One geofence per place

pull/996/head
Alex Baker 4 years ago
parent 2d79e2e571
commit 0bdf9c8d6f

@ -2,21 +2,30 @@ package org.tasks.data
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import org.junit.Assert.assertEquals import com.todoroo.astrid.dao.TaskDao
import org.junit.Assert.*
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.tasks.caldav.GeoUtils.toLikeString import org.tasks.caldav.GeoUtils.toLikeString
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.TestComponent import org.tasks.injection.TestComponent
import org.tasks.makers.GeofenceMaker.ARRIVAL
import org.tasks.makers.GeofenceMaker.DEPARTURE
import org.tasks.makers.GeofenceMaker.PLACE
import org.tasks.makers.GeofenceMaker.TASK
import org.tasks.makers.GeofenceMaker.newGeofence
import org.tasks.makers.PlaceMaker.LATITUDE import org.tasks.makers.PlaceMaker.LATITUDE
import org.tasks.makers.PlaceMaker.LONGITUDE import org.tasks.makers.PlaceMaker.LONGITUDE
import org.tasks.makers.PlaceMaker.newPlace import org.tasks.makers.PlaceMaker.newPlace
import org.tasks.makers.TaskMaker.*
import javax.inject.Inject import javax.inject.Inject
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class LocationDaoTest : InjectingTestCase() { class LocationDaoTest : InjectingTestCase() {
@Inject lateinit var locationDao: LocationDao @Inject lateinit var locationDao: LocationDao
@Inject lateinit var taskDao: TaskDao
@Test @Test
fun getExistingPlace() { fun getExistingPlace() {
@ -43,6 +52,62 @@ class LocationDaoTest : InjectingTestCase() {
assertEquals(-116.816944, place?.longitude) assertEquals(-116.816944, place?.longitude)
} }
@Test
fun noActiveGeofences() {
val place = newPlace()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid)))
assertNull(locationDao.getGeofencesByPlace(place.uid))
}
@Test
fun activeArrivalGeofence() {
val place = newPlace()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true)))
val geofence = locationDao.getGeofencesByPlace(place.uid)
assertTrue(geofence.arrival)
assertFalse(geofence.departure)
}
@Test
fun activeDepartureGeofence() {
val place = newPlace()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(DEPARTURE, true)))
val geofence = locationDao.getGeofencesByPlace(place.uid)
assertFalse(geofence.arrival)
assertTrue(geofence.departure)
}
@Test
fun geofenceInactiveForCompletedTask() {
val place = newPlace()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1), with(COMPLETION_TIME, newDateTime())))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true)))
assertNull(locationDao.getGeofencesByPlace(place.uid))
}
@Test
fun geofenceInactiveForDeletedTask() {
val place = newPlace()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1), with(DELETION_TIME, newDateTime())))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true)))
assertNull(locationDao.getGeofencesByPlace(place.uid))
}
override fun inject(component: TestComponent) = component.inject(this) override fun inject(component: TestComponent) = component.inject(this)
} }

@ -0,0 +1,31 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.Geofence
import org.tasks.data.Place
object GeofenceMaker {
val PLACE: Property<Geofence, String> = Property.newProperty()
val TASK: Property<Geofence, Long> = Property.newProperty()
val ARRIVAL: Property<Geofence, Boolean> = Property.newProperty()
val DEPARTURE: Property<Geofence, Boolean> = Property.newProperty()
val RADIUS: Property<Geofence, Int> = Property.newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<Geofence> ->
val geofence = Geofence()
geofence.place = lookup.valueOf(PLACE, "")
geofence.task = lookup.valueOf(TASK, 1)
geofence.isArrival = lookup.valueOf(ARRIVAL, false)
geofence.isDeparture = lookup.valueOf(DEPARTURE, false)
geofence.radius = lookup.valueOf(RADIUS, 250)
geofence
}
fun newGeofence(vararg properties: PropertyValue<in Geofence?, *>): Geofence {
return Maker.make(instantiator, *properties)
}
}

@ -4,14 +4,17 @@ import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.PropertyLookup import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.Place import org.tasks.data.Place
object PlaceMaker { object PlaceMaker {
val LATITUDE: Property<Place, Double> = Property.newProperty() val LATITUDE: Property<Place, Double> = Property.newProperty()
val LONGITUDE: Property<Place, Double> = Property.newProperty() val LONGITUDE: Property<Place, Double> = Property.newProperty()
val UUID: Property<Place, String> = Property.newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<Place> -> private val instantiator = Instantiator { lookup: PropertyLookup<Place> ->
val place = Place() val place = Place()
place.uid = lookup.valueOf(UUID, UUIDHelper.newUUID())
place.latitude = lookup.valueOf(LATITUDE, 0.0) place.latitude = lookup.valueOf(LATITUDE, 0.0)
place.longitude = lookup.valueOf(LONGITUDE, 0.0) place.longitude = lookup.valueOf(LONGITUDE, 0.0)
place place

@ -1,25 +1,24 @@
package org.tasks.location; package org.tasks.location;
import static com.google.android.gms.location.Geofence.NEVER_EXPIRE; import static com.google.android.gms.location.Geofence.NEVER_EXPIRE;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import static java.util.Collections.singletonList;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.google.android.gms.location.Geofence; import androidx.annotation.Nullable;
import com.google.android.gms.location.GeofencingClient;
import com.google.android.gms.location.GeofencingRequest; import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.GeofencingRequest.Builder; import com.google.android.gms.location.GeofencingRequest.Builder;
import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationServices;
import com.google.common.collect.ImmutableList;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.data.Location;
import org.tasks.data.LocationDao; import org.tasks.data.LocationDao;
import org.tasks.data.MergedGeofence;
import org.tasks.data.Place;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.preferences.PermissionChecker; import org.tasks.preferences.PermissionChecker;
import timber.log.Timber;
public class GeofenceApi { public class GeofenceApi {
@ -38,77 +37,56 @@ public class GeofenceApi {
} }
public void registerAll() { public void registerAll() {
register(locationDao.getActiveGeofences()); update(locationDao.getPlacesWithGeofences());
} }
public void register(long taskId) { public void update(long taskId) {
register(locationDao.getActiveGeofences(taskId)); update(locationDao.getPlaceForTask(taskId));
} }
public void register(Location location) { public void update(String place) {
register(singletonList(location)); update(locationDao.getPlace(place));
} }
private void register(final List<Location> locations) { private void update(List<Place> places) {
if (!permissionChecker.canAccessLocation()) { for (Place place : places) {
return; update(place);
}
List<Geofence> requests = getRequests(locations);
if (!requests.isEmpty()) {
LocationServices.getGeofencingClient(context)
.addGeofences(
new Builder().addGeofences(requests).build(),
PendingIntent.getBroadcast(
context,
0,
new Intent(context, GeofenceTransitionsIntentService.Broadcast.class),
PendingIntent.FLAG_UPDATE_CURRENT));
} }
} }
public void cancel(long taskId) { public void update(@Nullable Place place) {
cancel(locationDao.getGeofences(taskId)); if (place == null || !permissionChecker.canAccessLocation()) {
}
public void cancel(final Location location) {
if (location != null) {
cancel(singletonList(location));
}
}
public void cancel(final List<Location> locations) {
if (!permissionChecker.canAccessLocation()) {
return; return;
} }
List<String> requestIds = getRequestIds(locations);
if (!requestIds.isEmpty()) {
LocationServices.getGeofencingClient(context).removeGeofences(requestIds);
}
}
@SuppressWarnings("ConstantConditions") GeofencingClient client = LocationServices.getGeofencingClient(context);
private List<String> getRequestIds(List<Location> locations) { MergedGeofence geofence = locationDao.getGeofencesByPlace(place.getUid());
return transform(newArrayList(filter(locations, notNull())), l -> Long.toString(l.getId())); if (geofence != null) {
} Timber.d("Adding geofence for %s", geofence);
client.addGeofences(
private List<com.google.android.gms.location.Geofence> getRequests(List<Location> locations) { new Builder().addGeofence(toGoogleGeofence(geofence)).build(),
return transform( PendingIntent.getBroadcast(
newArrayList(filter(locations, l -> l != null && (l.isArrival() || l.isDeparture()))), context,
this::toGoogleGeofence); 0,
new Intent(context, GeofenceTransitionsIntentService.Broadcast.class),
PendingIntent.FLAG_UPDATE_CURRENT));
} else {
Timber.d("Removing geofence for %s", place);
client.removeGeofences(ImmutableList.of(Long.toString(place.getId())));
}
} }
private com.google.android.gms.location.Geofence toGoogleGeofence(Location location) { private com.google.android.gms.location.Geofence toGoogleGeofence(MergedGeofence geofence) {
int transitionTypes = 0; int transitionTypes = 0;
if (location.isArrival()) { if (geofence.isArrival()) {
transitionTypes |= GeofencingRequest.INITIAL_TRIGGER_ENTER; transitionTypes |= GeofencingRequest.INITIAL_TRIGGER_ENTER;
} }
if (location.isDeparture()) { if (geofence.isDeparture()) {
transitionTypes |= GeofencingRequest.INITIAL_TRIGGER_EXIT; transitionTypes |= GeofencingRequest.INITIAL_TRIGGER_EXIT;
} }
return new com.google.android.gms.location.Geofence.Builder() return new com.google.android.gms.location.Geofence.Builder()
.setCircularRegion(location.getLatitude(), location.getLongitude(), location.getRadius()) .setCircularRegion(geofence.getLatitude(), geofence.getLongitude(), geofence.getRadius())
.setRequestId(Long.toString(location.getId())) .setRequestId(geofence.getUid())
.setTransitionTypes(transitionTypes) .setTransitionTypes(transitionTypes)
.setExpirationDuration(NEVER_EXPIRE) .setExpirationDuration(NEVER_EXPIRE)
.build(); .build();

@ -4,7 +4,6 @@ import static com.google.android.gms.location.Geofence.GEOFENCE_TRANSITION_ENTER
import static com.google.android.gms.location.Geofence.GEOFENCE_TRANSITION_EXIT; import static com.google.android.gms.location.Geofence.GEOFENCE_TRANSITION_EXIT;
import static com.todoroo.astrid.reminders.ReminderService.TYPE_GEOFENCE_ENTER; import static com.todoroo.astrid.reminders.ReminderService.TYPE_GEOFENCE_ENTER;
import static com.todoroo.astrid.reminders.ReminderService.TYPE_GEOFENCE_EXIT; import static com.todoroo.astrid.reminders.ReminderService.TYPE_GEOFENCE_EXIT;
import static java.util.Collections.singletonList;
import static org.tasks.time.DateTimeUtils.currentTimeMillis; import static org.tasks.time.DateTimeUtils.currentTimeMillis;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@ -12,11 +11,13 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import androidx.core.app.JobIntentService; import androidx.core.app.JobIntentService;
import com.google.android.gms.location.GeofencingEvent; import com.google.android.gms.location.GeofencingEvent;
import com.google.common.collect.Lists;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.Notifier; import org.tasks.Notifier;
import org.tasks.data.Location; import org.tasks.data.Geofence;
import org.tasks.data.LocationDao; import org.tasks.data.LocationDao;
import org.tasks.data.Place;
import org.tasks.injection.InjectingJobIntentService; import org.tasks.injection.InjectingJobIntentService;
import org.tasks.injection.ServiceComponent; import org.tasks.injection.ServiceComponent;
import org.tasks.notifications.Notification; import org.tasks.notifications.Notification;
@ -58,20 +59,27 @@ public class GeofenceTransitionsIntentService extends InjectingJobIntentService
com.google.android.gms.location.Geofence triggeringGeofence, boolean arrival) { com.google.android.gms.location.Geofence triggeringGeofence, boolean arrival) {
String requestId = triggeringGeofence.getRequestId(); String requestId = triggeringGeofence.getRequestId();
try { try {
Place place = locationDao.getPlace(requestId);
if (place == null) {
Timber.e("Can't find place for requestId %s", requestId);
return;
}
List<Geofence> geofences = arrival
? locationDao.getArrivalGeofences(place.getUid())
: locationDao.getDepartureGeofences(place.getUid());
notifier.triggerNotifications( notifier.triggerNotifications(
singletonList( Lists.transform(geofences, g -> toNotification(place, g, arrival)));
toNotification(locationDao.getGeofence(Long.parseLong(requestId)), arrival)));
} catch (Exception e) { } catch (Exception e) {
Timber.e(e, "Error triggering geofence %s: %s", requestId, e.getMessage()); Timber.e(e, "Error triggering geofence %s: %s", requestId, e.getMessage());
} }
} }
private Notification toNotification(Location location, boolean arrival) { private Notification toNotification(Place place, Geofence geofence, boolean arrival) {
Notification notification = new Notification(); Notification notification = new Notification();
notification.taskId = location.getTask(); notification.taskId = geofence.getTask();
notification.type = arrival ? TYPE_GEOFENCE_ENTER : TYPE_GEOFENCE_EXIT; notification.type = arrival ? TYPE_GEOFENCE_ENTER : TYPE_GEOFENCE_EXIT;
notification.timestamp = currentTimeMillis(); notification.timestamp = currentTimeMillis();
notification.location = location.getId(); notification.location = place.getId();
return notification; return notification;
} }

@ -95,7 +95,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
} }
override fun delete() { override fun delete() {
locationDao.getGeofencesByPlace(place.uid).forEach(locationDao::delete) locationDao.deleteGeofencesByPlace(place.uid)
locationDao.delete(place) locationDao.delete(place)
setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED)) setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED))
finish() finish()

@ -10,7 +10,6 @@ import com.google.common.collect.Sets.difference
import com.google.common.collect.Sets.newHashSet import com.google.common.collect.Sets.newHashSet
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.SyncFlags
import com.todoroo.astrid.helper.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import com.todoroo.astrid.service.TaskCreator import com.todoroo.astrid.service.TaskCreator
import net.fortuna.ical4j.model.Parameter import net.fortuna.ical4j.model.Parameter
@ -29,6 +28,7 @@ import java.io.ByteArrayOutputStream
import java.io.StringReader import java.io.StringReader
import javax.inject.Inject import javax.inject.Inject
@Suppress("ClassName")
class iCalendar @Inject constructor( class iCalendar @Inject constructor(
private val tagDataDao: TagDataDao, private val tagDataDao: TagDataDao,
private val preferences: Preferences, private val preferences: Preferences,
@ -85,14 +85,13 @@ class iCalendar @Inject constructor(
val geofence = Geofence(place!!.uid, preferences) val geofence = Geofence(place!!.uid, preferences)
geofence.task = taskId geofence.task = taskId
geofence.id = locationDao.insert(geofence) geofence.id = locationDao.insert(geofence)
geofenceApi.register(Location(geofence, place))
} else if (place != existing.place) { } else if (place != existing.place) {
geofenceApi.cancel(existing)
val geofence = existing.geofence val geofence = existing.geofence
geofence.place = place!!.uid geofence.place = place!!.uid
locationDao.update(geofence) locationDao.update(geofence)
geofenceApi.register(existing) geofenceApi.update(existing.place)
} }
geofenceApi.update(place)
} }
fun getTags(categories: List<String>): List<TagData> { fun getTags(categories: List<String>): List<TagData> {
@ -154,8 +153,8 @@ class iCalendar @Inject constructor(
val geo = remote.geoPosition val geo = remote.geoPosition
if (geo == null) { if (geo == null) {
locationDao.getActiveGeofences(task.getId()).forEach { locationDao.getActiveGeofences(task.getId()).forEach {
geofenceApi.cancel(it)
locationDao.delete(it.geofence) locationDao.delete(it.geofence)
geofenceApi.update(it.place)
} }
} else { } else {
setPlace(task.getId(), geo) setPlace(task.getId(), geo)

@ -15,17 +15,59 @@ import org.tasks.filters.LocationFilters;
public interface LocationDao { public interface LocationDao {
@Query( @Query(
"SELECT * FROM geofences INNER JOIN places ON geofences.place = places.uid WHERE geofence_id = :id LIMIT 1") "SELECT places.*"
Location getGeofence(Long id); + " FROM places"
+ " INNER JOIN geofences ON geofences.place = places.uid"
+ " INNER JOIN tasks ON geofences.task = tasks._id"
+ " WHERE tasks.completed = 0 AND tasks.deleted = 0"
+ " AND (geofences.arrival > 0 OR geofences.departure > 0)"
+ " GROUP BY places.uid")
List<Place> getPlacesWithGeofences();
@Query( @Query(
"SELECT * FROM geofences INNER JOIN places ON geofences.place = places.uid WHERE task = :taskId ORDER BY name ASC LIMIT 1") "SELECT places.*,"
+ " max(geofences.arrival) as arrival,"
+ " max(geofences.departure) as departure,"
+ " min(geofences.radius) as radius"
+ " FROM places"
+ " INNER JOIN geofences ON geofences.place = places.uid"
+ " INNER JOIN tasks ON tasks._id = geofences.task"
+ " WHERE place = :uid AND tasks.completed = 0 AND tasks.deleted = 0"
+ " AND (geofences.arrival > 0 OR geofences.departure > 0)"
+ " GROUP BY places.uid")
MergedGeofence getGeofencesByPlace(String uid);
@Query("DELETE FROM geofences WHERE place = :place")
void deleteGeofencesByPlace(String place);
@Query(
"SELECT geofences.* FROM geofences"
+ " INNER JOIN tasks ON tasks._id = geofences.task"
+ " WHERE place = :place AND arrival = 1 AND tasks.completed = 0 AND tasks.deleted = 0")
List<Geofence> getArrivalGeofences(String place);
@Query(
"SELECT geofences.* FROM geofences"
+ " INNER JOIN tasks ON tasks._id = geofences.task"
+ " WHERE place = :place AND departure = 1 AND tasks.completed = 0 AND tasks.deleted = 0")
List<Geofence> getDepartureGeofences(String place);
@Query(
"SELECT * FROM geofences"
+ " INNER JOIN places ON geofences.place = places.uid"
+ " WHERE task = :taskId ORDER BY name ASC LIMIT 1")
Location getGeofences(long taskId); Location getGeofences(long taskId);
@Query( @Query(
"SELECT geofences.*, places.* FROM geofences INNER JOIN places ON geofences.place = places.uid INNER JOIN tasks ON tasks._id = geofences.task WHERE tasks._id = :taskId AND tasks.deleted = 0 AND tasks.completed = 0") "SELECT geofences.*, places.* FROM geofences INNER JOIN places ON geofences.place = places.uid INNER JOIN tasks ON tasks._id = geofences.task WHERE tasks._id = :taskId AND tasks.deleted = 0 AND tasks.completed = 0")
List<Location> getActiveGeofences(long taskId); List<Location> getActiveGeofences(long taskId);
@Query("SELECT places.*"
+ " FROM places"
+ " INNER JOIN geofences ON geofences.place = places.uid"
+ " WHERE geofences.task = :taskId")
Place getPlaceForTask(long taskId);
@Query( @Query(
"SELECT geofences.*, places.* FROM geofences INNER JOIN places ON geofences.place = places.uid INNER JOIN tasks ON tasks._id = geofences.task WHERE tasks.deleted = 0 AND tasks.completed = 0") "SELECT geofences.*, places.* FROM geofences INNER JOIN places ON geofences.place = places.uid INNER JOIN tasks ON tasks._id = geofences.task WHERE tasks.deleted = 0 AND tasks.completed = 0")
List<Location> getActiveGeofences(); List<Location> getActiveGeofences();
@ -57,9 +99,6 @@ public interface LocationDao {
@Query("SELECT * FROM geofences WHERE task = :taskId") @Query("SELECT * FROM geofences WHERE task = :taskId")
List<Geofence> getGeofencesForTask(long taskId); List<Geofence> getGeofencesForTask(long taskId);
@Query("SELECT * FROM geofences WHERE place = :uid")
List<Geofence> getGeofencesByPlace(String uid);
@Query("SELECT * FROM places") @Query("SELECT * FROM places")
List<Place> getPlaces(); List<Place> getPlaces();

@ -0,0 +1,52 @@
package org.tasks.data;
import androidx.room.Embedded;
public class MergedGeofence {
@Embedded Place place;
boolean arrival;
boolean departure;
int radius;
public Place getPlace() {
return place;
}
public String getUid() {
return place.getUid();
}
public double getLatitude() {
return place.getLatitude();
}
public double getLongitude() {
return place.getLongitude();
}
public boolean isArrival() {
return arrival;
}
public boolean isDeparture() {
return departure;
}
public int getRadius() {
return radius;
}
@Override
public String toString() {
return "MergedGeofence{"
+ "place="
+ place.getDisplayName()
+ ", arrival="
+ arrival
+ ", departure="
+ departure
+ ", radius="
+ radius
+ '}';
}
}

@ -98,9 +98,9 @@ public class AfterSaveWork extends InjectingWorker {
if (justCompleted || justDeleted) { if (justCompleted || justDeleted) {
notificationManager.cancel(taskId); notificationManager.cancel(taskId);
geofenceApi.cancel(taskId); }
} else if (completionDateModified || deletionDateModified) { if (completionDateModified || deletionDateModified) {
geofenceApi.register(taskId); geofenceApi.update(taskId);
} }
if (justCompleted) { if (justCompleted) {

@ -7,6 +7,8 @@ import com.todoroo.astrid.alarms.AlarmService;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
import com.todoroo.astrid.timers.TimerPlugin; import com.todoroo.astrid.timers.TimerPlugin;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.data.Geofence;
import org.tasks.data.LocationDao;
import org.tasks.data.TaskAttachment; import org.tasks.data.TaskAttachment;
import org.tasks.data.TaskAttachmentDao; import org.tasks.data.TaskAttachmentDao;
import org.tasks.data.UserActivity; import org.tasks.data.UserActivity;
@ -29,6 +31,7 @@ public class CleanupWork extends InjectingWorker {
@Inject AlarmService alarmService; @Inject AlarmService alarmService;
@Inject TaskAttachmentDao taskAttachmentDao; @Inject TaskAttachmentDao taskAttachmentDao;
@Inject UserActivityDao userActivityDao; @Inject UserActivityDao userActivityDao;
@Inject LocationDao locationDao;
public CleanupWork(@NonNull Context context, @NonNull WorkerParameters workerParams) { public CleanupWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams); super(context, workerParams);
@ -47,7 +50,10 @@ public class CleanupWork extends InjectingWorker {
alarmService.cancelAlarms(task); alarmService.cancelAlarms(task);
reminderService.cancelReminder(task); reminderService.cancelReminder(task);
notificationManager.cancel(task); notificationManager.cancel(task);
geofenceApi.cancel(task); for (Geofence geofence : locationDao.getGeofencesForTask(task)) {
locationDao.delete(geofence);
geofenceApi.update(geofence.getPlace());
}
for (TaskAttachment attachment : taskAttachmentDao.getAttachments(task)) { for (TaskAttachment attachment : taskAttachmentDao.getAttachments(task)) {
FileHelper.delete(context, attachment.parseUri()); FileHelper.delete(context, attachment.parseUri());
taskAttachmentDao.delete(attachment); taskAttachmentDao.delete(attachment);

@ -41,8 +41,8 @@ import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.LocalBroadcastManager; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.Location;
import org.tasks.data.LocationDao; import org.tasks.data.LocationDao;
import org.tasks.data.Place;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.intents.TaskIntents; import org.tasks.intents.TaskIntents;
@ -383,14 +383,14 @@ public class NotificationManager {
PendingIntent.getActivity(context, (int) id, intent, PendingIntent.FLAG_UPDATE_CURRENT)); PendingIntent.getActivity(context, (int) id, intent, PendingIntent.FLAG_UPDATE_CURRENT));
if (type == TYPE_GEOFENCE_ENTER || type == TYPE_GEOFENCE_EXIT) { if (type == TYPE_GEOFENCE_ENTER || type == TYPE_GEOFENCE_EXIT) {
Location location = locationDao.getGeofence(notification.location); Place place = locationDao.getPlace(notification.location);
if (location != null) { if (place != null) {
builder.setContentText( builder.setContentText(
context.getString( context.getString(
type == TYPE_GEOFENCE_ENTER type == TYPE_GEOFENCE_ENTER
? R.string.location_arrived ? R.string.location_arrived
: R.string.location_departed, : R.string.location_departed,
location.getDisplayName())); place.getDisplayName()));
} }
} else if (!Strings.isNullOrEmpty(taskDescription)) { } else if (!Strings.isNullOrEmpty(taskDescription)) {
builder builder

@ -263,8 +263,8 @@ public class LocationControlSet extends TaskEditControlFragment {
} }
if (original != null) { if (original != null) {
geofenceApi.cancel(original);
locationDao.delete(original.geofence); locationDao.delete(original.geofence);
geofenceApi.update(original.place);
} }
if (location != null) { if (location != null) {
Place place = location.place; Place place = location.place;
@ -272,7 +272,7 @@ public class LocationControlSet extends TaskEditControlFragment {
geofence.setTask(task.getId()); geofence.setTask(task.getId());
geofence.setPlace(place.getUid()); geofence.setPlace(place.getUid());
geofence.setId(locationDao.insert(geofence)); geofence.setId(locationDao.insert(geofence));
geofenceApi.register(location); geofenceApi.update(place);
} }
task.setModificationDate(DateUtilities.now()); task.setModificationDate(DateUtilities.now());
} }

Loading…
Cancel
Save