From 3a7ae54734b1dca68b83d1e6612ff8f04fbd180b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Brul=C3=A9?= <raphael.brule@savoirfairelinux.com> Date: Thu, 30 Jul 2020 12:42:52 -0400 Subject: [PATCH] Location sharing: stop message Adds the location sharing stop message for Android devices. Works with the upcoming iOS implementation and does not break compatibility with older versions of this feature. Change-Id: I9f19e4d5ae7ec312c5b91811e6a209d5a0b89962 --- .../ring/services/LocationSharingService.java | 19 ++++++- .../src/main/java/cx/ring/model/Account.java | 56 +++++++++++++------ .../java/cx/ring/services/AccountService.java | 24 +++++++- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java b/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java index a8e4b89e8..11b5dbc17 100644 --- a/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java +++ b/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java @@ -2,6 +2,7 @@ * Copyright (C) 2004-2020 Savoir-faire Linux Inc. * * Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com> + * Author: Raphaël Brulé <raphael.brule@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,6 +45,7 @@ import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationCompat; +import org.json.JSONException; import org.json.JSONObject; import java.util.Date; @@ -192,6 +194,7 @@ public class LocationSharingService extends Service implements LocationListener .throttleLatest(10, TimeUnit.SECONDS) .map(location -> { JSONObject out = new JSONObject(); + out.put("type", AccountService.Location.Type.position.toString()); out.put("lat", location.getLatitude()); out.put("long", location.getLongitude()); out.put("alt", location.getAltitude()); @@ -220,9 +223,23 @@ public class LocationSharingService extends Service implements LocationListener else if (ACTION_STOP.equals(action)) { if (path == null) contactLocationShare.clear(); - else + else { contactLocationShare.remove(path); + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("type", AccountService.Location.Type.stop.toString()); + jsonObject.put("time", Long.MAX_VALUE); + } catch (JSONException e) { + e.printStackTrace(); + } + + Log.w(TAG, "location send " + jsonObject + " to " + contactLocationShare.size()); + StringMap msgs = new StringMap(); + msgs.setRaw(CallService.MIME_GEOLOCATION, Blob.fromString(jsonObject.toString())); + Ringservice.sendAccountTextMessage(path.getAccountId(), path.getContactId(), msgs); + } + mContactSharingSubject.onNext(contactLocationShare.keySet()); if (contactLocationShare.isEmpty()) { diff --git a/ring-android/libringclient/src/main/java/cx/ring/model/Account.java b/ring-android/libringclient/src/main/java/cx/ring/model/Account.java index b1b872a79..acaf66d6c 100644 --- a/ring-android/libringclient/src/main/java/cx/ring/model/Account.java +++ b/ring-android/libringclient/src/main/java/cx/ring/model/Account.java @@ -1,8 +1,9 @@ /* - * Copyright (C) 2004-2019 Savoir-faire Linux Inc. + * Copyright (C) 2004-2020 Savoir-faire Linux Inc. * * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com> + * Author: Raphaël Brulé <raphael.brule@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -900,26 +901,45 @@ public class Account { Log.w(TAG, "onLocationUpdate " + location.getPeer() + " " + location.getLatitude() + ", " + location.getLongitude()); CallContact contact = getContactFromCache(location.getPeer()); - ContactLocation cl = new ContactLocation(); - cl.timestamp = location.getDate(); - cl.latitude = location.getLatitude(); - cl.longitude = location.getLongitude(); - cl.receivedDate = new Date(); + switch (location.getType()) { + case position: + ContactLocation cl = new ContactLocation(); + cl.timestamp = location.getDate(); + cl.latitude = location.getLatitude(); + cl.longitude = location.getLongitude(); + cl.receivedDate = new Date(); + + Observable<ContactLocation> ls = contactLocations.get(contact); + if (ls == null) { + ls = BehaviorSubject.createDefault(cl); + contactLocations.put(contact, ls); + mLocationSubject.onNext(contactLocations); + ContactLocationEntry entry = new ContactLocationEntry(); + entry.contact = contact; + entry.location = ls; + mLocationStartedSubject.onNext(entry); + } else { + if (ls.blockingFirst().timestamp < cl.timestamp) + ((Subject<ContactLocation>) ls).onNext(cl); + } + break; + + case stop: + forceExpireContact(contact); + break; + } - Observable<ContactLocation> ls = contactLocations.get(contact); - if (ls == null) { - ls = BehaviorSubject.createDefault(cl); - contactLocations.put(contact, ls); + return LOCATION_SHARING_EXPIRATION_MS; + } + + synchronized private void forceExpireContact(CallContact contact) { + Log.w(TAG, "forceExpireContact " + contactLocations.size()); + Observable<ContactLocation> cl = contactLocations.remove(contact); + if (cl != null) { + Log.w(TAG, "Contact stopped sharing location: " + contact.getDisplayName()); + ((Subject<ContactLocation>) cl).onComplete(); mLocationSubject.onNext(contactLocations); - ContactLocationEntry entry = new ContactLocationEntry(); - entry.contact = contact; - entry.location = ls; - mLocationStartedSubject.onNext(entry); - } else { - if (ls.blockingFirst().timestamp < cl.timestamp) - ((Subject<ContactLocation>) ls).onNext(cl); } - return cl.receivedDate.getTime() + LOCATION_SHARING_EXPIRATION_MS; } synchronized public void maintainLocation() { diff --git a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java index 012b33505..624422f7d 100644 --- a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java +++ b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java @@ -1,8 +1,9 @@ /* - * Copyright (C) 2004-2019 Savoir-faire Linux Inc. + * Copyright (C) 2004-2020 Savoir-faire Linux Inc. * * Author: Thibault Wittemberg <thibault.wittemberg@savoirfairelinux.com> * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com> + * Author: Raphaël Brulé <raphael.brule@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +21,7 @@ */ package cx.ring.services; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -129,6 +131,11 @@ public class AccountService { Map<String, String> messages; } public static class Location { + public enum Type { + position, + stop + } + Type type; String accountId; String callId; Uri peer; @@ -136,6 +143,10 @@ public class AccountService { double latitude; double longitude; + public Type getType() { + return type; + } + public String getAccount() { return accountId; } @@ -182,8 +193,15 @@ public class AccountService { if (obj.size() < 2) return Maybe.empty(); Location l = new Location(); - l.latitude = obj.get("lat").getAsDouble(); - l.longitude = obj.get("long").getAsDouble(); + + JsonElement type = obj.get("type"); + if (type == null || type.getAsString().equals(Location.Type.position.toString())) { + l.type = Location.Type.position; + l.latitude = obj.get("lat").getAsDouble(); + l.longitude = obj.get("long").getAsDouble(); + } else if (type.getAsString().equals(Location.Type.stop.toString())) { + l.type = Location.Type.stop; + } l.time = obj.get("time").getAsLong(); l.accountId = msg.accountId; l.callId = msg.callId; -- GitLab