DatadogNet.Trace.Android 3.12.1.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package DatadogNet.Trace.Android --version 3.12.1.3
                    
NuGet\Install-Package DatadogNet.Trace.Android -Version 3.12.1.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DatadogNet.Trace.Android" Version="3.12.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DatadogNet.Trace.Android" Version="3.12.1.3" />
                    
Directory.Packages.props
<PackageReference Include="DatadogNet.Trace.Android" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DatadogNet.Trace.Android --version 3.12.1.3
                    
#r "nuget: DatadogNet.Trace.Android, 3.12.1.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DatadogNet.Trace.Android@3.12.1.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DatadogNet.Trace.Android&version=3.12.1.3
                    
Install as a Cake Addin
#tool nuget:?package=DatadogNet.Trace.Android&version=3.12.1.3
                    
Install as a Cake Tool

DatadogNet.Android

NuGet release Targets: net8.0 | net9.0 | net10.0 dd-sdk-android 3.12.1 Licence: MIT AND Apache-2.0

.NET for Android and .NET MAUI bindings for the native Datadog Android SDK (dd-sdk-android).

Enable Datadog Real User Monitoring, Logs, Trace, Session Replay, WebView tracking and native crash reporting from C#, in a net8.0-android, net9.0-android or net10.0-android app.

dotnet add package DatadogNet.RUM.Android
using Com.Datadog.Android;
using Com.Datadog.Android.Core.Configuration;
using Com.Datadog.Android.Privacy;
using Com.Datadog.Android.Rum;

var configuration = new Configuration.Builder(
        clientToken: "<CLIENT_TOKEN>", env: "production", variant: "", service: "my-app")
    .UseSite(DatadogSite.Us1)
    .Build();

Datadog.Initialize(context, configuration, TrackingConsent.Granted);
Rum.Enable(new RumConfiguration.Builder("<RUM_APPLICATION_ID>").Build());

Contents


Packages

Thirteen packages, one per dd-sdk-android module. Versions are <dd-sdk-android version>.<binding revision>3.12.1.1 is dd-sdk-android 3.12.1, binding revision 1. The fourth component belongs to this repository and advances when the bindings or packaging change while the native artifacts stay put.

Package Wraps Depends on What it is for
DatadogNet.RUM.Android dd-sdk-android-rum Core, Internal The usual starting point. Real User Monitoring — views, actions, resources, errors, long tasks and mobile vitals.
DatadogNet.Core.Android dd-sdk-android-core Internal SDK initialization, configuration, consent, user and account info. Every feature needs it.
DatadogNet.Internal.Android dd-sdk-android-internal Shared foundation every other module is built on.
DatadogNet.Logs.Android dd-sdk-android-logs Core, Internal Log collection.
DatadogNet.Trace.Android dd-sdk-android-trace Core, Internal, TraceApi, TraceInternal Distributed tracing (APM).
DatadogNet.TraceApi.Android dd-sdk-android-trace-api Core, Internal The tracing contract — IDatadogTracer, IDatadogSpan, IDatadogScope.
DatadogNet.TraceInternal.Android dd-sdk-android-trace-internal Core, Internal, TraceApi The tracing engine. Ships the module; binds nothing.
DatadogNet.SessionReplay.Android dd-sdk-android-session-replay Core, Internal Session Replay. Requires RUM.
DatadogNet.SessionReplayMaterial.Android dd-sdk-android-session-replay-material SessionReplay Records Material Components faithfully.
DatadogNet.SessionReplayCompose.Android dd-sdk-android-session-replay-compose SessionReplay, Internal Records Jetpack Compose content. net9/net10 only.
DatadogNet.Ndk.Android dd-sdk-android-ndk Core, Internal Native (NDK) crash capture. Opt-in.
DatadogNet.WebView.Android dd-sdk-android-webview Core, Internal Bridges RUM/Logs out of a WebView. Opt-in.
DatadogNet.OkHttp.Android dd-sdk-android-okhttp Internal, RUM, Trace Reports outgoing HTTP calls as RUM resources and propagates tracing headers.

Most apps need one or two lines:

<PackageReference Include="DatadogNet.RUM.Android" Version="3.12.1.3" />
<PackageReference Include="DatadogNet.Logs.Android" Version="3.12.1.3" />

