-
-
Notifications
You must be signed in to change notification settings - Fork 55
Platform prerequisites
Everything each platform needs beyond dotnet add package.
Three of these fail silently — no exception, no log line, or an error that does not mention WebRTCme. They are first, because they account for most of the time people lose here.
| Platform | Symptom if you miss it | |
|---|---|---|
| 1 | Windows | The app hangs before Main. No error, nothing in any log |
| 2 | MAUI, all four |
error NU1605 naming Microsoft.Maui.Controls, not WebRTCme |
| 3 | Blazor | Nothing works. No message |
Not a defect, and not fixable in the package — a prerequisite that has to be stated.
WebRTCme is a MAUI library on Windows by design, so its package depends on
Microsoft.Maui.Controls, which brings the Windows App SDK, which injects a bootstrapper into the
module constructor of anything that references the package.
That bootstrapper looks for a matching Windows App Runtime framework package. When it cannot find one it does not fail — it blocks:
[Native Frames]
Microsoft.WindowsAppRuntime.Bootstrap.Net!...Bootstrap.TryInitialize(...)
...BootstrapCS.AutoInitialize.AccessWindowsAppSDK()
...WindowsAppRuntime.Common.AutoInitialize.InitializeWindowsAppSDK()
<Module>..cctor()
Your app stops before Main, having written nothing. A missing library would have thrown by
name — this does not throw at all, which is what makes it so hard to recognise.
| A development machine | Yes. Visual Studio's MAUI workload installs it — which is why you will not see this locally |
| A clean Windows machine | No. It is not part of Windows |
| A packaged (MSIX) app | Yes. The dependency is declared and the installer or Store supplies it |
An unpackaged app — what plain dotnet publish produces |
No |
Carry the runtime inside your app:
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
</PropertyGroup>That is the recommendation for unpackaged apps: it costs some size and nothing else, and it cannot be forgotten at deployment time.
The alternative is to ship
WindowsAppRuntimeInstall.exe
alongside and require users to run it, or to declare it as a documented prerequisite. Both work;
both rely on somebody remembering.
Packaged apps need none of this.
How this was found, because the path is worth knowing if you ever meet a silent hang. The device test suite ran in two seconds on real Windows and hung on a CI runner for six hours, until the job limit stopped it. Six theories were wrong before a stack dump settled it. What worked was a module initializer writing to stderr — xUnit captures stdout and replays it only when a test ends, so a test that never ends prints nothing — and then
dotnet-stack reporton the live process.
Your restore fails without this, and the error does not mention WebRTCme:
error NU1605: Detected package downgrade: Microsoft.Maui.Controls from 10.0.101 to 10.0.20
YourApp -> WebRTCme 26.9.21 -> Microsoft.Maui.Controls (>= 10.0.101)
YourApp -> Microsoft.Maui.Controls (>= 10.0.20)
The packages depend on Microsoft.Maui.Controls 10.0.101. Your MAUI workload's own implicit
reference is whatever that workload bundles — 10.0.20 for a current SDK — and NuGet calls the
difference a downgrade and refuses the restore.
Name the versions yourself, exactly as NU1605 instructs:
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) != ''">
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.101" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.101" />
</ItemGroup>It is not optional and it is not discoverable until the restore fails. Keep it in step when you upgrade WebRTCme — Releases states the version each release wants, and a pin left behind produces the same NU1605 in the opposite direction.
This applies to MAUI target frameworks only. A Blazor WebAssembly app never sees it.
The Blazor binding is JSInterop over the browser's own WebRTC, and the JavaScript half ships as a static web asset. Without the tag, nothing works and nothing says why.
In wwwroot/index.html, before _framework/blazor.webassembly.js:
<script src="_content/WebRTCme/JsInterop.js"></script>The path changed in this release. It used to be
_content/WebRTCme.Bindings.Blazor/JsInterop.js, and that package no longer exists. See
Releases.
Blazor WebAssembly only. Blazor Server and Blazor Hybrid are not supported — see What works where.
| .NET SDK |
10.0.400 or later. dotnet --version
|
| MAUI workload |
dotnet workload install maui — for MAUI apps only |
A Blazor WebAssembly app needs neither the MAUI workload nor anything else on this page beyond the script tag.
| Platform | Target framework | Minimum OS |
|---|---|---|
| Blazor WebAssembly | net10.0 |
any current browser |
| Android | net10.0-android |
API 28 (Android 9) |
| iOS | net10.0-ios |
iOS 15.0 |
| Mac Catalyst | net10.0-maccatalyst |
macOS 12 (Catalyst 15.0) |
| Windows | net10.0-windows10.0.22621.0 |
Windows 10 22H2 (build 22621) |
Asking for less than a floor gets you an error telling you to raise it.
Not needed for Hello world, which uses a data channel and touches no hardware.
Needed the moment you call GetUserMedia or GetDisplayMedia.
Platforms/Android/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />Screen sharing needs more. Android requires a foreground service of type
mediaProjection, and from Android 13 a runtime POST_NOTIFICATIONS permission, because a
foreground service must post a notification. The library provides the consent activity and the
service itself — the consent flow belongs to the library rather than your activity, so you do not
have to override OnActivityResult and forward the result.
Platforms/iOS/Info.plist and Platforms/MacCatalyst/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Allow video camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Allow microphone access</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Local network access is required to reach the signalling server and connect calls.</string>NSLocalNetworkUsageDescription matters more than it looks: without it, a call to a signalling
server on the same LAN fails in a way that does not obviously point at permissions.
Mac Catalyst wants a real signing identity, not ad-hoc. macOS ties camera, microphone and Screen Recording grants to a stable code identity, and an ad-hoc signature with no team gives it nothing to hold on to — a grant can evaporate on relaunch and every rebuild invalidates it. That looks like three unrelated bugs: camera permission re-prompting after each build, Screen Recording refusing after being granted, and the app appearing to hang while a permission call never returns. One cause.
Windows needs nothing declared. Blazor gets the browser's own permission prompt, and requires a
secure context — HTTPS, or localhost. getUserMedia does not exist on a plain-HTTP page
served from anything else.
| Android | Android SDK and a JDK. The JDK must be recent enough to read libwebrtc.aar
|
| iOS | A Mac, Xcode, and a signing identity |
| Mac Catalyst | A Mac |
| Windows | Nothing extra |
| Blazor | Nothing extra |
Building is not deploying. Every slice — including iOS and Mac Catalyst — builds with plain
dotnet build on Windows. Only linking and deploying an app for those two needs a Mac.
Troubleshooting maps symptoms to causes, including all three of the silent failures above.
Start here
The stack
- WebRTCnative
- Bindings
- The unified API
- Middleware
- Connection
- · Signaling (mesh)
- · MediaSoup (SFU)
- Demo apps
Reference
When it breaks