offline track

This commit is contained in:
2026-06-19 12:50:42 +03:00
parent 8812cf9b40
commit d4842d4b29
3 changed files with 69 additions and 15 deletions
@@ -67,6 +67,15 @@ public class CommandPoller {
}
}
@Override
public void onSyncComplete(long trackId, int pointCount) {
if (pendingAckSessionId > 0 && trackId > 0) {
long sid = pendingAckSessionId;
pendingAckSessionId = -1;
executor.execute(() -> ackSession(sid, trackId));
}
}
@Override
public void onError(String message) {
Log.w(TAG, "track: " + message);
@@ -136,15 +136,40 @@ public class TrackRecorder {
}
public void start() {
if (recording || pendingSync) {
if (recording) {
return;
}
executor.execute(() -> {
if (pendingSync) {
syncWhenOnline();
if (pendingSync) {
notifyError(appContext.getString(R.string.track_sync_pending));
return;
}
}
if (!networkMonitor.isOnline()) {
startLocalRecording();
return;
}
try {
startOnlineRecording();
} catch (Exception e) {
Log.w(TAG, "start track on server failed", e);
if (isReachabilityError(e)) {
startLocalRecording();
} else {
notifyError(e.getMessage() != null ? e.getMessage() : "start failed");
}
}
});
}
/** Retry upload of a track stopped offline. */
public void retryPendingSync() {
executor.execute(this::syncWhenOnline);
}
private void startOnlineRecording() throws Exception {
long id = serverApi.startTrack(deviceId);
synchronized (buffer) {
buffer.clear();
@@ -157,11 +182,29 @@ public class TrackRecorder {
persistState(false);
startTimers();
notifyState();
} catch (Exception e) {
Log.e(TAG, "start track failed", e);
notifyError(e.getMessage());
}
});
private static boolean isReachabilityError(Throwable e) {
while (e != null) {
if (e instanceof java.net.UnknownHostException
|| e instanceof java.net.ConnectException
|| e instanceof java.net.SocketTimeoutException) {
return true;
}
String msg = e.getMessage();
if (msg != null) {
String lower = msg.toLowerCase();
if (lower.contains("unable to resolve host")
|| lower.contains("failed to connect")
|| lower.contains("timeout")
|| lower.contains("econnrefused")
|| lower.contains("network is unreachable")) {
return true;
}
}
e = e.getCause();
}
return false;
}
private void startLocalRecording() {
@@ -265,6 +308,7 @@ public class TrackRecorder {
trackId = id;
flushBuffer();
persistState(false);
notifyState();
Log.i(TAG, "promoted local track to server id " + id);
} catch (Exception e) {
Log.w(TAG, "promote local track failed", e);
@@ -681,6 +681,7 @@ public class MapFragment extends Fragment {
trackRecorder.stop();
} else {
if (trackRecorder.hasPendingSync()) {
trackRecorder.retryPendingSync();
Toast.makeText(requireContext(), R.string.track_sync_pending, Toast.LENGTH_SHORT).show();
return;
}