Skip to content

Commit 8f3e714

Browse files
committed
Local-only location tracking, config overhaul, resilience
- Device location tracking is now stored locally in SQLite (TR-MOBILE-001); removed all API/mediator calls from LocationTrackingService. - Added DeviceLocationEntity, migration, and MobileDatabaseMigrationService; database is auto-migrated on startup. - Overhauled app configuration: appsettings.json, build-time host IP detection for Android, platform-specific config loading, and strong-typed ApiSettings. - Integrated Polly-based resilience (fallback, circuit breaker, retry, timeout) for all API HttpClients (Overpass, Location, Marketing). - Fixed LogViewerControl DataContext so logs display in UI. - Updated Kestrel to listen on 0.0.0.0 in dev for Android LAN access. - Added byte[]→Bitmap converter for chat image previews. - Updated docs: device location tracking, migrations, config, resilience, and troubleshooting. - All related tests pass; architecture and privacy improved.
1 parent d9dff17 commit 8f3e714

File tree

53 files changed

+5501
-186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+5501
-186
lines changed

Directory.Packages.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<ItemGroup>
99
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
1010
<PackageVersion Include="GPS.SimpleMVC" Version="2.0.0" />
11+
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.2" />
1112
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
1213
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.2" />
1314
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.2" />
@@ -16,6 +17,7 @@
1617
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.1" />
1718
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
1819
<PackageVersion Include="Moq" Version="4.20.72" />
20+
<PackageVersion Include="Polly.Extensions" Version="8.5.0" />
1921
<PackageVersion Include="Refit.HttpClientFactory" Version="9.0.2" />
2022
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.0.1" />
2123
<!-- Test packages required by FWH.Common.Workflow.Tests -->

