mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Merge branch 'main' into adb/add-isbroadcast-isappsender
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
package org.thoughtcrime.securesms.geolocation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ActiveLocationChats {
|
||||
|
||||
private static final String PREFS_NAME = "location_streaming";
|
||||
private static final String KEY_ACTIVE = "active_chat_ids";
|
||||
|
||||
private ActiveLocationChats() {}
|
||||
|
||||
private static SharedPreferences prefs(Context context) {
|
||||
return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a chat. Uses commit() to guarantee the write reaches disk before the process can die to
|
||||
* preserve the superset invariant.
|
||||
*/
|
||||
static void add(Context context, int chatId) {
|
||||
Set<String> current = new HashSet<>(getAll(context));
|
||||
current.add(String.valueOf(chatId));
|
||||
prefs(context).edit().putStringSet(KEY_ACTIVE, current).commit();
|
||||
}
|
||||
|
||||
public static void remove(Context context, int chatId) {
|
||||
Set<String> current = new HashSet<>(getAll(context));
|
||||
current.remove(String.valueOf(chatId));
|
||||
prefs(context).edit().putStringSet(KEY_ACTIVE, current).apply();
|
||||
}
|
||||
|
||||
static void clear(Context context) {
|
||||
prefs(context).edit().remove(KEY_ACTIVE).apply();
|
||||
}
|
||||
|
||||
static Set<Integer> getAllIds(Context context) {
|
||||
Set<Integer> ids = new HashSet<>();
|
||||
for (String s : getAll(context)) {
|
||||
try {
|
||||
ids.add(Integer.parseInt(s));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
private static Set<String> getAll(Context context) {
|
||||
return prefs(context).getStringSet(KEY_ACTIVE, new HashSet<>());
|
||||
}
|
||||
}
|
||||
+68
-35
@@ -17,13 +17,15 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.ServiceCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
import org.thoughtcrime.securesms.ConversationListActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
|
||||
public class LocationStreamingService extends Service {
|
||||
|
||||
private static final String TAG = "LocationStreamingService";
|
||||
private static final String TAG = "LocationStreamingSvc";
|
||||
private static final String ACTION_STOP = "org.thoughtcrime.securesms.geolocation.STOP_STREAMING";
|
||||
private static final int NOTIFICATION_ID = 8801;
|
||||
private static final String CHANNEL_ID = "location_streaming";
|
||||
@@ -36,38 +38,63 @@ public class LocationStreamingService extends Service {
|
||||
// static API
|
||||
|
||||
/** Register a chat for location updates, then ensure the service is running. */
|
||||
public static void startSharing(Context context, int chatId, int durationSeconds) {
|
||||
ActiveLocationChats.add(context, chatId);
|
||||
DcHelper.getContext(context).sendLocationsToChat(chatId, durationSeconds);
|
||||
ContextCompat.startForegroundService(
|
||||
context, new Intent(context, LocationStreamingService.class));
|
||||
}
|
||||
|
||||
/** Unregister a chat. If no chats remain, stop the service. */
|
||||
public static void stopSharing(Context context, int chatId) {
|
||||
ActiveLocationChats.remove(context, chatId);
|
||||
DcHelper.getContext(context).sendLocationsToChat(chatId, 0);
|
||||
if (!DcHelper.getContext(context).isSendingLocationsToChat(0)) {
|
||||
context.stopService(new Intent(context, LocationStreamingService.class));
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureRunning(Context context) {
|
||||
if (!hasLocationPermission(context)) {
|
||||
for (int chatId : ActiveLocationChats.getAllIds(context)) {
|
||||
DcHelper.getContext(context).sendLocationsToChat(chatId, 0);
|
||||
}
|
||||
ActiveLocationChats.clear(context);
|
||||
public static void startSharing(Context context, int accountId, int chatId, int durationSeconds) {
|
||||
try {
|
||||
DcHelper.getRpc(context).sendLocationsToChat(accountId, chatId, durationSeconds);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to start location streaming", e);
|
||||
return;
|
||||
}
|
||||
ContextCompat.startForegroundService(
|
||||
context, new Intent(context, LocationStreamingService.class));
|
||||
}
|
||||
|
||||
/** Unregister a chat. If no chats remain, stop the service. */
|
||||
public static void stopSharing(Context context, int accountId, int chatId) {
|
||||
try {
|
||||
DcHelper.getRpc(context).sendLocationsToChat(accountId, chatId, 0);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to stop location streaming", e);
|
||||
}
|
||||
if (!isAnySharingActive(context)) {
|
||||
context.stopService(new Intent(context, LocationStreamingService.class));
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureRunning(Context context) {
|
||||
if (!hasLocationPermission(context)) {
|
||||
try {
|
||||
DcHelper.getRpc(context).stopSendingLocations();
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to stop location streaming", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isAnySharingActive(context)) {
|
||||
ContextCompat.startForegroundService(
|
||||
context, new Intent(context, LocationStreamingService.class));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
private static boolean isAnySharingActive(Context context) {
|
||||
try {
|
||||
Rpc rpc = DcHelper.getRpc(context);
|
||||
for (int accountId : rpc.getAllAccountIds()) {
|
||||
if (rpc.isSendingLocations(accountId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to check location streaming state", e);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// lifecycle
|
||||
|
||||
@Override
|
||||
@@ -86,7 +113,7 @@ public class LocationStreamingService extends Service {
|
||||
@Override
|
||||
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
|
||||
if (intent != null && ACTION_STOP.equals(intent.getAction())) {
|
||||
stopAllSharing();
|
||||
stopAllSharing(this);
|
||||
stopSelf();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
@@ -100,11 +127,12 @@ public class LocationStreamingService extends Service {
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
private void stopAllSharing() {
|
||||
for (int chatId : ActiveLocationChats.getAllIds(this)) {
|
||||
DcHelper.getContext(this).sendLocationsToChat(chatId, 0);
|
||||
private static void stopAllSharing(Context context) {
|
||||
try {
|
||||
DcHelper.getRpc(context).stopSendingLocations();
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to stop sending locations", e);
|
||||
}
|
||||
ActiveLocationChats.clear(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -150,16 +178,21 @@ public class LocationStreamingService extends Service {
|
||||
private void publishAndWrite(Location location) {
|
||||
LocationData.getInstance().post(location);
|
||||
|
||||
boolean keepGoing =
|
||||
DcHelper.getContext(this)
|
||||
.setLocation(
|
||||
(float) location.getLatitude(),
|
||||
(float) location.getLongitude(),
|
||||
location.getAccuracy());
|
||||
boolean keepGoing;
|
||||
try {
|
||||
keepGoing =
|
||||
DcHelper.getRpc(this)
|
||||
.setLocation(
|
||||
(float) location.getLatitude(),
|
||||
(float) location.getLongitude(),
|
||||
location.getAccuracy());
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to set location", e);
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "keepGoing: " + keepGoing);
|
||||
|
||||
if (!keepGoing) {
|
||||
stopAllSharing();
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import chat.delta.rpc.Rpc;
|
||||
import chat.delta.rpc.RpcException;
|
||||
import chat.delta.util.ListenableFuture;
|
||||
import chat.delta.util.SettableFuture;
|
||||
@@ -63,7 +64,6 @@ import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
|
||||
import org.thoughtcrime.securesms.components.audioplay.AudioView;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.geolocation.ActiveLocationChats;
|
||||
import org.thoughtcrime.securesms.geolocation.LocationStreamingService;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
|
||||
@@ -491,16 +491,29 @@ public class AttachmentManager {
|
||||
|
||||
public static void selectLocation(Activity activity, int chatId) {
|
||||
Context appContext = activity.getApplicationContext();
|
||||
Rpc rpc = DcHelper.getRpc(appContext);
|
||||
int accountId = DcHelper.getContext(appContext).getAccountId();
|
||||
|
||||
if (DcHelper.getContext(appContext).isSendingLocationsToChat(chatId)) {
|
||||
boolean currentlySharing;
|
||||
try {
|
||||
currentlySharing = rpc.isSendingLocationsToChat(accountId, chatId);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to check location streaming state", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentlySharing) {
|
||||
if (LocationStreamingService.isRunning()) {
|
||||
LocationStreamingService.stopSharing(appContext, chatId);
|
||||
LocationStreamingService.stopSharing(appContext, accountId, chatId);
|
||||
return;
|
||||
}
|
||||
// Stale — service is dead but chat layer still thinks it's sharing.
|
||||
// Clean up this chat and fall through to the fresh start flow.
|
||||
ActiveLocationChats.remove(appContext, chatId);
|
||||
DcHelper.getContext(appContext).sendLocationsToChat(chatId, 0);
|
||||
// Clean up and fall through to the fresh start flow.
|
||||
try {
|
||||
rpc.sendLocationsToChat(accountId, chatId, 0);
|
||||
} catch (RpcException e) {
|
||||
Log.e(TAG, "Failed to stop stale location streaming", e);
|
||||
}
|
||||
}
|
||||
|
||||
Permissions.with(activity)
|
||||
@@ -514,7 +527,8 @@ public class AttachmentManager {
|
||||
ShareLocationDialog.show(
|
||||
activity,
|
||||
durationInSeconds ->
|
||||
LocationStreamingService.startSharing(appContext, chatId, durationInSeconds));
|
||||
LocationStreamingService.startSharing(
|
||||
appContext, accountId, chatId, durationInSeconds));
|
||||
})
|
||||
.request(
|
||||
android.Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
|
||||
Reference in New Issue
Block a user