OpenTok.Net
2.34.1.3
See the version list below for details.
dotnet add package OpenTok.Net --version 2.34.1.3
NuGet\Install-Package OpenTok.Net -Version 2.34.1.3
<PackageReference Include="OpenTok.Net" Version="2.34.1.3" />
<PackageVersion Include="OpenTok.Net" Version="2.34.1.3" />
<PackageReference Include="OpenTok.Net" />
paket add OpenTok.Net --version 2.34.1.3
#r "nuget: OpenTok.Net, 2.34.1.3"
#:package OpenTok.Net@2.34.1.3
#addin nuget:?package=OpenTok.Net&version=2.34.1.3
#tool nuget:?package=OpenTok.Net&version=2.34.1.3
OpenTok.Net
One Session/Publisher/Subscriber API over Vonage's (formerly TokBox's) native OpenTok iOS and
Android SDKs, so a .NET or .NET MAUI app writes its calling code once.
dotnet add package OpenTok.Net.Maui
using var session = new OpenTokSession(apiKey, sessionId);
session.Connected += (_, _) => session.Publish(publisher);
session.StreamReceived += (_, e) =>
{
var subscriber = new OpenTokSubscriber(e.Stream);
RemoteView.Source = subscriber; // OpenTokVideoView, from OpenTok.Net.Maui
session.Subscribe(subscriber);
};
session.Connect(token);
No #if IOS, no #if ANDROID, no delegate subclass, no Java listener, no JavaCast, and no
hand-written video-view handler. samples/OpenTok.Sample.Maui is that code as a running app —
compare it with the per-platform samples in the two binding repositories, which are the same flow
written twice.
Packages
| Package | Depends on | Use it when |
|---|---|---|
OpenTok.Net |
OpenTok.Net.iOS / OpenTok.Net.Android, per target framework |
Always — OpenTokSession, OpenTokPublisher, OpenTokSubscriber. |
OpenTok.Net.Maui |
OpenTok.Net + Microsoft.Maui.Controls |
You are building MAUI and want OpenTokVideoView rather than writing a handler. |
Both carry net8.0, net9.0 and net10.0 for iOS and Android — six target frameworks each.
For background blur, background replacement or noise suppression, add the platform transformers
package too — OpenTok.Net.Transformers.iOS and/or OpenTok.Net.Transformers.Android. Neither is
a dependency of anything here, because each costs around 70 MB; OpenTokTransformer is present in
OpenTok.Net either way, and reports that the library is not loaded if you use it without them.
The split keeps MAUI out of the core package's dependency graph: a plain .NET for iOS or .NET for
Android app can take OpenTok.Net on its own and render video however it likes, reaching the
SDK's view through IOpenTokVideoSource.NativeView.
What it covers
Connect, publish, subscribe — and the rest of what both SDKs actually do, all of it cross-platform:
| Session | connect / disconnect, reconnection events, participant join / leave, capabilities from the token |
| Signalling | send to everyone or to one participant, with FromSelf worked out for you |
| Moderation | force-mute all or one stream, lift the mute state, force-disconnect |
| Publisher | mute audio / video, camera position, torch, zoom, audio level, forced-mute notification |
| Subscriber | per-stream audio and video toggles, volume, audio level, captions and translation language |
| Archiving | recording started / stopped |
| Encryption | end-to-end encryption secret |
| Transformers | background blur, background replacement, noise suppression (needs a transformers package) |
| Lifecycle | Pause() / Resume() for backgrounding |
| Calling services | OpenTokAudioSession — hand audio to CallKit or android.telecom |
samples/OpenTok.Sample.Maui demonstrates every row of that table in one page, with no
per-platform code.
Samples
| Sample | Platforms | Shows |
|---|---|---|
OpenTok.Sample.Maui |
both | Everything in the table above, one page, no per-platform code |
OpenTok.Sample.CallKit.iOS |
iOS | CXProvider, answering from the system call UI, audio handed to CallKit |
OpenTok.Sample.Telecom.Android |
Android | ConnectionService + PhoneAccount, and a camera/microphone foreground service |
The two calling-service samples are separate apps rather than branches of the first, deliberately.
CXProvider and ConnectionService share a purpose and nothing else — on iOS the app owns a
provider object and calls it; on Android the framework binds a service and asks the app for
connections, which inverts the flow entirely. The one thing they do share is
OpenTokAudioSession, which both call identically, and that is exactly the part the façade could
honestly unify.
If your Android app can be backgrounded mid-call, you need a foreground service. Since Android
14, a background app is refused camera and microphone access without one carrying the matching
foregroundServiceType — silently: the session stays connected and simply captures nothing, which
the other participant sees as a frozen frame. OpenTok.Sample.Maui includes one
(Platforms/Android/OpenTokCaptureService.cs) precisely because it is not optional.
What the façade does and does not hide
It hides the parts that are accidentally different, and leaves alone the parts that genuinely are.
Hidden. iOS answers an OTError out parameter from every call while Android returns void and
reports through a listener; iOS wants a delegate object per protocol while Android wants either a
listener interface or an event; iOS hands back a UIView and Android an Android.Views.View;
Android needs a Context and iOS does not; Android's Publisher.Builder.Build() needs a
JavaCast and iOS's constructor does not. None of that is a real difference in behaviour, and all
of it is gone.
Not hidden. OpenTokError.Code is the platform's own number and is deliberately not unified —
the two SDKs number their errors differently and Vonage documents no correspondence, so mapping
them would mean inventing one. Log it; do not branch on it across platforms. Permissions are not
requested for you either: when to ask and what to do when refused is a UI decision.
OpenTokConnectionState is the intersection the two platforms can both answer for — iOS exposes six
states, Android exposes none and only fires callbacks — so the façade tracks it rather than asking
the SDK, and it means the same thing on both.
Threading
Events are raised on whichever thread the native SDK used. That is not the UI thread on either platform. Marshal before touching UI:
session.Connected += (_, _) => MainThread.BeginInvokeOnMainThread(() => StatusLabel.Text = "connected");
OpenTokVideoView already does this internally, so setting Source from a callback is safe.
Disposal is not optional
OpenTokPublisher holds the camera and microphone; OpenTokSession holds a live signalling
connection. Neither SDK releases anything because the managed wrapper became unreachable. A
publisher that is never disposed keeps the camera until the process ends — and on Android that
blocks the next publisher the same app creates, which presents as a call screen that works once
and then shows black.
Building locally
The two platform binding packages are restored, not built here. NuGet.config points at sibling
checkouts' artifacts/ directories ahead of nuget.org, so an unreleased binding change is picked up
by packing that repository first; with no siblings present, restore falls through to nuget.org.
./build/BuildNugets.sh
dotnet test tests/OpenTok.Net.PackageTests
No single .NET SDK builds net8, net9 and net10 for either platform, so BuildNugets.sh packs
twice (the installed SDK's band, then a net10 pass from a scratch global.json) and merges the
results — see build/merge-packages.py. Packages are packed in build/packages.tsv order, and each
is merged immediately after its own two passes, because OpenTok.Net.Maui's restore needs an
OpenTok.Net in artifacts/ that already carries every target framework.
See docs/packaging.md for why the pack order matters and how CI versions flow
into the inter-package reference.
Tests
Three suites, two of which run anywhere:
tests/OpenTok.Net.UnitTestschecks the repository's own bookkeeping with nothing built —build/packages.tsvagainst the projects undersrc/, the solution against both, dependency ordering, and the version pins. Including the invariant this repository exists for: both pinned platform packages wrapping the same native SDK generation.tests/OpenTok.Net.PackageTestsinspects the packed.nupkgfiles: an assembly for every target framework, the right platform binding depended on for each one, an exact-version link between the two packages, and the same same-SDK-generation check read back out of the shipped.nuspec.tests/OpenTok.Net.DeviceTestsis a bare app (no MAUI, no test framework) that runs on a simulator or emulator. It contains no#ifat all — the same calls compiled once, drivingOTSessionon iOS andCom.Opentok.Android.Sessionon Android. That is the claim of this repository, executed: it proves the native payload loads and that the state machine, argument validation and disposal semantics behave identically on both runtimes. Nothing connects, publishes or subscribes, so no credentials, no network and no camera are involved.
./build/BuildNugets.sh
dotnet test tests/OpenTok.Net.UnitTests
dotnet test tests/OpenTok.Net.PackageTests
With a simulator or emulator already booted:
./.github/scripts/run-simulator-tests.sh 2.34.1.1 net9.0-ios18.0
OPENTOK_DEVICE_RID=android-arm64 ./.github/scripts/run-emulator-tests.sh 2.34.1.1 net9.0-android35.0
CI
| Workflow | Trigger | What it does |
|---|---|---|
pr.yml |
pull request | Packs both packages as <version>-beta.<pr>.<run>, runs the unit and package tests, builds the sample against them, runs the device checks on an iOS simulator and an Android emulator (net8 and net10 legs in parallel), then publishes the beta to nuget.org. Forked PRs build and test but skip publishing, since they cannot read secrets. |
release.yml |
tag v* |
The same build and tests at the tag's version, publishes to nuget.org, then creates a GitHub release — from docs/release-notes/<version>.md when a curated file exists, otherwise from the commit log since the previous tag. |
Both call the reusable build.yml. The pack and simulator jobs run
on macOS (an -ios target framework needs Xcode to resolve reference assemblies, even for a project
with no native code); the emulator job runs on Linux, because the Android emulator needs KVM.
Publishing uses nuget.org trusted publishing (OIDC, no long-lived API key) against the nuget.org
environment.
Sample
samples/OpenTok.Sample.Maui is a MAUI app for both platforms with no per-platform code: API
key/session/token entry, Connect/Disconnect/Publish, local and remote video, and a status log. It
consumes the packed packages from ./artifacts, so pack first:
./build/BuildNugets.sh
dotnet build samples/OpenTok.Sample.Maui -f net9.0-ios18.0 -p:RuntimeIdentifier=iossimulator-arm64
dotnet build samples/OpenTok.Sample.Maui -f net9.0-android35.0
OpenTok.Net.sln contains the library projects and the tests but not the sample, so
dotnet build OpenTok.Net.sln does not require the MAUI workload.
Requirements
- iOS 15.0+ — OTXCFramework 2.34.1's own floor, raised from 13.0 by that SDK.
- Android API 24+ —
opentok-android-sdk's ownminSdkVersion. - JDK 17+ on
$JAVA_HOMEfor any Android app build —opentok-android-sdk'sclasses.jaris Java 17 class file format. See the Android binding repository's README for the details.
Repository layout
src/, samples/, tests/ and build/ are this project. The Bindings/, NugetPackages/ and
SampleApps/ directories, and the *.sh scripts beside them, are the superseded monorepo —
the iOS and Android bindings moved to their own repositories, and the old OpenTok.Net package was
a nuspec whose .targets copied files into lib/ at consumer build time rather than a real
cross-platform API. They are kept only so the history is readable and can be deleted.
Licence
MIT — see LICENSE. Vonage's own OpenTok SDKs are distributed under their own SDK licence terms, reached transitively through the platform binding packages.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-android34.0 is compatible. net8.0-ios18.0 is compatible. net9.0-android was computed. net9.0-android35.0 is compatible. net9.0-ios was computed. net9.0-ios18.0 is compatible. net10.0-android was computed. net10.0-android36.0 is compatible. net10.0-ios was computed. net10.0-ios26.0 is compatible. |
-
net10.0-android36.0
- OpenTok.Net.Android (= 2.34.1.4)
-
net10.0-ios26.0
- OpenTok.Net.iOS (= 2.34.1.2)
-
net8.0-android34.0
- OpenTok.Net.Android (= 2.34.1.4)
-
net8.0-ios18.0
- OpenTok.Net.iOS (= 2.34.1.2)
-
net9.0-android35.0
- OpenTok.Net.Android (= 2.34.1.4)
-
net9.0-ios18.0
- OpenTok.Net.iOS (= 2.34.1.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on OpenTok.Net:
| Package | Downloads |
|---|---|
|
OpenTok.Net.Maui
OpenTokVideoView, a .NET MAUI view that renders an OpenTok publisher's camera preview or a subscriber's remote video, over the cross-platform OpenTok.Net API. Handles the part every OpenTok MAUI app otherwise writes twice: OpenTok hands its render view out of the SDK rather than taking one in, so the view has to be attached into a container after the fact. Call UseOpenTok() in MauiProgram. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.34.1.4-beta.8.30 | 0 | 7/29/2026 |
| 2.34.1.4-beta.7.24 | 6 | 7/29/2026 |
| 2.34.1.4-beta.6.27 | 0 | 7/29/2026 |
| 2.34.1.4-beta.5.25 | 0 | 7/29/2026 |
| 2.34.1.3 | 71 | 7/28/2026 |
| 2.34.1.3-beta.4.12 | 33 | 7/28/2026 |
| 2.27.1.900-beta.3.4 | 39 | 7/27/2026 |
| 2.27.1.17 | 1,524 | 2/9/2024 |