Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
155000 stories
·
33 followers

Scott & Mark Learn To...Double-Check References

1 Share
From: Scott Hanselman
Views: 0

In this episode, Scott Hanselman and Mark Russinovich dive into a growing issue in AI-driven research: hallucinated references in academic papers. After scanning thousands of conference submissions, Mark uncovers widespread citation inaccuracies, sparking a broader conversation about accountability, cognitive surrender, and the risks of over-relying on AI tools. They explore where AI adds value versus where it erodes critical thinking, from academic writing to everyday coding and content creation. The conversation shifts into the realities of vibe coding, the tradeoffs of speed versus quality, and what it means to maintain taste and expertise in an AI-accelerated world, ultimately asking: if AI lowers the barrier to create, does it also lower the standard?

Listen to other episodes at https://scottandmarklearn.to

Discover other Microsoft podcasts at https://microsoft.com/podcasts


Code: N6LPHTWYWYEG33VE

Read the whole story
alvinashcraft
12 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Episode 43 : Music Tech Pioneers VIII : Manfred Rürup : Steinberg : The Early Years !

1 Share

Music Tech Pioneers VIII : Manfred Rürup  : Steinberg : The Early Years !

Hosted by Vin Curigliano of AAVIM Technology, I am joined by guest co-host Pete Brown of Microsoft and special guest Manfred Rürup, who is the Co-Founder and Ex CEO of Steinberg.

We cover Manfred's early history with music and technology , and how that lead to a Professional Recording and Performing Career throughout the 70's and early 80's, before crossing paths with Charlie Steinberg in the early 80's, and founding Steinberg Research.

We discuss Manfred's professional music career across multiple bands and performing artists, sharing some adventures that were encountered navigating those heady days of recording and touring during that era, cover some of the albums and music styles explored , gear used, etc, from early Prog Rock, Fusion, Experimental, to German New Wave.

We cover the early pioneering days of being one of the first to explore computer based sequencing on less than ideal computer hardware, the evolution of the sequencing packages that paved the way to the innovations that the team visualised and brought to the ground breaking and game changing release of Cubase in 1989, that became the blueprint for the way DAW workflow environments were approached and implemented across most if not all DAW's that followed.

We discuss the landmark releases of Cubase, the initial adventures of introducing digital audio to the Cubase sequencing environment, the preliminary excursions using initially 3rd party audio hardware, then moving to the first native version on Atari Falcon, and the eventual evolution of VST ( Virtual Studio Technology ), which launched the native DAW era on Mac and Windows, and created a whole new industry around Plugins and Virtual Instruments.

We cover the development of ASIO , that although is well known to be the industry standard and essentially default low latency driver protocol for Windows, we discuss how it was orginally also available on earlier Mac OS versions pre OSX, and share some opinions and Pro's and Cons on that not being embraced on the later platform.

We discuss the development of Nuendo and the reasoning behind the move in that direction, the eventual merging of the codebase with Cubase, and Manfreds exodus shortly after the initial Steinberg sale to Pinnacle.

We also cover Manfred's creative and business endeavors after leaving Steinberg, muse over the current state of Music Technology, sharing some great insights and behind the scenes stories, and much, much more.

Host & Guest Links :

AAVIM Technology : www.aavimt.com.au

DAWbench : www.dawbench.com

Microsoft : www.microsoft.com

Pete Brown : https://twitter.com/Pete_Brown

Manfred Rürup : https://www.linkedin.com/in/manfred-ruerup-808250/


VO :

Andrew Peters : www.andrewpetersvo.com

Music Themes :

Original DAWbench VI Theme Music composed by Rob John : Independent Music Productions : http://www.indmusicprods.com

DAWbench Radio Show ReMix by Erin McKimm : www.erinmckimm.com


All Rights Reserved : © AAVIMT 2026





Download audio: https://traffic.libsyn.com/secure/dawbench/DAWbench-Radio-Show-E43.mp3?dest-id=1394774
Read the whole story
alvinashcraft
20 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Microsoft 365 Copilot on mobile: What staged rollout plans can miss

1 Share

IT teams often design rollout plans in careful stages: the right pilot group, the right prerequisites, the right communications, and the right guardrails. Sequencing matters.

But when Microsoft 365 Copilot on mobile shows up in your environment, the shape of adoption can change.

Employee behavior doesn’t always follow the same tidy stages as licensing or deployment plans. Once people can use Copilot in the moments where work actually happens—between meetings, on the go, in a hallway conversation, before a customer call—usage can spread faster, more socially, and less linearly than many rollout models assume.

You can stage the rollout, but you can’t always stage the real-world usage pattern that follows. And mobile is one of the fastest places that gap shows up.

What we’re seeing: mobile changes the moments where Copilot shows up

Mobile shifts adoption because it changes the context in which Copilot appears day to day:

  • Copilot shows up more during “in-between” work moments

Those moments where people look for quick help: summarizing, drafting, finding, checking, and preparing.

  • Usage spreads through behavior, not just rollout sequence

A teammate shares a faster way to prep for a meeting. A leader asks for a quick recap while traveling. A project team starts referencing Copilot outputs in a chat thread. That kind of spread can move ahead of your staged plan.

  • Desktop assumptions don’t always carry over cleanly

Governance, communication, and readiness decisions that feel straightforward in a desktop-first mindset can surface earlier when usage starts in mobile-first ways.

Taken together, mobile introduces a second force into staged rollout planning: behavioral adoption momentum that doesn’t always wait for the next planned phase.

Staged Copilot deployment ≠ staged usage

