Files
PalladiumWallet/src/App.Android/MainActivity.cs
T
davide 94a474fe41 fix(sync): recover connection after Android screen lock/unlock
TcpClient.Connected only reflects the last known socket state, so a
connection killed silently while the phone was locked (Doze, mobile
radio suspend, NAT timeout) still reported IsConnected == true. The
keep-alive ping's failure was swallowed by an empty catch, so the
stale "connected" state never cleared and sync kept retrying on a
dead socket instead of reconnecting.

Treat a failed keep-alive ping as a disconnect (tear down the client
and reconnect), and add OnPause/OnResume to the Android activity to
force an immediate health check on resume instead of waiting for the
20s timer, which may itself be suspended during Doze.
2026-07-19 16:01:18 +02:00

60 lines
1.9 KiB
C#

using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Avalonia.Android;
using AvaloniaApp = PalladiumWallet.App.App;
namespace PalladiumWallet.Mobile;
[Activity(
Label = "Palladium Wallet",
Theme = "@style/MyTheme.NoActionBar",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity
{
internal const int ScanRequestCode = 9001;
internal static TaskCompletionSource<string?>? ScanTcs;
internal static MainActivity? Current;
private bool _wasPaused;
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
Current = this;
}
protected override void OnPause()
{
base.OnPause();
_wasPaused = true;
}
protected override void OnResume()
{
base.OnResume();
if (!_wasPaused) return;
_wasPaused = false;
// The TCP socket can die silently while the screen was off/locked (Doze,
// mobile radio suspend, NAT timeout) without the app ever observing the
// failure. Force an immediate health check instead of waiting for the next
// 20s keep-alive tick, which may itself have been suspended for longer than
// the lock.
if (AvaloniaApp.MainViewModel is { } vm)
_ = vm.CheckConnectionOnResumeAsync();
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == ScanRequestCode)
{
var text = resultCode == Result.Ok ? data?.GetStringExtra(ScannerActivity.ResultKey) : null;
ScanTcs?.TrySetResult(text);
ScanTcs = null;
}
}
}