FunWasHad.slnLaunch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
{
66
"Path": "src\\FWH.Mobile\\FWH.Mobile.Android\\FWH.Mobile.Android.csproj",
77
"Action": "Start",
8-
"DebugTarget": "7.6 Fold-in with outer display API 33 (Android 13.0 - API 33)"
8+
"DebugTarget": "Motorola edge 2024 (Android 15.0 - API 35)"
99
},
1010
{
1111
"Path": "src\\FWH.AppHost\\FWH.AppHost.csproj",
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
# API Network Configuration for Android Development
2+
3+
## Overview
4+
5+
The FWH Location API and Marketing API are configured to listen on all network interfaces (`0.0.0.0`) during Development mode, allowing Android devices and emulators to connect via the host machine's IP address.
6+
7+
## Configuration
8+
9+
### Location API (FWH.Location.Api)
10+
11+
**Ports:**
12+
- HTTP: `4748` (all interfaces in Development)
13+
- HTTPS: `4747` (all interfaces in Development)
14+
15+
**Endpoints:**
16+
- Android Emulator: `http://10.0.2.2:4748`
17+
- Physical Android Device: `http://192.168.1.77:4748` (example, auto-detected)
18+
- Desktop/iOS: `https://localhost:4747` or `http://localhost:4748`
19+
20+
### Marketing API (FWH.MarketingApi)
21+
22+
**Ports:**
23+
- HTTP: `4750` (all interfaces in Development)
24+
- HTTPS: `4749` (all interfaces in Development)
25+
26+
**Endpoints:**
27+
- Android Emulator: `http://10.0.2.2:4750`
28+
- Physical Android Device: `http://192.168.1.77:4750` (example, auto-detected)
29+
- Desktop/iOS: `https://localhost:4749` or `http://localhost:4750`
30+
31+
## Implementation
32+
33+
### Kestrel Configuration
34+
35+
Both APIs use the following Kestrel configuration in `Program.cs`:
36+
37+
```csharp
38+
if (builder.Environment.IsDevelopment())
39+
{
40+
builder.WebHost.ConfigureKestrel(options =>
41+
{
42+
// Listen on all interfaces for HTTP
43+
options.ListenAnyIP(port);
44+
45+
// Listen on all interfaces for HTTPS
46+
options.ListenAnyIP(httpsPort, listenOptions =>
47+
{
48+
listenOptions.UseHttps();
49+
});
50+
});
51+
}
52+
```
53+
54+
### Why `0.0.0.0`?
55+
56+
**localhost (127.0.0.1):**
57+
- Only accepts connections from the same machine
58+
- Android devices/emulators cannot reach it from external network
59+
60+
**0.0.0.0 (all interfaces):**
61+
- Accepts connections from any network interface
62+
- Allows Android emulators via `10.0.2.2`
63+
- Allows physical Android devices via LAN IP (e.g., `192.168.1.77`)
64+
- Still accepts `localhost` connections from the host machine
65+
66+
## Security Considerations
67+
68+
### Development Mode Only
69+
70+
The `0.0.0.0` configuration is **only active in Development mode**:
71+
72+
```csharp
73+
if (builder.Environment.IsDevelopment())
74+
{
75+
// Listen on 0.0.0.0
76+
}
77+
```
78+
79+
In **Production**, APIs should:
80+
- Listen on specific interfaces or use reverse proxy
81+
- Enforce HTTPS with valid certificates
82+
- Implement proper authentication and authorization
83+
- Use API gateways and rate limiting
84+
85+
### Local Network Exposure
86+
87+
When listening on `0.0.0.0`, the APIs are accessible to:
88+
- ✅ Your development machine (localhost)
89+
- ✅ Devices on your local network (same Wi-Fi/Ethernet)
90+
- ❌ Internet (blocked by router/firewall)
91+
92+
**Recommendations:**
93+
1. Use trusted networks only (home/office Wi-Fi)
94+
2. Avoid public Wi-Fi while developing
95+
3. Enable firewall rules if concerned about LAN exposure
96+
4. Use VPN for remote development if needed
97+
98+
## Integration with Android IP Detection
99+
100+
The Kestrel `0.0.0.0` configuration works in tandem with the Android MSBuild IP detection:
101+
102+
### Build-Time IP Detection
103+
104+
1. **MSBuild Target** (in `FWH.Mobile.Android.csproj`):
105+
- Detects host IP at build time
106+
- Injects IP into `appsettings.Development.json`
107+
- Example: `"HostIpAddress": "192.168.1.77"`
108+
109+
2. **API Configuration** (in `Program.cs`):
110+
- APIs listen on `0.0.0.0:4748` and `0.0.0.0:4750`
111+
- Accept connections from any local network IP
112+
113+
3. **Mobile App Connection**:
114+
- Loads config with detected IP
115+
- Connects to `http://192.168.1.77:4748`
116+
- API accepts connection because it listens on all interfaces
117+
118+
### Connection Flow
119+
120+
```
121+
┌─────────────────────────────────────────────────────────────┐
122+
│ 1. Developer builds Android app (DEBUG) │
123+
│ MSBuild detects host IP: 192.168.1.77 │
124+
│ Injects into appsettings.Development.json │
125+
└────────────────────┬────────────────────────────────────────┘
126+
127+
┌────────────────────▼────────────────────────────────────────┐
128+
│ 2. APIs start via Aspire AppHost │
129+
│ Location API listens on 0.0.0.0:4748 │
130+
│ Marketing API listens on 0.0.0.0:4750 │
131+
└────────────────────┬────────────────────────────────────────┘
132+
133+
┌────────────────────▼────────────────────────────────────────┐
134+
│ 3. Android app reads configuration │
135+
│ LocationApiBaseUrl: http://192.168.1.77:4748 │
136+
│ MarketingApiBaseUrl: http://192.168.1.77:4750 │
137+
└────────────────────┬────────────────────────────────────────┘
138+
139+
┌────────────────────▼────────────────────────────────────────┐
140+
│ 4. App makes HTTP request to 192.168.1.77:4748 │
141+
│ Request reaches host via local network │
142+
│ API accepts on 0.0.0.0:4748 │
143+
│ Response returned to app │
144+
└─────────────────────────────────────────────────────────────┘
145+
```
146+
147+
## Troubleshooting
148+
149+
### Android App Cannot Connect
150+
151+
**Symptom:**
152+
- App shows connection errors
153+
- Timeout when accessing APIs
154+
155+
**Diagnostic Steps:**
156+
157+
1. **Check API is running:**
158+
```powershell
159+
# Check if process is listening on port
160+
netstat -an | Select-String "4748"
161+
162+
# Should show: 0.0.0.0:4748 LISTENING
163+
```
164+
165+
2. **Verify IP detection:**
166+
```powershell
167+
# Check what IP was detected
168+
cat src\FWH.Mobile\FWH.Mobile.Android\obj\appsettings.Development.processed.json
169+
170+
# Confirm HostIpAddress matches your machine IP
171+
ipconfig
172+
```
173+
174+
3. **Test API accessibility:**
175+
```powershell
176+
# From your development machine
177+
curl http://localhost:4748/health
178+
179+
# From Android device (if adb connected)
180+
adb shell curl http://192.168.1.77:4748/health
181+
```
182+
183+
4. **Check firewall:**
184+
```powershell
185+
# Windows Firewall might block ports
186+
# Add inbound rule for ports 4748, 4749, 4750
187+
188+
# Or temporarily disable for testing
189+
# (Not recommended for production)
190+
```
191+
192+
### API Shows "Address Already in Use"
193+
194+
**Symptom:**
195+
```
196+
System.IO.IOException: Failed to bind to address http://0.0.0.0:4748: address already in use.
197+
```
198+
199+
**Solutions:**
200+
201+
1. **Another process using the port:**
202+
```powershell
203+
# Find process using port 4748
204+
netstat -ano | Select-String "4748"
205+
206+
# Kill the process (find PID from netstat output)
207+
taskkill /PID <pid> /F
208+
```
209+
210+
2. **Previous API instance still running:**
211+
- Stop all running instances
212+
- Rebuild and restart via AppHost
213+
214+
3. **Aspire orchestration conflict:**
215+
- Stop AppHost completely
216+
- Clean solution: `dotnet clean`
217+
- Rebuild: `dotnet build`
218+
- Start AppHost again
219+
220+
### Wrong IP Detected
221+
222+
**Symptom:**
223+
- IP in config doesn't match your network
224+
- App tries to connect to wrong address
225+
226+
**Solutions:**
227+
228+
1. **Multiple network adapters:**
229+
- Check `ipconfig` output
230+
- Identify correct adapter (Wi-Fi vs Ethernet vs VPN)
231+
- Use environment variables to override:
232+
```powershell
233+
$env:LOCATION_API_BASE_URL = "http://192.168.1.77:4748/"
234+
dotnet build
235+
```
236+
237+
2. **VPN interfering:**
238+
- Disconnect VPN during development
239+
- Or use VPN IP if APIs need to be accessed over VPN
240+
241+
3. **Clean and rebuild:**
242+
```powershell
243+
dotnet clean src/FWH.Mobile/FWH.Mobile.Android/FWH.Mobile.Android.csproj
244+
dotnet build src/FWH.Mobile/FWH.Mobile.Android/FWH.Mobile.Android.csproj -c Debug
245+
```
246+
247+
## Testing
248+
249+
### Verify API is listening on 0.0.0.0
250+
251+
```powershell
252+
# Start the AppHost
253+
dotnet run --project src/FWH.AppHost/FWH.AppHost.csproj
254+
255+
# In another terminal, check listening addresses
256+
netstat -an | Select-String "4748|4749|4750"
257+
258+
# Expected output (Windows):
259+
# TCP 0.0.0.0:4748 0.0.0.0:0 LISTENING
260+
# TCP 0.0.0.0:4747 0.0.0.0:0 LISTENING
261+
# TCP 0.0.0.0:4750 0.0.0.0:0 LISTENING
262+
# TCP 0.0.0.0:4749 0.0.0.0:0 LISTENING
263+
```
264+
265+
### Test from Different Sources
266+
267+
```powershell
268+
# From localhost
269+
curl http://localhost:4748/health
270+
271+
# From LAN IP
272+
curl http://192.168.1.77:4748/health
273+
274+
# From Android emulator (using adb)
275+
adb shell curl http://10.0.2.2:4748/health
276+
```
277+
278+
All should return successful health check responses.
279+
280+
## Environment-Specific Behavior
281+
282+
| Environment | Listening Address | Accessible From |
283+
|------------|-------------------|-----------------|
284+
| **Development** | `0.0.0.0` | Localhost, LAN devices, Android emulator |
285+
| **Staging** | Configured via deployment | Typically behind load balancer/gateway |
286+
| **Production** | Configured via deployment | Public internet via reverse proxy/CDN |
287+
288+
## Related Configuration Files
289+
290+
- `src/FWH.Location.Api/Program.cs` - Location API Kestrel config
291+
- `src/FWH.MarketingApi/Program.cs` - Marketing API Kestrel config
292+
- `src/FWH.AppHost/Program.cs` - Aspire orchestration with port mappings
293+
- `src/FWH.Mobile/FWH.Mobile.Android/DetectHostIp.ps1` - IP detection script
294+
- `src/FWH.Mobile/FWH.Mobile.Android/FWH.Mobile.Android.csproj` - MSBuild target
295+
- `src/FWH.Mobile/FWH.Mobile/Configuration/ApiSettings.cs` - Mobile app config model
296+
297+
## References
298+
299+
- [Kestrel web server in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel)
300+
- [Configure endpoints for Kestrel](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints)
301+
- [Android Emulator Networking](https://developer.android.com/studio/run/emulator-networking)
302+
- [.NET Aspire overview](https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview)

0 commit comments

Comments
 (0)