Mobile frequently compresses the “pilot → expand → scale timeline,” creating earlier-than-expected issues:

  • IT starts fielding questions about “what’s allowed,” “what’s recommended,” or “what’s safe” before the plan anticipated
  • Governance and communication become tightly linked. If the org hasn’t expressed expectations and guardrails early and clearly, fast-moving usage can create confusion or conflicting local norms
  • Rollout plans start competing with reality. Mobile can make Copilot feel “present” in daily work. While IT is still staging rollout, parts of the organization behave like they’re already in broader adoption.

In many environments, this doesn’t stay theoretical for long.

What to do: four areas that tend to matter most

If you’re planning your Copilot rollout, you’ll want to think through these four connected areas:

  1. Rollout sequencing: how you stage availability and expansion
  2. User behavior expectations: how adoption may spread, and how you’ll message it
  3. Governance and readiness considerations: what needs to be clear before usage accelerates
  4. Communication planning: how you set expectations so momentum doesn’t create confusion

If you’re hearing early signals that people are experimenting with Copilot in mobile contexts before the rollout has fully caught up or already seeing pockets of usage spreading faster than expected, use these four as levers for regaining clarity and alignment

Next step

Read the full blog for Microsoft 365 Copilot mobile rollout planning guidance, including how to align sequencing, governance, and communication, whether you’re still designing your rollout approach, or already responding to early signs of faster-than-expected adoption.

Read the full Accelerator blog: Microsoft 365 Copilot on mobile: Planning guidance for IT admins

Read the whole story
alvinashcraft
41 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Write Logic Apps in C#: introducing the Logic Apps Standard SDK

1 Share

The workflow you always wished you could write in code

If you build on Logic Apps Standard, you already know the deal: the runtime is excellent at the unglamorous parts of integration - connecting to systems, retrying, scaling, keeping run history you can actually debug. What you sometimes wanted was a different front door. You're a .NET developer. You live in C#, source control, and pull requests. And for a long time, authoring a workflow meant leaving all of that behind for a visual designer and a JSON file.

That's the gap the new Logic Apps Standard SDK closes. It lets you define Logic Apps Standard workflows in code - strongly typed, IntelliSense-guided C# - without giving up a single thing the runtime already does for you.

What is the Logic Apps Standard SDK?

The Logic Apps Standard SDK (Microsoft.Azure.Workflows.Sdk) is a NuGet package that gives you a fluent, code-first way to build workflow definitions in C#. Instead of dragging actions onto a canvas, you compose a workflow with method chaining: a trigger, then the actions that follow it, all the way to a response.

Worth saying clearly, because people ask: this is a new way to define workflows - not a new runtime. The workflows you write with the SDK compile down to the same definitions and run on the same Logic Apps Standard runtime you use today. Same connectors. Same hosting. Same rich run history and monitoring. You're changing the authoring experience, not the engine underneath it.

Why this matters for developers

When your workflow lives in C#, it behaves like the rest of your code. A few things fall out of that almost for free:

  • Type safety and IntelliSense - connector operations, triggers, and outputs are discoverable as you type, and the compiler catches mistakes before you run anything.
  • Real source control and reviews - workflows diff like code, get reviewed in pull requests, and version alongside the services they orchestrate.
  • Familiar tooling - refactor, debug with F5, and lean on the .NET ecosystem you already know.
  • Extensibility on your terms — Compose your workflow declaratively with the fluent builder, then drop into plain imperative C# wherever a step needs logic that might be too complex to implement declaratively - loops, branching, a call into your own library, all encapsulated in a step of your workflow - without leaving the file or the language.

And it isn't limited to one style of work. The SDK covers both enterprise integration workflows - the connect-systems-and-move-data scenarios Logic Apps is known for - and agentic workflows, where a conversational or autonomous AI agent drives the steps. Both are first-class in the same SDK, built from the same building blocks.

There's one more angle worth calling out, because it's becoming hard to ignore: coding agents are simply better at writing imperative code than declarative JSON. And the reason is the same set of guardrails that helps you. Strong typing and a compilation step mean the code an agent produces is syntactically correct out of the gate — the type system and the compiler do the checking, so you don't have to. Layer unit tests on top and you've covered north of 90% of what matters; what's left is integration testing. Getting an LLM to the same level of accuracy against declarative JSON means building dedicated tooling to stand in for everything the compiler gives you for free. With code-first workflows, those guardrails are just there — which makes this a natural fit for an agent-assisted way of building.

Getting started

Everything here lives in the Logic Apps extension for VS Code. You'll want the Logic Apps Standard VS Code extension version 5.961.10 or later, which includes all the components you need to create code first workflows. Beyond that, the prerequisites are the ones you'd expect - VS Code with the Logic Apps extension, an Azure subscription you can create resources in, and a working comfort with C# and .NET.

From a clean start, you're a handful of steps from a running workflow:

  1. Create the workspace — launch the Logic Apps extension and choose Create new Logic Apps workspace. Pick a folder, name the workspace and project, and when prompted for the workflow type, choose Logic Apps codeful - that's the code-first option that uses the SDK.
  2. Pick a workflow kind - name your first workflow and choose how it runs: Stateful, Autonomous agents (Preview), or Conversational agents (Preview). The agent options are where the agentic scenarios live.
  1. Enable connectors - when prompted, select Use connectors from Azure, choose your subscription and resource group, and pick Connection Keys for authentication. Managed identity is still in development, so connection keys are the way in for now.
  2. Find your way around - the project opens with Program.cs, which builds and starts the host, plus a workflow file (like workflow1.cs) where your trigger and actions are defined. The SDK compiles those definitions and runs them on the Logic Apps runtime.
  3. Run it - press F5 (or right-click Program.cs and pick Overview). The runtime starts locally and an overview page opens where you can fire triggers, watch run history, and inspect inputs and outputs.