DatadogNet.Core.Android arrives transitively — you rarely reference it directly, though you will using Com.Datadog.Android; to reach Datadog.Initialize.

There is no façade package. The iOS bindings have DatadogNet.Objc.iOS, which re-exports the whole SDK, because dd-sdk-ios ships a DatadogObjc framework that does exactly that. dd-sdk-android has no equivalent, and inventing one would mean every app paying for Session Replay and NDK crash reporting to use RUM. Reference the features you actually enable.

Target frameworks: net8.0-android34.0, net9.0-android35.0, net10.0-android36.0 — except DatadogNet.SessionReplayCompose.Android, which is net9/net10 only. Compose's last net8 build pins an AndroidX SavedState old enough to collide with what a MAUI app resolves, and holding the whole repository back to match would have broken MAUI consumers of all thirteen packages to keep net8 for the one that needs Compose.

Minimum API level: 23 (Android 6.0) — dd-sdk-android 3.x raised its own floor from 21.

net8 sunset. The net8 head is already past its platform support window — the net8 mobile workloads left support with MAUI 8 on 14 May 2025 — and ships for the apps that still target it, with the emulator checks run against it. It is also what holds the whole AndroidX/Kotlin dependency set below current (see Directory.Build.props). So the trade-off does not persist by inertia: the net8 head is dropped, and the held-back versions unpinned, in the first release after .NET 8 itself leaves support on 10 November 2026.

MAUI version: build with MAUI 10. See Building locally.


Installing

<ItemGroup>
  <PackageReference Include="DatadogNet.RUM.Android" Version="3.12.1.3" />
</ItemGroup>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">23</SupportedOSPlatformVersion>

The packages are Android-only. In a multi-targeted MAUI project, guard the reference so an iOS or Windows head does not try to restore them:

<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
  <PackageReference Include="DatadogNet.RUM.Android" Version="3.12.1.3" />
</ItemGroup>

Usage

The C# names are the Kotlin/Java ones projected into C#, so com.datadog.android.rum.Rum becomes Com.Datadog.Android.Rum.Rum and enable(...) becomes Enable(...).

samples/DatadogNet.Android.Example is a working MAUI app that does all of the below; Datadog.cs is the setup in one file.

Initialize

Once, as early as possible. In MAUI that means MauiProgram.CreateMauiApp, or better still your Application subclass — crash reporting only covers what happens after it is enabled, and startup crashes are the ones worth catching.

using Com.Datadog.Android;
using Com.Datadog.Android.Core.Configuration;
using Com.Datadog.Android.Privacy;

var configuration = new Configuration.Builder(
        clientToken: "<CLIENT_TOKEN>", env: "production", variant: "", service: "my-app")
    .UseSite(DatadogSite.Us1)          // Us1, Us3, Us5, Eu1, Ap1, Ap2, Uk1, Us1Fed, Us2Fed
    .SetBatchSize(BatchSize.Medium)
    .SetUploadFrequency(UploadFrequency.Average)
    .Build();

Datadog.Initialize(context, configuration, TrackingConsent.Granted);
Datadog.SetVerbosity((int)Android.Util.LogPriority.Warn);   // SDK problems to logcat

Configuration.Builder takes all four arguments — Kotlin's defaults for variant and service do not survive into C#, so pass "" and your service name explicitly.

RUM

using Com.Datadog.Android.Rum;
using Com.Datadog.Android.Rum.Tracking;

var rum = new RumConfiguration.Builder("<RUM_APPLICATION_ID>")
    .SetSessionSampleRate(100f)
    .TrackUserInteractions()
    .UseViewTrackingStrategy(new ActivityViewTrackingStrategy(true))
    .Build();

Rum.Enable(rum);

TrackUserInteractions(), not TrackInteractions(). Datadog's own documentation still shows the latter; it does not exist in 3.x.

MAUI renders every page into a single Activity, so ActivityViewTrackingStrategy reports one view for the whole app. Report pages yourself instead:

var monitor = GlobalRumMonitor.Get();

using (monitor.StartView("checkout", "Checkout"))
{
    monitor.AddAction(RumActionType.Tap, "pay", new Dictionary<string, object?>
    {
        ["cart.total"] = 42.50m,
    });

    try { /* ... */ }
    catch (Exception exception) { monitor.AddError(exception); }
}

StartView, AddAction and AddError above are from the convenience API.

Logs

using Com.Datadog.Android.Log;

Logs.Enable(new LogsConfiguration.Builder().Build());

var logger = new Logger.Builder()
    .SetName("app")
    .SetBundleWithRumEnabled(true)
    .Build();

logger.Log(LogLevel.Info, "user signed in");
logger.Log(LogLevel.Error, "payment failed", exception, new Dictionary<string, object?>
{
    ["order.id"] = orderId,
});

Trace

using Com.Datadog.Android.Trace;

Trace.Enable(new TraceConfiguration.Builder().Build());

GlobalDatadogTracer.RegisterIfAbsent(DatadogTracing.NewTracerBuilder().Build());

AndroidTracer is gone. dd-sdk-android 3.0 removed it along with the OpenTracing dependency. DatadogTracing.NewTracerBuilder() is the replacement. Note also that GlobalDatadogTracer.Get and RegisterIfAbsent are static while Clear and GetOrNull are not — the latter are GlobalDatadogTracer.Instance.Clear().

Session Replay

using Com.Datadog.Android.Sessionreplay;

SessionReplay.Enable(new SessionReplayConfiguration.Builder(100f)
    .SetTextAndInputPrivacy(TextAndInputPrivacy.MaskAll)
    .SetImagePrivacy(ImagePrivacy.MaskAll)
    .SetTouchPrivacy(TouchPrivacy.Hide)
    .Build());

Requires RUM. The three privacy levels decide what is redacted on the device, before anything is uploaded. Loosen them deliberately. The older single SessionReplayPrivacy is deprecated upstream and still bound, but prefer the three.

Enable is static; StartRecording and StopRecording are not — they are SessionReplay.Instance.StartRecording(sdkCore). That asymmetry is upstream's, not the binding's.

Add DatadogNet.SessionReplayMaterial.Android or DatadogNet.SessionReplayCompose.Android and register the extension when your app draws Material or Compose content:

.AddExtensionSupport(new MaterialExtensionSupport())

Native crash reporting

Add DatadogNet.Ndk.Android, then enable it after initializing the SDK:

using Com.Datadog.Android.Ndk;

NdkCrashReports.Enable();

Crashes are reported on the next launch, as RUM errors and logs. Upload your native symbols to Datadog for symbolication. Like DatadogNet.WebView.Android, the package ships consumer R8 keep-rules for its JNI-only entry point, so Release shrinking cannot strip NdkCrashReports.

Network instrumentation

Add DatadogNet.OkHttp.Android. This is what makes HTTP calls visible in RUM:

using Com.Datadog.Android.Okhttp;

var client = new OkHttpClient.Builder()
    .AddInterceptor(new DatadogInterceptor.Builder(hosts).Build())
    .EventListenerFactory(new DatadogEventListener.Factory())
    .Build();

HttpClient in .NET does not route through OkHttp unless you configure AndroidMessageHandler, so a MAUI app using HttpClient will not report resources automatically.

WebView tracking

using Com.Datadog.Android.Webview;

WebViewTracking.Enable(webView, new List<string> { "example.com" });

The package ships consumer R8/ProGuard keep-rules (under buildTransitive/), because WebViewTracking is reached from .NET through JNI alone and a shrunk Release build would otherwise remove it and throw ClassNotFoundException at runtime. Nothing to configure — NuGet imports them into the consuming app automatically.

Datadog.SetUserInfo(userId: "user-123", name: "Ada Lovelace", email: "ada@example.com");
Datadog.SetTrackingConsent(TrackingConsent.Pending);

Pending collects events but holds them on the device until consent is granted or refused — which is what a prompt-on-first-launch flow wants.


Convenience API

The generated binding is a faithful projection of Kotlin, which makes some things clumsy in C#. Each package adds a small hand-written layer over it. The generated members are all still there; nothing is hidden or renamed.

Instead of Write
monitor.StartView("k", "Name", new Dictionary<string, Java.Lang.Object>())StopView using (monitor.StartView("k", "Name"))
hand-wrapping every value in Java.Lang.Object new Dictionary<string, object?> { ["k"] = 42 } on any overload below
monitor.AddAction(type, name, javaMap) monitor.AddAction(type, name, attributes?)
monitor.AddError(message, source, throwable, javaMap) with a Throwable you do not have monitor.AddError(exception)
logger.Log(priority, message, throwable, javaMap) logger.Log(level, message, exception?, attributes?)

The view scope is the one worth adopting everywhere: the raw API is a StartView / StopView pair matched by key, and a view left open by an early return or an exception captures every later action and error in the session.

Attribute values may be strings, any numeric type, bool, DateTime, DateTimeOffset, Guid, enums, Java.Lang.Objects, arrays and nested dictionaries. Anything else throws ArgumentException rather than being silently dropped.

IntelliSense on the generated tier is bare, and cannot currently be otherwise. The binding toolchain imports API documentation from a -sources.jar of Java sources (@(JavaSourceJar)); dd-sdk-android is Kotlin, and its sources jars contain only .kt files, which the importer does not parse. The convenience layer above is fully documented; for the raw surface the C# names map 1:1 onto the Kotlin ones, so upstream's own reference is the documentation.


What is not bound

Three groups of members are deliberately absent, each for a reason recorded next to the rule that removes it in the relevant Transforms/Metadata.xml:

  • Session Replay wireframe mappers (...recorder.mapper, 28 types). The hierarchy is generic and its single member erases to map(Object, …), which the generator cannot bind. The types still ship in the .aar and still run, so recording is unaffected — including through the Material and Compose extensions. What you cannot do is author a custom mapper in C#.
  • dd-sdk-android-trace-internal's entire surface. It is the dd-trace-java engine vendored under com.datadog.trace.**; the tracing API you call is com.datadog.android.trace.*, in Trace and TraceApi. The package ships the module without binding it.
  • A handful of internal typesEvictingQueue, SessionRebasedSampler, OkHttpRequestInfoBuilder — plus the ExecutorService members of FlushableExecutorService and the abstract build() on TracingInterceptor.BaseBuilder. All are generator failures on erased generics or covariant returns, and none is reachable from a documented API.

Kotlin constructs that do not project into C# at all are a property of the language boundary, not of these bindings: extension functions (Session Replay's View.setSessionReplayHidden, the RUM resource helpers, everything in the coroutine and Rx integrations) land on synthetic …Kt classes, and inline functions taking lambdas are not callable. Default parameter values do not exist in C#; where upstream marked a member @JvmOverloads you get the arity ladder, and where it did not, you must pass every argument.


How this repository works

Maven Central: com.datadoghq:dd-sdk-android-*:3.12.1
        │  @(AndroidMavenLibrary) — resolves the .aar and its .pom, cached under
        │  ~/.cache/dotnet-android/MavenCacheDirectory
        ▼
   src/DatadogNet.<Package>.Android/ — binding project + committed Transforms/Metadata.xml
        │  build/BuildNugets.sh — pack twice (net9 band, net10 band), then merge
        ▼
   artifacts/*.nupkg  ──►  nuget.org

Nothing is committed and nothing is compiled from source. There is no fetch script: the .NET Android SDK resolves each module from Maven Central, and — because it reads the .pom too — fails the build when an .aar links against Java types that no referenced package provides. That check is why this repository has no libs/ directory and why a missing Java dependency is a build error here rather than a NoClassDefFoundError in somebody's app.

That check is about completeness; authenticity is pinned separately. Every artifact this repository resolves has a SHA-256 recorded in build/maven-checksums.txt, and the VerifyDatadogMavenArtifactHashes target checks the bytes actually resolved — on both the @(AndroidMavenLibrary) path and the direct-download fallback — against it on every build. A hash that changes for an unchanged version fails the build instead of shipping; build/UpdateMavenChecksums.sh regenerates the pins after a version bump.

Why the two-pass build. Each .NET SDK's Android workload ships reference packs for the current target framework and the previous one — the .NET 9 band builds net8 + net9, the .NET 10 band builds net9 + net10. No single SDK builds all three, so BuildNugets.sh packs twice and merge-packages.py grafts the net10 assets into the net9 packages, carrying the dependency group across with them.

Four Java dependencies have no .NET binding and are embedded as plain Java rather than left to fail at runtime: Kronos (Core), JCTools and RE2/J (TraceApi), and androidx.metrics (RUM). Each is embedded in exactly one package — the same classes contributed twice would be dexed twice and fail the consuming app's build.

Layout

Path What
src/DatadogNet.*.Android/ One binding project per module. Transforms/Metadata.xml is committed and explains every rule.
src/Datadog.Binding.props Everything the thirteen projects share, so each .csproj is its identity and its dependencies.
src/DatadogNet.*/Additions/ The hand-written convenience API.
build/packages.tsv The package set. The build script, both workflows and the tests all read it.
build/ Pack and merge scripts.
tests/DatadogNet.Android.PackageTests/ Asserts the shape of the packed .nupkgs.
tests/DatadogNet.Android.DeviceTests/ An Android app that consumes the packed packages and drives the real SDK on an emulator.
samples/DatadogNet.Android.Example/ A MAUI app doing the same, the way an app would.

The tests consume the packed .nupkgs from artifacts/ rather than referencing the projects, so they exercise what actually gets published — including the inter-package dependencies, which a ProjectReference would bypass entirely.

DatadogNet.sln deliberately contains the binding projects and the tests but not the sample, so dotnet build DatadogNet.sln does not require the MAUI workload.


Building locally

Requires the .NET 9 and .NET 10 SDKs with the android workload, a JDK, and the Android SDK with platforms 34, 35 and 36.

./build/BuildNugets.sh          # packs all thirteen into artifacts/
dotnet test tests/DatadogNet.Android.PackageTests

Run the on-emulator smoke tests against the packed packages, with an emulator already booted:

./.github/scripts/run-emulator-tests.sh 3.12.1.3 net9.0-android35.0

Build and run the sample:

cd /tmp && dotnet new globaljson --sdk-version 10.0.301 --force
dotnet build <repo>/samples/DatadogNet.Android.Example/DatadogNet.Android.Example.csproj -t:Run

The sample targets net10.0-android36.0 and needs the .NET 10 SDK, which this repository's global.json does not select — hence the scratch directory. That is a constraint on the MAUI version you build the sample with, not on what the packages support: MAUI 9 cannot build against the AndroidX generation these packages depend on, and it is an SDK defect rather than anything the bindings do. A plain MAUI 9 app with nothing but Xamarin.AndroidX.AppCompat 1.7.1.1 added fails the same way, with no Datadog package present.


Upgrading the Datadog SDK

  1. Bump DatadogNativeVersion in Directory.Build.props and reset DatadogBindingRevision to 1.

  2. ./build/UpdateMavenChecksums.sh — re-pins every artifact's SHA-256 for the new version. Review the diff: only artifacts whose version changed should have a changed hash.

  3. ./build/BuildNugets.sh — every module is resolved fresh from Maven Central, and verified against the pins from step 2.

  4. Re-derive the dependencies — now scripted: build/verify-transitive-deps.py checks every module's .module runtime dependencies against what the projects declare, and the ignore list against the .pom pollution it neutralises. CI runs it on every build, so a dependency upstream adds (or an ignore entry it retires) is a named failing coordinate rather than a silent gap. To spelunk one module by hand, read the Gradle module metadata, not the .pom:

    curl -s https://repo1.maven.org/maven2/com/datadoghq/dd-sdk-android-core/3.13.0/dd-sdk-android-core-3.13.0.module \
      | python3 -c "import json,sys; [print(d['group']+':'+d['module'], d['version']['requires']) for v in json.load(sys.stdin)['variants'] if v['name']=='releaseVariantReleaseRuntimePublication' for d in v.get('dependencies',[])]"
    

    The .pom is wrong: Gradle flattens the test-fixtures variant into it, so it lists JUnit, Mockito, AssertJ, Elmyr, kotlin-reflect and a dd-sdk-android.tools:unit:unspecified that resolves nowhere. Those are neutralised by the @(AndroidIgnoredJavaDependency) block in src/Datadog.Binding.props; check that list still matches after an upgrade, because dropping an entry upstream stops shipping is how a real missing dependency gets silently ignored.

  5. Re-check each Transforms/Metadata.xml. A removal rule that no longer matches anything becomes a BG8A00 warning rather than an error, so a rule that upstream has fixed will linger silently.

  6. Run both test suites.

If Datadog adds or removes a module, add or remove a row in build/packages.tsv and the matching project — the build script, the workflows and the package tests all follow from it.


Releasing

Tag it. v3.12.1.3 builds, tests, publishes all thirteen packages to nuget.org via trusted publishing, and creates a GitHub release. The tag drives which native SDK is bound, so an older line can be released by tagging it.

Pull requests publish a -beta.<pr>.<run> prerelease of the whole set.

Both run the same build.yml: pack, package tests, and the emulator smoke tests. Pull requests additionally compile the MAUI sample against the packed packages; releases do not, since the commit being tagged has already been through that check and it would otherwise put a MAUI workload install between the packages being built and being published.

Curated notes in docs/release-notes/<version>.md replace the generated commit list when present.


Troubleshooting

Nothing appears in Datadog. Check UseSite matches your organisation's region — this is the most common cause. Call Datadog.SetVerbosity((int)LogPriority.Verbose) to see the SDK's own diagnostics in logcat.

NoClassDefFoundError at runtime. A Java dependency did not make it into the app. Usually a partially restored package; clear the cached copies and restore again: rm -rf ~/.nuget/packages/datadognet.*. If it happens only in Release and names a Datadog class, R8 shrank it out: the WebView and Ndk packages ship keep-rules for their JNI-only entry points, so update them first, and add a -keep for anything else you reach only through reflection.

Duplicate class when building the app. Two packages are contributing the same Java classes. The four embedded third-party libraries are each owned by exactly one package for this reason — if you added a PackageReference for one of them yourself, remove it.

XA4241/XA4242 when building this repository. Java dependency verification found an unsatisfied dependency. Add the matching binding PackageReference to the project; the error names the Microsoft-maintained package when one exists.

'Trace' is an ambiguous reference. Com.Datadog.Android.Trace.Trace collides with Android.OS.Trace. Alias it: using DdTrace = Com.Datadog.Android.Trace.Trace;.

'Logs' does not exist in the namespace 'DatadogNet.Logs' — or the same for Trace or SessionReplay. Your app's own namespace starts with DatadogNet., and C# resolves a bare name outward through enclosing namespaces before looking at using directives. The bindings avoid creating DatadogNet.<Feature> namespaces for exactly this reason, so if you see it, something in your solution declares one. Rename it or fully qualify the call.

RUM records one view for the whole app. Expected in MAUI: every page renders into a single Activity. Report views yourself with monitor.StartView(...).

HTTP calls do not appear as RUM resources. HttpClient does not route through OkHttp by default. Use the OkHttp client directly, or configure AndroidMessageHandler.


Licence

The binding code in this repository is MIT. The native artifacts the packages ship are built and published by Datadog and are Apache-2.0, as are Kronos, JCTools and androidx.metrics; RE2/J is under the Go licence. Every package declares MIT AND Apache-2.0 and carries the MIT text, the Apache-2.0 text and Datadog's NOTICE under licenses/.

Product Compatible and additional computed target framework versions.
.NET net8.0-android34.0 is compatible.  net9.0-android was computed.  net9.0-android35.0 is compatible.  net10.0-android was computed.  net10.0-android36.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on DatadogNet.Trace.Android:

Package Downloads
DatadogNet

One cross-platform Datadog API for .NET MAUI: RUM, Logs, Trace and Session Replay on Android, iOS and Mac Catalyst from shared code, over the native dd-sdk-android and dd-sdk-ios bindings. Restores and no-ops on Windows, so a multi-headed app needs no conditionals.

DatadogNet.OkHttp.Android

.NET for Android / .NET MAUI bindings for the native Datadog Android SDK's dd-sdk-android-okhttp module: DatadogInterceptor, TracingInterceptor and DatadogEventListener, which report outgoing HTTP calls as RUM resources and propagate distributed-tracing headers to your backend. Built against dd-sdk-android 3.12.1, which compiles against OkHttp 4.12.0. This is the integration that makes network requests visible; without it RUM records screens but not the calls they make.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.12.1.4 77 7/26/2026
3.12.1.4-beta.11.19 26 7/30/2026
3.12.1.4-beta.10.17 28 7/30/2026
3.12.1.4-beta.9.16 28 7/29/2026
3.12.1.4-beta.8.15 31 7/28/2026
3.12.1.4-beta.7.14 45 7/26/2026
3.12.1.3 153 7/24/2026
3.12.1.3-beta.6.13 56 7/24/2026
3.12.1.3-beta.5.12 45 7/24/2026
3.12.1.2 101 7/23/2026
3.12.1.2-beta.4.10 41 7/23/2026
3.12.1.2-beta.4.9 40 7/23/2026
3.12.1.2-beta.4.8 44 7/23/2026
3.12.1.1 93 7/23/2026
3.12.1.1-beta.2.5 45 7/23/2026
2.26.3.2 84 7/23/2026
2.26.3.1 98 7/23/2026
2.26.3.1-beta.3.6 45 7/23/2026

## What's changed

Binding-only release. The native SDK is unchanged — still
[dd-sdk-android 3.12.1](https://github.com/DataDog/dd-sdk-android/releases/tag/3.12.1) — and so
are the package ids, namespaces and API. The fourth component advances for the changes below,
which came out of a full ergonomics review of the four DatadogNet repositories.

## Release builds stop losing Datadog classes to R8

`DatadogNet.WebView.Android` and `DatadogNet.Ndk.Android` now ship consumer R8/ProGuard
keep-rules under `buildTransitive/`, imported into the consuming app automatically. Their entry
points — `WebViewTracking`, `NdkCrashReports` — are reached from .NET through JNI alone, which a
Java shrinker cannot see, so a shrunk Release build removed them and `Enable` threw
`ClassNotFoundException` at runtime from a package that was correctly installed. If you carried a
manual `-keep` for either, or disabled shrinking to work around this, you can remove the
workaround. New package-layout tests assert the rules stay in the packages.

## Supply-chain pins for every Maven artifact

Java dependency verification always checked *completeness* — that every linked Java type is
provided by some referenced package. It said nothing about *authenticity*. Now every artifact
this repository resolves has a SHA-256 pinned in `build/maven-checksums.txt` (18 pins: the
thirteen dd-sdk modules plus Kronos, JCTools, RE2/J and androidx.metrics), and the
`VerifyDatadogMavenArtifactHashes` target checks the bytes actually resolved — on both the
`@(AndroidMavenLibrary)` path and the direct-download fallback — on every build. A hash that
changes for an unchanged version fails the build instead of shipping.
`build/UpdateMavenChecksums.sh` regenerates the pins on upgrade.

## The upgrade ritual's sharpest steps are now a script

`build/verify-transitive-deps.py` re-derives every module's real runtime dependencies from its
Gradle `.module` metadata — the `.pom` is polluted by the flattened test-fixtures variant — and
checks them against what the projects declare, and checks the `@(AndroidIgnoredJavaDependency)`
list against the `.pom` pollution it neutralises. CI runs it before packing, so a dependency
upstream adds is a named failing coordinate rather than a `NoClassDefFoundError` in somebody's
app, and an ignore entry upstream retires is a warning rather than a place a real missing
dependency can hide.

## Smaller improvements

- **nuget.org now shows these notes**: `docs/release-notes/<version>.md` is packed into
 `PackageReleaseNotes`, with the releases page as fallback.
- **README versions can no longer go stale silently** — the install snippets sat at `3.12.1.1`
 while `3.12.1.2` shipped; `build/CheckReadmeVersions.sh` now fails CI on drift.
- The jctools/re2j versions, previously hand-synchronised across three projects, live once in
 `Directory.Build.props`.
- The README states plainly why the generated tier has no IntelliSense (upstream's sources jars
 are Kotlin-only, and the binding toolchain's Javadoc import parses Java sources) and where the
 documentation therefore lives.

## net8 sunset

Stated policy, so the trade-off does not persist by inertia: the `net8.0-android34.0` head —
past its platform support window since MAUI 8 left support on 14 May 2025, and the reason the
whole AndroidX/Kotlin dependency set is held below current — is dropped, and the held-back
versions unpinned, in the first release after .NET 8 itself leaves support on
**10 November 2026**.

## Upgrading from 3.12.1.2

Nothing to change. A Release build with R8 enabled may now keep classes that previously
vanished — which is the fix, not a regression.