Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Source/Trackify/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">

<!-- Uno.Resizetizer fills empty attributes from the csproj: Name ← ApplicationId,
Publisher ← "O=" + ApplicationPublisher, Version ← ApplicationDisplayVersion with
ApplicationVersion as the 4th part. For the Microsoft Store, copy Name and Publisher (CN=…) from
Partner Center → Product identity onto this element, and PublisherDisplayName into <Properties>:
values written here win over the generated ones. Leave Version to the build — the release
pipeline sets it from the vX.Y.Z tag, with the 4th part 0 as the Store requires. -->
<Identity />
<Properties />

Expand All @@ -25,7 +31,13 @@
</Application>
</Applications>

<!-- What the packaged app does, so the WinRT Bluetooth APIs are allowed and the Store's "this app
can" list is truthful: the hubs over Bluetooth LE (WindowsLegoService), and Server mode reaching
the Pi backend on the home network or at a remote URL. DeviceCapability must come last. -->
<Capabilities>
<Capability Name="internetClient" />
<Capability Name="privateNetworkClientServer" />
<rescap:Capability Name="runFullTrust" />
<DeviceCapability Name="bluetooth" />
</Capabilities>
</Package>
4 changes: 4 additions & 0 deletions Source/Trackify/Platforms/Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<!-- Server mode (Services/Remote: Refit + SignalR to the CLI backend). .NET for Android only adds
INTERNET by itself to Debug builds (for the debugger), so without this line a Release/Play build
fails every Server-mode request with a socket "permission denied". -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
<!-- allowBackup=false: the store holds device-local hub pairings (BLE ids/MACs of *this* phone's
hubs), which are meaningless once restored onto another device — so keep them off cloud backup.
Expand Down
28 changes: 22 additions & 6 deletions Source/Trackify/Platforms/iOS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
<integer>1</integer>
<integer>2</integer>
</array>
<!-- The binary is arm64-only (armv7 was the template's 32-bit leftover). bluetooth-le mirrors
Android's required bluetooth_le feature; every device that runs iOS 14.2+ has it, so it
excludes no one — but Apple only lets an update ADD a capability that existing users'
devices also have, so it is set from the first upload. -->
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
<string>arm64</string>
<string>bluetooth-le</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
Expand All @@ -34,14 +38,26 @@
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>

<!-- Required to scan for and connect to LEGO Powered Up hubs over Bluetooth LE. -->
<!-- The UI is German only; this tells iOS (and the App Store's language list) so. -->
<key>CFBundleDevelopmentRegion</key>
<string>de</string>

<!-- Required to scan for and connect to LEGO Powered Up hubs over Bluetooth LE. Shown in the
system permission prompt, so it says what happens with the access. The trademark stays
descriptive (with ®) and is not the subject of the sentence. -->
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Trackify verwendet Bluetooth, um LEGO Powered Up Hubs zu finden und zu steuern.</string>
<string>Trackify nutzt Bluetooth, um die Hubs von Zügen (LEGO® Powered Up) in der Nähe zu finden und Fahrt und Licht zu steuern.</string>

<!-- Server mode reaches the Trackify backend on the home network (a Pi), which raises iOS's
local-network prompt; this is its text. App Transport Security keeps its defaults (no
exceptions), mirroring Android's usesCleartextTraffic=false; whether a plain-http backend
is reachable on iOS is still to be checked on a device (docs/store-release.md). -->
<key>NSLocalNetworkUsageDescription</key>
<string>Im Servermodus verbindet sich Trackify mit dem Trackify-Server (zum Beispiel einem Raspberry Pi) im lokalen Netzwerk.</string>

<!--
Adjust this to your application's encryption usage.
<!-- Export compliance: the only encryption is TLS for Server mode, through the OS's own
networking stack (exempt). Declaring it here skips the encryption question on every upload. -->
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
-->
</dict>
</plist>
99 changes: 62 additions & 37 deletions Source/Trackify/Platforms/iOS/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -1,41 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<!-- see https://aka.platform/uno/apple-privacy-manifest for more information -->

<!-- .NET Runtime/BCL -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
<!--
Apple privacy manifest, bundled by Uno.Sdk as PrivacyInfo.xcprivacy (Uno.SingleProject.iOS.targets).
See https://aka.platform.uno/apple-privacy-manifest and
https://developer.apple.com/documentation/bundleresources/privacy-manifest-files

A plist has exactly one root object. The previous version listed the API entries as several
top-level <dict>s with no NSPrivacyAccessedAPITypes key around them; a plist parser keeps just one
of those dicts and finds no NSPrivacyAccessedAPITypes at all, so every required-reason API below
counted as undeclared (App Store Connect warning ITMS-91053).

<!-- NSUserDefaults -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
Trackify collects nothing and tracks no one: the train store (SQLite) and the settings stay on
the device, and Server mode only talks to a backend the user runs and enters themselves.
-->
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<!-- .NET runtime/BCL file APIs, and SQLite (e_sqlite3) stat()-ing its own database file —
both only inside the app container. -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
<!-- .NET runtime: elapsed-time measurement (Stopwatch / Environment.TickCount). -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<!-- .NET runtime: free-space checks before writing files (DriveInfo / statfs). -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
<!-- NSUserDefaults: Uno's ApplicationData.LocalSettings, which keeps the Direct/Server mode and
the backend URL (Services/Remote/ConnectionState) — read and written by this app only. -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
18 changes: 15 additions & 3 deletions Source/Trackify/Trackify.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<!-- Package Publisher -->
<ApplicationPublisher>Trackify</ApplicationPublisher>
<!-- Package Description -->
<Description>Trackify powered by Uno Platform.</Description>
<Description>Züge per Bluetooth steuern und Gleispläne zeichnen.</Description>

<!--
UnoFeatures are used to quickly add and manage features enabled for your app.
Expand All @@ -47,8 +47,20 @@
</UnoFeatures>
</PropertyGroup>

<!-- The app no longer does Bluetooth: train control lives in the CLI on the Raspberry Pi. It
registers a no-op ILegoService (Services/UnsupportedLegoService) so the UI still runs. -->
<!-- Android Release (the AAB for Google Play): .NET SDK 10.0.2xx adds the host RID (win-x64) to
RuntimeIdentifiers whenever PublishTrimmed is on, and restore then looks for a
Microsoft.NETCore.App.Runtime.Mono.win-x64 pack that does not exist (NU1102). The Android
workload opts out of this itself from 36.1.30 on (dotnet/android#10722); this line covers an
older installed workload. Drop it once every build machine runs workload 36.1.30 or newer. -->
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<UseDefaultPublishRuntimeIdentifier>false</UseDefaultPublishRuntimeIdentifier>
</PropertyGroup>

<!-- Bluetooth runs on the device heads: AddTrackifyApplication registers the local ILegoService
transport for android/ios (Plugin.BLE) and windows (WinRT); wasm has none, and desktop only
on Linux (BlueZ, via AddTrackifyInfrastructure). Server
mode (Services/Remote) talks to the CLI backend on a Pi instead. That is why the store
manifests declare Bluetooth and network access. -->

<!-- High-performance logging (source-generated LoggerMessage) with a Serilog backend. -->
<ItemGroup>
Expand Down
Loading
Loading