That last part is worth dwelling on: run history for SDK workflows uses the same rich visual view as designer-built ones. You author in code, but you monitor and troubleshoot exactly as you always have.

A look at the capabilities

Connectors and triggers

Every workflow starts with a trigger and runs a series of actions. The SDK exposes both through two entry points - WorkflowTriggers and WorkflowActions - each split into BuiltIn and Managed.

  • Built-in triggers and actions run directly in the runtime: HTTP request, recurrence, and the conversational agent trigger; actions like Compose, HTTP, Response, and custom code.
  • Managed connectors give you the full Logic Apps connector catalog - Service Bus, SharePoint, SQL, and hundreds more - typed and ready to call.

The managed surface is generated from the same connector definitions the designer uses, so the operations you know are right there:

// Built-in trigger var trigger = WorkflowTriggers.BuiltIn.CreateHttpTrigger(); // Managed connector action — full catalog, strongly typed var getItems = WorkflowActions.Managed .Sharepointonline("sharepoint") .GetItems( dataset: () => "https://contoso.sharepoint.com", table: () => "orders-list-id") .WithName("GetOrders");

 

 

The fluent API streamlines the definition

This is where it comes together. You compose a workflow by chaining operations with .Then(...). The shape of your code mirrors the shape of your workflow - read it top to bottom and you read the execution path.

trigger .Then(validateOrder) .Then(getOrders) .Then(sendResponse);

Control flow is part of the same fluent model. Built-in structures like Condition (if/else) and ForEach - along with Switch, Until, Scope, and Terminate - are just actions you chain in, each taking a small factory for the branch or loop body:

var checkTotal = WorkflowActions.BuiltIn.Control.Condition( expression: () => order.Total > 1000, trueBranch: () => requireApproval, falseBranch: () => autoApprove ).WithName("CheckOrderValue");

And ForEach takes the collection to iterate and a factory that builds the body for each item:

var processLines = WorkflowActions.BuiltIn.Control.ForEach( items: () => order.LineItems, actions: (item) => new WorkflowBuiltInActions() .Compose(inputs: () => $"Line: {item}").WithName("HandleLine") ).WithName("ProcessLineItems");

Need parallel branches that fan back in? The same Then pattern handles branching and join - no JSON wiring, no run-after blocks to hand-edit.

Extending workflows with custom code

Some logic doesn't belong in a connector or an expression - it's just code. The CustomCode action lets you drop a real C# method into the middle of a workflow. It receives a WorkflowContext, so you can read the trigger payload or any earlier action's results and return a strongly typed value the next step can use:

var enrich = WorkflowActions.BuiltIn.CustomCode<string>(async (context) => { var trigger = await context.GetTriggerResults(); var order = await context.GetActionResults("GetOrders"); // your logic, your libraries, your types return "enriched"; }).WithName("EnrichOrder");

That's the escape hatch that keeps you in flow: when a step needs custom transformation, validation, or a call into your own libraries, you write a method instead of bending an expression to do something it was never meant to.

Handling failures: try/catch with run-after

Real workflows have to deal with things going wrong, and the SDK gives you the same try/catch shape Logic Apps has always had - expressed in code. The .Then(...) overload takes a FlowStatus[] run-after condition, so a handler runs only when the step before it ends in a status you name. Wrap the risky work in a Scope (your try), then chain a handler that runs after it Failed or TimedOut (your catch):

var tryProcess = WorkflowActions.BuiltIn.Control.Scope(() => callPaymentApi.Then(saveOrder) ).WithName("ProcessPayment"); var handleFailure = WorkflowActions.BuiltIn .Compose(inputs: () => "Payment failed — compensating") .WithName("HandleFailure"); trigger .Then(tryProcess) .Then(handleFailure, runAfter: new[] { FlowStatus.Failed, FlowStatus.TimedOut });

The status set is the whole vocabulary: Succeeded, Failed, Skipped, and TimedOut. Combine them however a step needs - a cleanup action that should run no matter what can list every status; a finally is just the union.

The same idea scales to fan-in. When several parallel branches converge, the per-predecessor RunAfter overload lets the join wait on each branch independently - so you can require some to succeed and tolerate others failing:

leftChain .Join(rightChain) .Then(merge, runAfter: new[] { new RunAfter(leftChain, FlowStatus.Succeeded), new RunAfter(rightChain, FlowStatus.Succeeded), });

Putting it together

Here's a small but complete shape - an HTTP-triggered order workflow that validates input, branches on order value, loops over line items, runs custom code, and replies. The core steps live in a Scope so a single failure handler can catch anything that goes wrong, and a clean reply only runs when the work succeeds. Notice it's all one readable chain:

namespace LogicApps { using Microsoft.Azure.Workflows.Sdk; using Microsoft.Azure.Workflows.Sdk.Connectors.Msnweather; using System.Net; public class OrderWorkflow : IWorkflowProvider { /// <summary> /// Gets the HTTP request/response workflow definition. /// </summary> public FlowDefinition[] GetWorkflows() { // --- Trigger ---------------------------------------------------- var trigger = WorkflowTriggers.BuiltIn.CreateHttpTrigger(); // --- Managed connector action (full catalog, strongly typed) ---- // Reused verbatim from the confirmed stateful1.cs pattern. var getWeather = WorkflowActions.Managed.Msnweather("msnweather").CurrentWeather( location: () => "98058", units: () => unitsInput.Imperial).WithName("GetWeather"); // --- Custom code: real C# in the middle of the workflow --------- var enrich = WorkflowActions.BuiltIn.CustomCode<string>(async (context) => { var triggerResults = await context.GetTriggerResults(); var weather = await context.GetActionResults("GetWeather"); // your logic, your libraries, your types return "enriched"; }).WithName("EnrichOrder"); // --- ForEach over a collection (control flow via .Control) ------- var processLines = WorkflowActions.BuiltIn.Control.ForEach( items: () => trigger.TriggerOutput.Body["lineItems"], actions: (item) => WorkflowActions.BuiltIn .Compose(inputs: () => $"Line: {item}").WithName("HandleLine") ).WithName("ProcessLineItems"); // --- Condition (if/else) (control flow via .Control) ------------ var checkTotal = WorkflowActions.BuiltIn.Control.Condition( expression: () => true, trueBranch: () => processLines, falseBranch: () => WorkflowActions.BuiltIn .Compose(inputs: () => "Auto-approved").WithName("AutoApprove") ).WithName("CheckOrderValue"); // --- Scope groups the core steps so one handler catches failures - var processOrder = WorkflowActions.BuiltIn.Control.Scope(() => checkTotal .Then(getWeather) .Then(enrich) ).WithName("ProcessOrder"); // --- Responses -------------------------------------------------- var ok = WorkflowActions.BuiltIn.Response( responseBody: () => "Order processed").WithName("Reply"); var failed = WorkflowActions.BuiltIn.Response( statusCode: () => HttpStatusCode.InternalServerError, responseBody: () => "Order failed").WithName("ReplyFailed"); // --- Assemble --------------------------------------------------- // Happy path runs after the Scope Succeeded; the handler runs after // Failed or TimedOut. trigger .Then(processOrder) .Then(ok, runAfter: new[] { FlowStatus.Succeeded }) .Then(failed, runAfter: new[] { FlowStatus.Failed, FlowStatus.TimedOut }); return new[] { WorkflowFactory.CreateStatefulWorkflow("OrderWorkflow", trigger) }; } } }

That last stretch is the best-practice shape in miniature: the happy-path Reply runs only after the Scope Succeeded, while a separate handler catches Failed or TimedOut and returns a 500 - no exception plumbing, just run-after conditions.

You implement IWorkflowProvider, hand your trigger graph to WorkflowFactory as a stateful, stateless, or agent workflow, and the host registers it. Run it with F5 and the Logic Apps runtime starts locally - same as any Standard project.

Before you build: preview realities

I'd rather you go in clear-eyed. While the SDK is in public preview, keep these in mind:

  • Service Provider connectors aren't supported yet - that connector type is coming in a future release.
  • Dynamic schemas aren't supported - support is planned.
  • Custom code supports callback methods only - inline lambdas aren't available in this version.
  • Define and name actions before referencing them - name an action before using it as a dependency elsewhere.
  • Managed identity authentication is in development - use connection keys for connectors in the meantime.

Try it, and tell us what you think

If you've ever wanted your workflows to live where the rest of your code lives - in C#, in source control, in your pull requests - this is for you. Install the Logic Apps extension for VS Code, create a Logic Apps codeful project, and build your first workflow in code.

This is a preview, which means your feedback genuinely shapes where it goes - which capabilities come next, where the rough edges are.

Bring issues, feature requests and feedback to our GitHub page. I read it. Let's make code-first workflows something you actually want to use.

Read the whole story
alvinashcraft
52 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Prioritizing Memory Efficiency: Essential Steps for Android 17

1 Share
Posted by Alice Yuan, Developer Relations Engineer, Ajesh Pai, Developer Relations Engineer, and Fung Lam, Developer Relations Engineer

While app performance is often equated with a smooth UI and fast start times, memory serves as the silent foundation upon which these visible metrics are built. It's no secret that we're seeing a shift where device memory is more important than ever. Not only have we made strides in Android memory optimizations with Android 17, we're providing the tooling and API support to help you stay ahead of stricter memory requirements later this year.

To ensure device stability, starting in Android 17, the system will begin enforcing app memory limits based on the device's total RAM. If an app exceeds those limits, Android will kill the process with no associated stack trace.

Beyond these forced terminations, unoptimized memory usage inevitably degrades the user experience. When the app approaches heap memory limits, it triggers frequent garbage collection—leading to noticeable UI stutters. Furthermore, when a device runs out of available memory, the system scrambles to reclaim pages, causing CPU strain, UI latency, and battery drain. If the memory shortage is too severe, it can cause Low Memory Killer (LMK) events that abruptly terminate background processes and force apps to have slow cold starts and lose user state.

To build highly performant apps and avoid these forced terminations, we recommend that you adopt the following memory optimization strategies:

  1. Maximize bytecode optimization with R8
  2. Optimize image loading
  3. Detect and fix memory leaks with Android Studio
  4. Trim memory when app leaves visible state
  5. Advanced memory observability with ProfilingManager

A condensed version of this blog post is also available in video format, go check it out!

Understanding Android 17 app memory limits

App memory limits are being introduced in Android 17 to prevent "one bad actor" from destroying the multitasking experience and stability of the user’s entire device.

Here is a breakdown of the reasons driving this architectural change:

  • Preventing cascading kills: When an app becomes bloated or leaks memory while holding a privileged state (e.g. it’s running a Foreground Service), it is initially shielded from the system's Low Memory Killer (LMK). As this single app grows unchecked and hoards RAM, the LMK is forced to compensate by killing off dozens of smaller, well-behaved cached apps and background jobs to reclaim space for the memory hog.
  • Preserving multitasking and user state: When the system is forced to purge cached apps to accommodate a single leaking process, the multitasking experience is severely degraded. Users returning to prior cached applications encounter sluggish cold starts instead of near-instant warm resumes. This inefficiency generates more CPU strain and accelerates battery depletion. It can also destroy the user’s context in recently used apps, such as scroll positions, navigation stacks, and in-game progress.

To determine if your app session was impacted by these constraints in the field, you can call getDescription() within ApplicationExitInfo. If the system applied a limit, the exit reason is reported as REASON_OTHER and the description string will contain "MemoryLimiter:AnonSwap". You can also leverage trigger-based profiling using TRIGGER_TYPE_ANOMALY to automatically capture heap dumps when the memory limit is reached. Furthermore, Android is actively working to surface more in-field memory metrics to developers within the Google Play Console.

We have also expanded our memory limits documentation to include local debugging commands, allowing you to simulate memory constraints in your local environment and validate your application's behavior under any memory limit enforcement. 

Maximize bytecode optimization with R8

A highly effective way to reduce your app's memory footprint is to enable the R8 optimizer. By shrinking classes, methods, and fields into shorter names and stripping out unused code and resources, R8 significantly reduces your app's memory footprint by minimizing the amount of resident code required during execution. 

R8 minimizes resident code, shrinking the memory footprint and lowering LMK termination risk. This results in more frequent warm starts over slow cold starts. Additionally, streamlined bytecode reduces main-thread CPU overhead, directly cutting ANR rates for a more fluid user experience. For example, the digital bank Monzo enabled full R8 optimization and saw a 35% reduction in their ANR rate, a 30% improvement in cold start rate, and a 9% reduction in overall app size.

The digital bank Monzo enabled full R8 optimization and boosted performance metrics by up to 35%.

To properly configure R8 in your build.gradle file:

  • Set isShrinkResources = true and isMinifyEnabled = true.
  • Use proguard-android-optimize.txt instead of the legacy proguard-android.txt, which actually prevents optimizations and is no longer supported in Android Gradle Plugin 9.
  • Remove android.enableR8.fullMode = false from your gradle.properties.

If you are using reflection in your code base, then add Keep rules to prevent R8 from optimizing those parts of the code. Make sure to scope the keep rules narrowly to get the maximum optimization.

To get the maximum optimization, make sure to follow these best practices in your keep rule file.

  • Remove global options like -dontoptimize, -dontshrink, and -dontobfuscate that prevent R8 from optimizing the entire codebase 
  • Remove keep rules that prevent optimizing Android components like Activity, Services, Views or Broadcast receivers.
  • Refine the broad package wide keep rules to target only specific classes or methods.

To see more best practices, view our keep rules documentation.

Library Developer R8 Best Practices

If you are a library developer, strictly place the rules your consumers need into your consumer-rules file, and keep your library's internal protection rules in your proguard-rules.pro file. For more information on how to optimize libraries, see Optimization for library authors.

R8 Configuration Analyzer

To audit your R8 optimization, use the Configuration Analyzer. Configuration analyzer shows the current state of optimization with Obfuscation, Optimization, and Shrinking scores. With configuration analyzer, you can also understand how many classes, methods or fields are prevented from optimization by each keep rule. Refine these broad package wide keep rules to unlock the maximum optimization.

Using configuration analyzer, you can also identify keep rules that are subsuming other keep rules, redundant keep rules and unused keep rules.

The Configuration Analyzer shows the current state of optimization with Obfuscation, Optimization, and Shrinking scores.

R8 Agent Skill 

You can also leverage the R8 Agent Skill with Android Studio agent or other AI tools to resolve misconfigurations and refine your rules resulting in improved app performance. (Insights from AI-driven skills will require technical verification)

Optimize image loading

Bitmaps are usually the largest common objects residing in your app's memory. They represent the final stage of the image loading process where compressed files, like JPEGs or PNGs, are decoded into raw pixel data for display. This means a tiny 100KB compressed image can balloon into several megabytes of RAM because memory consumption is determined by the image's pixel dimensions and color depth. Since bitmap operations are frequently on the critical path to drawing frames, unoptimized images cause severe memory bloat and UI jank.

Google recommends leveraging image loading libraries Coil for Kotlin-first projects, particularly when developing with Jetpack Compose and Glide for Java-based applications.

Adopt these five best practices

  1. Downsample images: If you’re loading bitmaps manually, avoid loading a massive image into a tiny thumbnail view; use inSampleSize to load a smaller version. Glide and Coil downsamples images by default and you can configure this downsample strategy using DownsampleStrategy and ImageLoader respectively.
  2. Cropping: Avoid embedding padding directly into an image file for letterboxing purposes (e.g., creating a transparent border to expand an image dimensions). Rather than baking in these borders, utilize InsetDrawable or apply padding directly within the View or Composable containing the bitmap.
  3. Config: Balance memory and quality by choosing the right pixel format. Use RGB_565 when transparency isn't needed, which uses half the memory of the default ARGB_8888 format. In Glide you can configure this by using DecodeFormat and in Coil you can use bitmapConfig property.
  4. Prioritize vector drawables: For basic geometric assets, leverage ShapeDrawable as a lightweight alternative to decoding rasterized bitmaps. By defining these assets once via XML, you ensure they scale seamlessly across all display densities while effectively eliminating resource-driven memory bloat.
  5. Reuse: If your application manages Bitmaps manually then to minimize memory churn, when a bitmap is no longer required, the app should call bitmap.recycle() and immediately discard the Bitmap reference. If you use an image loading library like Glide or Coil, return the bitmap to the library’s managed pool. By providing an existing buffer for future memory needs, the pool effectively avoids the overhead of new allocations.

Check out our documentation on Optimizing performance for images to learn more.

Android Studio tooling

You can also eliminate redundant bitmaps using Android Studio Narwhal 4. Here is how to hunt them down in five simple steps:

  1. Open the Profiler tab in Android Studio
  2. Click Heap Dump (or "Analyze Memory Usage") and hit record to take a snapshot of your app’s current memory state.
  3. Scan the analysis results for the yellow warning triangle ⚠️, which Android Studio uses to flag duplicate bitmaps being stored multiple times. Alternatively, navigate to the profiler header, choose "Filter by:" and pick the "Duplicate Bitmaps" setting.
  4. Click on any flagged entry to open the Bitmap Preview pane, allowing you to see exactly which image is the repeat offender.
  5. Use that visual confirmation to track down the redundant loading logic in your code and implement a better caching strategy.
Look for the yellow warning triangle ⚠️ in heap dumps when using the Android Studio Profiler.

Detect and fix memory leaks with Android Studio

Memory leaks in Android occur when your code holds onto an object's reference long after its lifecycle has ended. This prevents the Garbage Collector (GC) from reclaiming that memory, eventually leading to sluggish performance or OutOfMemoryError (OOM).

Android Studio Panda 3 features a dedicated LeakCanary profiler task, allowing developers to analyze real-time memory leaks and map traces within the IDE.

The LeakCanary profiler task in Android Studio actively moves the memory leak analysis from your device to your development machine, resulting in a significant performance boost during the leak analysis phase as compared to on-device leak analysis.

LeakCanary memory leak analysis contextualized with Go to declaration for debugging

Additionally, the leak analysis is now contextualized within the IDE and fully integrated with your source code, providing features like go to declaration and other helpful code connections that drastically reduce the friction and time required to investigate and fix memory leaks.

Examples of common memory leaks 

Memory leaks occur when an object persists in memory beyond its intended lifespan. This typically happens due to:

  • Retaining references to Fragments, Activities, or Views that are no longer in use.
  • Mismanaging Context references.
  • Failing to properly unregister observers, listeners, and receivers.
  • Creating static references to objects that are bound to components with shorter lifecycles.

Here are a few example scenarios:

Scenario

Compose-based example

View-based example

Leaking Context

Example:
Passing LocalContext.current to a ViewModel

Fix:
Keep Context dependent logic within the UI layer. For non-UI layers, refactor to use dependency injection or observe UI state using Kotlin flow.

Example:
Storing an Activity in a companion object or static variable.

Fix:
Don’t hold static references to UI components. Refactor to use dependency injection or observe UI state using Kotlin flow.

Leaking Listeners

Example:
Using DisposableEffect to start a listener but leaving onDispose empty.

Fix:
Perform the unregistration and cleanup logic inside the onDispose block.

Example:
Registering for SensorManager updates and forgetting to unregister.

Fix:
Manually call unregisterListener() in onStop() or onDestroy() lifecycle.

Leaking Views

Example:
Holding a reference to a legacy View inside an AndroidView without a release strategy.

Fix:
Use the release block of the AndroidView composable to clean up the legacy View.

Example:
Keeping a reference to a view binding object after the Fragment is destroyed.

Fix:
Set the binding variable to null inside the onDestroyView() lifecycle method.

Trim memory when app leaves visible state

Android can reclaim memory from your app or stop your app entirely if necessary to free up memory for critical tasks, as explained in Overview of memory management. Android will usually reclaim memory from your app when it’s not visible to the user, such as by discarding some of your app’s code and data pages in memory or compressing your heap allocations. When the user resumes your app and your app tries to access some memory that’s been reclaimed, the OS will swap that memory back in on demand. This swapping behavior can be slow, and cause unexpected jank or stutters in your app.

If you leave it to the OS to decide what memory to reclaim from your app, you may find that the OS reclaimed memory that you’ll need shortly after resuming your app. Instead, your app can voluntarily discard memory allocations that it can regenerate later, on demand and at a low cost. To do so, you can implement the ComponentCallbacks2 interface. You can implement onTrimMemory in your Activity, Fragment, Service, or even your custom Application class. Using it in the Application class is highly effective for global cache management.

The provided onTrimMemory() callback method notifies your app of lifecycle or memory-related events that present a good opportunity for your app to voluntarily reduce its memory usage.

In terms of memory lifecycle management, your implementation should focus exclusively on TRIM_MEMORY_UI_HIDDEN and TRIM_MEMORY_BACKGROUND. Since Android 14, the system has ceased delivering notifications for other legacy constants, which were formally deprecated in Android 15.

TRIM_MEMORY_UI_HIDDEN: This signal indicates that your application's UI has transitioned out of the user's view. This provides an opportunity to release substantial memory allocations tied strictly to the interface—such as Bitmaps, video playback buffers, or complex animation resources.

TRIM_MEMORY_BACKGROUND: At this level, your process is residing in the background and is now a candidate for termination to satisfy the system's global memory needs. To extend the duration your process remains in the cached state, and reduce the number of app cold starts, you should aggressively release any resources that can be easily reconstructed once the user resumes their session.

import android.content.ComponentCallbacks2
// Other import statements.

class MainActivity : AppCompatActivity(), ComponentCallbacks2 {

    /**
     * Release memory when the UI becomes hidden or when system resources become low.
     * @param level the memory-related event that is raised.
     */
    override fun onTrimMemory(level: Int) {

        if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            // Release memory related to UI elements, such as bitmap caches.
        }

        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
            // Release memory related to background processing, such as by
            // closing a database connection.
        }
    }
}

Note: The onTrimMemory integration may depend on SDK support. For instance, certain games rely on their game engine to enable this capability. Please check out the game memory optimization documents.

Advanced memory observability with ProfilingManager

To catch and diagnose memory issues in the field that cannot be reproduced locally, you should leverage the ProfilingManager API. Introduced in Android 15, this advanced observability API allows you to programmatically collect real-user Perfetto profiles.

For teams that lack a dedicated infrastructure to manage and host performance artifacts, Crashlytics is exploring a specialized solution to streamline this workflow. They are inviting developers to provide feedback.

Android 17 introduces new event-driven triggers, most notably TRIGGER_TYPE_OOM and TRIGGER_TYPE_ANOMALY:

  • The OOM trigger automatically collects a Java heap dump at the exact moment an OutOfMemoryError crash occurs, providing precise allocation states. A collected OOM profile is provided the next time the app starts and registers the registerForAllProfilingResults callback.
  • The Anomaly trigger detects severe performance issues, such as excessive binder spam or breached memory thresholds. The memory anomaly delivers a heap dump just prior to the system terminating the app.
  val profilingManager = 
applicationContext.getSystemService(ProfilingManager::class.java)
    val triggers = ArrayList()  


    triggers.add(ProfilingTrigger.Builder(
                 ProfilingTrigger.TRIGGER_TYPE_ANOMALY))
    val mainExecutor: Executor = Executors.newSingleThreadExecutor()
    val resultCallback = Consumer { profilingResult ->
        if (profilingResult.errorCode != ProfilingResult.ERROR_NONE) {
            // upload profile result to server for further analysis          
            setupProfileUploadWorker(profilingResult.resultFilePath)
        } 

    profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback)
    profilingManager.addProfilingTriggers(triggers)

Once you’ve collected the heap dump, you can download the profile from the server, or locally via adb pull and drag and drop the file into the Perfetto UI. To streamline your memory debugging workflow, use the Heap Dump Explorer, this is the new default view for heap dumps in Perfetto UI. This tool provides an intuitive interface for inspecting Java heap dumps, allowing you to visualize object allocation hierarchies, compute retained memory sizes, and identify the shortest path from garbage collection root. By leveraging the Heap Dump Explorer, you can rapidly pinpoint memory leaks, bloated retained objects such as excessive bitmap allocations, and analyze heap object allocations all in one place.

Use the Heap Dump Explorer’s embedded flamegraph to visually inspect and navigate through objects with the highest heap allocations.

Conclusion

Optimizing bytecode with R8, adopting image loading best practices, and resolving memory leaks are critical steps toward delivering a high-quality user experience while managing resources effectively under pressure. Adopting these proactive measures helps maintain app stability and performance, preventing unexpected terminations while safeguarding user context. To further your performance expertise, explore our revised memory guidance.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Introducing Uno Platform Studio 3.0: AI-Native Productivity Platform for Enterprise .NET Applications

1 Share
&&
AnnouncementStudio 3.0
Introducing Uno Platform Studio 3.0

Announcing Uno Platform Studio 3.0. Create and design cross-platform .NET apps within minutes, directly in your browser, using Uno Platform Studio Agent. No installs required.

Try it now →

AI coding tools are everywhere. GitHub Copilot, Claude, Codex, and a growing list of agents can now generate code at remarkable speed and quality. For many developers, that is already a productivity gain.

For enterprises, generating code is not the same as building a real application. Enterprise applications need design system awareness, live runtime context, cross-platform consistency, UI validation, and a human reviewer who can say yes or no. Without that surrounding layer, even the best agent is guessing.

That is the gap Uno Platform Studio 3.0 closes.

The release highlight is Uno Platform Studio Agent and the Uno Platform Studio App. We are opening the front door to them with Uno Platform Studio App on the web: a brand-new, browser-based way to go from a prompt to a working Uno Platform app in minutes. This is the fastest path from idea to a .NET app that runs everywhere .NET runs.

We are announcing Uno Platform Studio 3.0 at Microsoft Build, where we will be joined by Kahua, our largest customer, for the session "Scale enterprise .NET apps with AI-assisted cross-platform workflows." Together, we will show how AI-assisted cross-platform workflows help enterprise .NET teams modernize, build, and scale real applications.

Launch Offer

To celebrate the launch, we are offering 20% off new purchases with promo code UNOBUILD26, valid through June 30, 2026. Try it now →

Studio Agent

Uno Platform Studio Agent

Behind Studio 3.0 sits Uno Platform Studio Agent, the orchestration layer that connects AI models to the Uno Platform development workflow. It is what turns a generic AI model into a Uno Platform-aware development assistant.

  • Deep contextual domain knowledge for building cross-platform .NET apps with the Uno Platform stack
  • Context window management with user prompts
  • App scaffolding guidance based on best practices
  • Grounded in latest Uno Platform docs
  • MCP tool invocation to verify AI work
  • Uno Platform-specific skills (70+ at launch)
  • Human-AI loops with contextual tools

The combination of Uno Platform Studio Agent and Uno Platform Studio App means .NET developers have a fast pass at going from idea to cross-platform reality with powerful agentic workflows.

Studio App

Uno Platform Studio App: Start from a Prompt, Scaffold Your App, Export to IDE/CLI

Open a browser. Describe the app you want. Watch a cross-platform .NET application scaffold in front of you. Because it uses Uno Platform, the application is built with the right foundations from the start.

The browser-based experience is designed to remove the friction between an idea and a working app. No install step, no project template wrestling, no waiting before you see your first screen.

  • Start from a prompt. Describe the app you have in mind, in your own words, and let Studio App scaffold a Uno Platform project to match.
  • Choose from 10+ predefined prompts. Pick from a curated library that covers common app shapes: dashboards, ordering flows, line-of-business patterns, and more. Each one drops you into a working app, ready to iterate.
  • Preview your app immediately. Studio App shows you the running result, not just generated code.
  • Iterate quickly. Refine your prompt, change the structure, restyle the UI, and see the updated app on the spot. Or tweak the app using Hot Design in the browser without spending AI tokens.
  • Continue in Studio App, or export and keep going. Continue iterating in the browser or export the project and continue in your preferred IDE or an agentic CLI environment.

For .NET teams that want to evaluate AI-assisted cross-platform development before committing, Studio App is the easiest possible on-ramp. For experienced Uno Platform developers, it is a fast way to bootstrap a new project, prototype a feature, or sketch out a new screen without leaving the browser.

Skills

Uno Platform Studio Skills

This first wave of over 70 skills spans the full app lifecycle, from visual design through navigation, state management, and testing:

  • Themes and Material skills apply semantic color palettes, typography scales, button and TextBox variants, FABs, and lightweight styling overrides, keeping brand identity consistent across every target platform.
  • MVUX skills cover architecture and data flow, with guidance on immutable records, reactive feeds and states, commands, selection, pagination, and entity messaging for clean, predictable apps.
  • Navigation skills handle setup, route registration, regions, dialogs, tab bars, NavigationView sidebars, responsive shells, and troubleshooting.
  • Toolkit skills round out the UI with AutoLayout, cards, chips, drawers, SafeArea, shadows, responsive extensions, and dozens of control behaviors.
  • Testing skills close the loop with UI automation through the Uno App MCP server and reliable assertion patterns.
Why a Platform

Why Invest in a .NET AI Development Productivity Platform?

It is a fair question. If a developer already has Copilot, Claude, or Codex, why add anything?

The short answer: because those tools are powerful, but they do not understand your app.

A generic agent can write a XAML page or a C# class. What it usually cannot do on its own is:

  • See the live visual tree of the running application
  • Know the design system, theme, and component library the team has standardized on
  • Validate that a change renders correctly across web, desktop, mobile, and embedded targets
  • Pull context from official, version-correct Uno Platform documentation
  • Stay inside an approval workflow that a human controls

Uno Platform Studio 3.0 is the layer that supplies all of that. Through Studio App, Hot Reload, Hot Design, Docs MCP, and App MCP, any agent gets the correct context. The result is an agent that stops generating plausible code and starts producing changes that fit the app.

Works With Your Agent

Uno Platform Studio Agent does not replace Copilot, Claude, Codex, or any other agent. If you are already productive using one of those agents, Uno Platform MCPs give them the context, surface area, harness, and validation loop they need to be productive in real enterprise .NET applications.

The .NET ecosystem is unlike any other. It carries decades of investment in enterprise applications, an established design language, deep tooling expectations, and a developer community that expects rigor. Creating a productivity platform is not something that can be assembled by wrapping an LLM. It is the result of years of platform work.

Enterprise

The Enterprise Wedge: Modernization and Cross-Platform Workflows

Enterprise .NET teams are not chasing vibes. They are managing portfolios of important applications: internal tools, customer-facing systems, line-of-business apps, and modernization projects that have been waiting on the roadmap for years.

  • Modernize WPF, WinForms, and Xamarin.Forms applications without rewriting from scratch
  • Continue and accelerate .NET and modern Uno Platform development
  • Ship apps to multiple platforms from one codebase
  • Move faster on internal business apps without losing architectural discipline
  • Work through legacy UI backlogs that have been blocking new business priorities

Enterprise teams do not just need code generation. They need productivity gains with reliability, governance, maintainability, and architectural consistency. They need developers to stay in control. Uno Platform Studio 3.0 is designed exactly for that workload.

Launch Promo

Launch Promotion

To celebrate the launch of Uno Platform Studio 3.0, we are offering 20% off new purchases with promo code UNOBUILD26, valid through June 30, 2026. The promotion applies to both monthly and annual purchases, and stacks with the standard 16% annual discount for customers who choose annual billing.

Microsoft Build

Microsoft Build and Kahua: AI-Native .NET, In the Real World

Studio 3.0 is launching at Microsoft Build, and we are not launching it alone. We will be joined on stage by Kahua, our largest customer, for the session:

Scale enterprise .NET apps with AI-assisted cross-platform workflows

Kahua builds construction management software that runs on the kinds of timelines and platforms that do not forgive surprises. Their story is exactly the story Studio 3.0 is built for: a serious .NET application portfolio, real cross-platform demands, and a need to move faster without sacrificing quality.

The session will walk through what AI-assisted cross-platform workflows actually look like inside a large .NET engineering organization: what changes, what gets faster, and what stays under human control.

Uno Platform and Kahua at Microsoft Build
Your Turn

Now It's Your Turn

Uno Platform Studio 3.0 is ready for you. Whether you are evaluating AI-assisted .NET development in your browser, modernizing a WPF estate, shipping new cross-platform apps, or scaling AI workflows across a whole team, this release is built for the work you are doing.

AI agents are powerful, but they need context. Uno Platform Studio 3.0 gives .NET developers and their agents the context, harness, feedback loop, and cross-platform foundation they need to build real enterprise apps faster, from the first prompt in Studio App to the production release on every platform.

We cannot wait to see what you build with it.

Uno Platform Team

The post Introducing Uno Platform Studio 3.0: AI-Native Productivity Platform for Enterprise .NET Applications appeared first on Uno Platform.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories