Android / Kotlin
Android development means building apps in Kotlin for a system that owns each app’s lifetime and may rebuild a screen or kill the whole process at any time. That one fact explains the platform’s most common bug — a screen that comes back empty — and nearly every architecture recommendation Google makes. The page opens with sixteen events that destroy a screen and what survives each, then covers process death and saved state, Kotlin and coroutines up to Kotlin 2.4, Compose and its three phases, background work, Google Play’s tracks and its 2026 calendar, five documented cases, and where it degrades.
- Current version
- Kotlin 2.4 · Android 17 · Compose 1.12
- Lifetime
- Owned by the system — rotation rebuilds, memory pressure kills
- Google Play
- Target API 36 required since 31 Aug 2026
What destroys your screen — sixteen events, and what survives each
On Android the system, not your app, decides how long a screen and its process live. An activity — the object that runs one screen — is destroyed and built again whenever the device’s configuration changes. The whole process is killed whenever the system needs its memory, and when the user comes back, Android rebuilds the screen they left as if nothing had happened. Each event destroys a different amount, and a piece of state survives an event only if it lives somewhere that event does not reach. So the useful question about any screen is not “does it work?”. It is “what is left of it after each of these?”. Here are sixteen events. Later sections cite the rows by number.
| # | Event | What Android does | What survives | How to test it |
|---|---|---|---|---|
| 1 | Pressing Home or switching to another app | Stops the activity; the process stays | Everything — for now | Press Home, come back |
| 2 | Navigating forward from a Fragment | Destroys the fragment’s view; keeps the fragment on the back stack | The fragment and its ViewModel — not its view or anything bound to the view | Navigate there and back with LeakCanary installed |
| 3 | Navigating away from a Compose destination | Disposes its composition; keeps its back-stack entry | The entry’s ViewModel and rememberSaveable — not remember | Navigate away and back |
| 4 | The phone lies unused and unplugged (Doze) | Defers network access, jobs and alarms to short maintenance windows | Everything — but background work waits | adb shell dumpsys deviceidle force-idle |
| 5 | Rotating the device | Destroys the activity and creates a new one; the process stays | ViewModel, saved state, disk — not the old activity object, not remember | Rotate the emulator |
| 6 | Switching dark mode | As row 5 | As row 5 | The Quick Settings tile |
| 7 | Changing the app’s language (per-app language, since Android 13) | As row 5 | As row 5 | Settings → Apps → Language |
| 8 | Changing the font size or display size | As row 5 | As row 5 | Settings → Display |
| 9 | Resizing the window — split screen, a foldable unfolding, a desktop window | As row 5; on screens 600 dp and wider an app targeting API 36 can no longer lock its orientation, and from API 37 it cannot opt out | As row 5 | A resizable or foldable emulator |
| 10 | Connecting a hardware keyboard | As row 5; from Android 17 the on-screen keyboard is not shown again unless the app asks | As row 5 | Attach a keyboard to the emulator |
| 11 | The system needs memory while the app is in the background | Kills the process; when the user returns, a new process rebuilds the screen from its saved state | Saved state and disk — not the ViewModel | adb shell am kill <package> with the app in the background, then reopen it from Recents |
| 12 | The user revokes a permission in Settings | Kills the process; returning restores the screen as in row 11 | As row 11 | Revoke a permission while the app is in the background |
| 13 | The back gesture on the last screen | Finishes the activity; for apps targeting API 36, onBackPressed() is no longer called | Disk only — the saved state is discarded | Swipe back |
| 14 | Swiping the app away in Recents | Removes the task and its saved state; the process usually ends too | Disk only | Swipe it away |
| 15 | Force stop in Settings | Kills the process; its alarms and jobs stop until the user opens the app again | Disk only | Settings → Apps → Force stop |
| 16 | Rebooting the phone | Ends everything; WorkManager reschedules its work, AlarmManager alarms are gone | Disk, and WorkManager’s queue | Reboot the emulator |
Process death, saved state and memory
Rows 11 and 12 exist because a phone runs dozens of apps in a few gigabytes of memory and does not page app memory out to disk; it compresses it instead. When that is not enough, a system service, the low-memory killer, ends processes in order of importance: cached apps in the background first, then less important ones. On a mid-range phone with a camera or a game in the foreground, your app in the background can be gone within seconds. Android then keeps a promise the user never sees: when they come back from Recents, a new process is started and the screen they left is rebuilt — same tab, same scroll position, same half-typed message — if the app saved them.
The mechanism is saved state. As an activity stops, Android asks it for a Bundle — a small map of values — and keeps it outside the app’s process, so it outlives the process and is handed to the new one. SavedStateHandle in a ViewModel and rememberSaveable in Compose are both written there. The Bundle travels through Binder, Android’s mechanism for calls between processes, whose buffer is 1 MB and shared by everything the process is sending at that moment. Google recommends keeping saved state under 50 KB, and since Android 7.0 going over the limit throws TransactionTooLargeException, a crash that happens on the way into the background.
| Where the state lives | Rows 5–10: rebuilt | Rows 11–12: process killed | Rows 13–16: session ended | Use it for |
|---|---|---|---|---|
remember in a composable | Lost | Lost | Lost | Values cheap to recompute — an animation, a filtered list |
| A ViewModel | Kept | Lost | Lost | What can be fetched again; work in flight |
Saved state — SavedStateHandle, rememberSaveable | Kept | Kept | Lost | Small things the user chose: an id, a tab, a scroll position, a draft — under 50 KB |
| Disk — Room, DataStore, files | Kept | Kept | Kept | Anything the user would mind losing |
Testing rows 11–12 takes a minute. The developer option “Don’t keep activities” destroys every activity as soon as you leave it, which catches part of the problem. The real test is to put the app in the background, run adb shell am kill with its package name — it kills only a background process — and reopen the app from Recents. The screen should look exactly as you left it. Since Android 11, ApplicationExitInfo tells the new process why the last one ended — low memory, a crash, an ANR, the user — so a team can count process deaths in production instead of guessing.
Memory itself is now policed from two sides. Android 17, released on 16 June 2026, sets per-app memory limits based on the device’s total RAM and ends a process that goes past them; the exit reason carries the text “MemoryLimiter:AnonSwap”. Google Play has made memory usage a core vital with thresholds per RAM tier — on a 4 GB phone, 2 GB in the foreground and 1 GB in the background — and says apps above them may lose store visibility from February 2027. Images are the usual cause, for the reason the React Native page gives: decoded, an image costs width × height × 4 bytes, so a 12-megapixel photo is 48 MB in memory.
Kotlin and coroutines: work that ends with the screen
Kotlin is a language from JetBrains, stable since February 2016, that Google made an official Android language in May 2017 and its preferred one in 2019. Jetpack Compose exists only in Kotlin, and the documentation and new APIApplication Programming Interface — contract between programsThe rules one program follows to call another: which requests it may send, in what shape, and what comes back. To the caller it is a contract — everything behind it stays a black box, which is exactly what lets the other side be rewritten without breaking you.Full article →All terms are written for it first. Kotlin compiles to the same JVMJava Virtual Machine — the runtime Java runs onThe machine compiled Java code actually runs on. It supplies the garbage collector and the JIT, and it is the reason one build runs unchanged on Windows, Linux and macOS — the platform difference is the JVM’s problem, not the program’s.Full article →All terms bytecodeinstructions for a virtual machineCompact instructions for a virtual machine rather than for a real processor — what the JVM, CPython, PHP’s OPcache, React Native’s Hermes and the Ethereum Virtual Machine run. A compiler produces it from source code ahead of time, so the runtime skips parsing; the virtual machine then interprets it or compiles the busy parts further into machine code.Full article →All terms as Java, which the Android build then turns into DEX code for the Android runtime, so the two languages call each other directly and a Java codebase can move one file at a time. Two features pay for themselves at once. Nullability is part of the type — a String? cannot be used as a String without a check — and data and sealed classes describe a screen’s states in a few lines, which the compiler then checks exhaustively in a when.
| Version | Released | What changed for an Android developer |
|---|---|---|
| 1.0 | Feb 2016 | The first stable release; Google adopts it for Android in May 2017 |
| 1.3 | Oct 2018 | Coroutines become stable |
| 1.9.20 | Nov 2023 | Kotlin Multiplatform stable — shared logic for Android and iOS |
| 2.0 | May 2024 | The K2 compiler; the Compose compiler moves into the Kotlin repository and releases with it |
| 2.0.20 | Aug 2024 | Strong skipping on by default in Compose |
| 2.2 | Jun 2025 | Guard conditions in when stable; context parameters in preview |
| 2.3 | Dec 2025 | A checker for ignored return values; Java 25 support |
| 2.4 | Jun 2026 | Context parameters and explicit backing fields stable; collection literals (experimental); 18 months of security fixes per release line |
Coroutines are what changed how Android code is written. A suspend function can pause — waiting for the network or the database — without blocking its thread, so asynchronous work reads from top to bottom. Dispatchers say where it runs: Dispatchers.Main for the UIUser Interface — what the user seesEverything the user sees and operates: screens, buttons, fields, states. UI is how the interaction looks; whether the interaction makes sense in the first place is a UX question, and the two get confused constantly.All terms, IO for blocking reads and writes, Default for computation. What makes coroutines safe rather than merely convenient is structured concurrency. Every coroutine is started in a scope, and when the scope is cancelled, everything started in it is cancelled too. The table at the top is therefore also a table of scopes: the right scope is the one that ends exactly when the work stops being useful.
| Scope | Cancelled when | Use it for |
|---|---|---|
| viewModelScope | The ViewModel is cleared — it survives rows 5–10 and ends with rows 11–16 | Loading and refreshing a screen’s data |
| lifecycleScope | The activity or fragment is destroyed — including on every rotation | Short work tied to that one object, such as showing a dialog |
| rememberCoroutineScope() | The composable leaves the composition | Work started by a tap — scrolling to the top, an animation |
| GlobalScope | Never | Almost nothing: it is how work outlives the screen it was for |
| WorkManager | Not a scope — the work is persisted and survives rows 11–16 | Work that must finish even if the user leaves |
On top of coroutines sits Flow, a stream of values over time: a database query that emits again when the rows change, a search field that queries as the user types. For screen state, StateFlow holds the current value and emits updates, which is what a rebuilt screen needs — something to read at once and to observe afterwards. How the screen collects it matters as much as where it is produced. collectAsStateWithLifecycle() in Compose, or repeatOnLifecycle(STARTED) with Views, stops collecting when the app goes to the background and starts again when it returns. Without it, a flow of location updates keeps the GPS running for a screen nobody is looking at.
The main thread has a deadline on Android too. If it does not handle an input event within 5 seconds, the system shows the “App isn’t responding” dialog — an ANR. Google Play counts the share of sessions that hit a user-perceived ANR, and above 0.47% overall, or 8% on any single phone model, the app’s visibility in the store can suffer. Most ANRs are ordinary work in the wrong place: a database query, a large JSONJavaScript Object Notation — text format for dataA text format for passing data around: key–value pairs, lists, numbers and strings. It came out of JavaScript, but every language reads it now, and that is why most APIs answer in it rather than in anything more capable.All terms parse or a file read on Dispatchers.Main. StrictMode, switched on in debug builds, reports disk and network access on the main thread as it happens.
Compose: three phases, and what recomposes
Jetpack Compose, stable since July 2021 and at version 1.12 in September 2026, is the UI toolkit Google recommends. You write composable functions that describe the screen for a given state; when a state they read changes, Compose runs them again — recomposition — and updates what changed. It replaces XML layouts, findViewById, adapters and the habit of holding references to views and changing them by hand. For a list, it is the difference between a RecyclerView with an adapter and a view holder, and a LazyColumn with a lambda.
Compose builds each frame in three phases. Composition decides what to show by running composable functions. Layout decides where: every element is measured and placed. Drawing renders the pixels. Compose records which phase read each piece of state, and when the state changes it repeats only that phase and the ones after it. That gives the main performance rule a precise form: read state as late as you can. A header that moves with the scroll and reads the scroll offset in its composable recomposes on every frame of the scroll. The same header reading the offset inside Modifier.offset { } repeats only layout, and inside graphicsLayer { } only drawing.
The second rule is skipping. During recomposition Compose skips a composable whose parameters have not changed. Since Kotlin 2.0.20 strong skipping is on by default: parameters of stable types are compared with equals(), and everything else by identity — is it the same object? That makes one pattern expensive in a way that is hard to see. Room emits a new list of new objects whenever any row in a query changes, so every row of a LazyColumn receives a different object and recomposes, even if only one row changed. Give list items stable keys, mark data classes that really are unchanging with @Immutable, and read the Compose compiler’s stability report before guessing.
| Concern | Views (XML) | Compose |
|---|---|---|
| How state reaches the screen | You find the view and set the value, and keep the two in sync yourself | The screen is a function of state; there is nothing to keep in sync |
| Lists | RecyclerView, an adapter and a view holder — several files per list | LazyColumn with an item lambda, virtualised by default |
| Where it bites | Leaked references to views after row 2, state that drifts from the screen | State read too early, unstable parameters, new objects from the data layer |
| Measuring it | Layout Inspector, GPU rendering profile | Recomposition counts in Layout Inspector, the compiler’s stability report |
| Reality in 2026 | Most existing screens, and libraries that still expect it | Where new work goes; the two interoperate in both directions |
Compose also carries the platform’s changes in screen shape. Since apps were required to target Android 15, they draw edge to edge, under the status and navigation bars; for apps targeting Android 16 the opt-out is gone, the back gesture plays a predictive animation by default, and on screens 600 dp and wider the system ignores orientation locks — row 9. A layout written for one phone held upright now has to work on a tablet, an unfolded foldable and a resizable window. Window size classes and the adaptive Compose libraries exist for exactly that, and the React Native page lists the same deadlines from a cross-platform team’s side.
Background work: what the system lets you run
An app that is not on screen has, by default, no right to keep running, and almost every Android release since 2015 has narrowed what it may do. Doze in Android 6.0 deferred network access and jobs while the phone lies still. Android 8.0 limited background services. Android 9 sorted apps into standby buckets by how recently they were used. Android 14 required every foreground service to declare a type and stopped granting exact alarms to newly installed apps by default. Android 15 capped data-sync services at six hours a day. On top of that, several manufacturers add battery managers of their own that end background work more aggressively than stock Android; the site dontkillmyapp.com tracks them by brand.
| The job | What to use | What the system promises |
|---|---|---|
| Work for the screen the user is looking at | A coroutine in viewModelScope | It runs while the screen exists and stops with it — nothing more is needed |
| Work that must finish eventually — a sync, an upload of logs | WorkManager, with constraints such as “on Wi-Fi” or “while charging” | It survives process death and reboot and runs when the system allows; periodic work at most every 15 minutes |
| Something the user started and is watching — navigation, a call, music, a video upload | A foreground service with a declared type and a visible notification | It runs while the notification shows; on Android 15, data-sync and media-processing services stop after six hours in a day |
| Something at an exact time the user set — an alarm clock, a calendar reminder | An exact alarm from AlarmManager | It fires on time even in Doze, but since Android 14 the permission is not granted to new installs by default |
| Keeping the processor awake while the screen is off | A partial wake lock — briefly, and rarely | Nothing: since 1 March 2026 Google Play may demote an app that holds one too long |
The practical consequence is that “run in the background” is never a requirement you can accept as written. Ask what the user needs to happen and when they need to know it happened. Most answers are WorkManager with a constraint, a foreground service with a notification, or a push message from the server that tells the app there is something to fetch. Test every background path on two or three phones from manufacturers known for aggressive battery management, because the stock emulator is the one place where background work always runs.
Shipping: tracks, staged rollouts and the Play calendar
Google Play gives every app four tracks. Internal testing reaches up to 100 testers, usually within seconds of a build being added. Closed and open testing reach larger groups, and production reaches everyone. A personal developer account created after 13 November 2023 must run a closed test with at least 12 testers, opted in for 14 days in a row, before it may publish to production at all. Review is usually faster than Apple’s, but it exists, and policy checks — permissions declared, the data-safety form matching what the app does, the target API level — are automated and do not negotiate.
A staged rollout releases an update to a percentage of users you choose and raise over time — 1%, then 5%, then 20% — and can be halted at any point. While it runs, Android vitals in the Play Console shows the new version’s crash and ANR rates against the thresholds that affect the app’s visibility: a user-perceived crash rate of 1.09% overall or 8% on one phone model, an ANR rate of 0.47% overall or 8% on one model. The per-model threshold is the one that catches fragmentation: a crash on one manufacturer’s phones can be invisible in the overall average and still cost the app its listing on those phones.
Google Play’s calendar — the requirements around this page’s date
| Since | What it requires | What it means in the code |
|---|---|---|
| Aug 2021 | New apps publish as Android App Bundles | Play builds the APK for each device and signs it with Play App Signing |
| 1 Nov 2025 (extensions to 31 May 2026) | Apps targeting Android 15 or later support 16 KB memory pages | Every native library in every dependency rebuilt with 16 KB alignment |
| 1 Mar 2026 | Excessive partial wake locks affect store visibility | Wake locks released on every path, including those taken by SDKs |
| 31 Aug 2026 (extensions to 1 Nov 2026) | New apps and updates target Android 16 (API 36); existing apps below API 35 are hidden from new users on newer Android | No opt-out from edge-to-edge, predictive back by default, orientation locks ignored on large screens — rows 9 and 13 |
| 30 Sep 2026 | Developer verification in Brazil, Indonesia, Singapore and Thailand, for apps from participating stores on certified devices | An app distributed outside Play still needs a verified developer behind it; Google says the rule goes global in 2027 |
| Feb 2027 | Memory usage, bitmap memory and code optimisation may affect store visibility | Memory measured against your users’ RAM tiers; R8 enabled |
| Targeting Android 17 (API 37) | Next year’s target if the yearly pattern holds | No orientation opt-out on large screens, a runtime permission for the local network, static final fields locked against reflection |
Which Android codebase are you looking at
| What you see in the code | What it tells you |
|---|---|
android:configChanges="orientation|screenSize" on most activities | Someone silenced rows 5 and 9 instead of saving state; rows 11–12 still lose it |
android:screenOrientation="portrait" | Ignored on screens 600 dp and wider for apps targeting API 36; no opt-out from API 37 |
override fun onBackPressed() | Not called for apps targeting API 36; use OnBackPressedCallback |
GlobalScope.launch | Work nobody cancels — it outlives the screen it was started for |
AsyncTask | Deprecated since Android 11; code from before coroutines |
kotlinCompilerExtensionVersion in build.gradle | The Compose compiler set up as before Kotlin 2.0; it now ships with Kotlin as a Gradle plugin |
LiveData, XML layouts and findViewById | The View era; it works, and new screens go to Compose with StateFlow |
targetSdk below 35 | Invisible to new users on newer Android since 31 Aug 2026 |
Five cases, and what each one was missing
Android’s cases share one shape: something the app does not control — the system, a shared component, a manufacturer, another app — changes underneath it. Each is documented by the people involved: a security firm’s disclosure, Google’s own documentation and statements, the companies whose users were affected.
| Case | What happened | What was missing |
|---|---|---|
| Stagefright, Jul–Aug 2015 | Bugs in Android’s media library, reachable by a single MMS, exposed an estimated 950 million devices | An update path that did not wait for every manufacturer and carrier |
| Android 7.0, Aug 2016 | Oversized saved state, until then silently dropped, began to crash apps targeting 7.0 | Saved state kept small — ids, not data |
| Google Home, 2020 | New features written in Kotlin; NullPointerExceptions, the most common crash type in Play Console, fell by 33% | Nothing — the type system did the work |
| Android System WebView, 22 Mar 2021 | An automatic WebView update crashed Gmail and many other apps that had shipped nothing | Crash monitoring that splits by the version of a system component, not only the app’s own |
| Teams and emergency calls, Dec 2021 | Teams, installed but signed out, registered phone accounts again and again; on some Pixel phones, 911 calls failed | A platform API used in a loop no test covered, on the one path nobody can test in production |
The WebView case shows what that means in practice. On 22 March 2021 an update to Android System WebView — the component that draws web content inside other apps, updated through Google Play — reached phones automatically, and apps across the ecosystem began to crash: Gmail, the Google app, Amazon, Discord, Outlook, banking apps. None of them had shipped anything. Google confirmed the problem within hours and released WebView and Chrome 89.0.4389.105, and users were told to update both. For an app team, the lesson is in monitoring: a crash spike with no release behind it is a system component until proven otherwise, and the crash reports have to carry the WebView version to show it.
The fifth case is the most serious and the most instructive. In December 2021 a user reported that a 911 call from a Pixel phone had failed: the phone showed a call, rang once and connected to nothing. Google traced it to an unintended interaction with Microsoft Teams. When Teams was installed but the user was not signed in, it registered a phone account with Android’s telecom service again and again, and on some Pixel phones the duplicates broke the emergency call path. Microsoft released a fixed Teams within days, and Google shipped its own platform fix in the January 2022 update. A platform API called in a loop is an ordinary bug. The lesson is that an app’s calls into shared system services reach paths the app’s own tests cannot — and an emergency call is a path nobody can try in production.
Where it degrades
Android is generous to a team that designs for the system’s ownership of the app and unforgiving to one that assumes the process stays alive. The language and the toolkit are good; the failures come from the events in the table and from the phones the team does not own. Almost every failure is one of these:
- Screen state held in the activity, which empties on the first rotation (rows 5–10).
- Nothing in saved state, so the app comes back blank after the system reclaims memory (rows 11–12).
- Too much in saved state, so it crashes on the way into the background.
configChangesused to silence rotation instead of saving state.- Work in
GlobalScope, and coroutines that swallow their own cancellation. - Flows collected without regard to the lifecycle, keeping sensors and the network running in the background.
- State read in composition that could be read in layout or drawing, and new objects from the data layer on every emission.
- Background work assumed to run, wake locks held on failure paths, and no test on an aggressive manufacturer’s phone.
- Testing only on a flagship and an emulator, which hides every memory and frame problem your users actually have.
- Play’s calendar — target API, 16 KB pages, vitals thresholds — discovered when an update is rejected.
The honest limit is reach without control. Android runs on more kinds of devices than any other system, from 2 GB phones to foldables and desktop windows, and that reach is the reason to build for it; in much of the world it is where most users are. The same reach means the app never knows the device it runs on, the system reclaims it whenever it likes, and parts of the platform beneath it update on someone else’s schedule. No architecture removes that. A good one makes every event in the table survivable, measures what happens on the phones the team does not own, and treats Play’s yearly target as a fixed item in the plan.
The practical check takes ten minutes. Read targetSdk, minSdk and the Kotlin version, and find them in the calendar table. Search for configChanges, GlobalScope, onBackPressed, catch (e: Exception) around suspending calls, and .collect { outside repeatOnLifecycle. Put the app in the background on the busiest screen, run adb shell am kill, and reopen it from Recents. Rotate every screen once. Open Android vitals and read the crash and ANR rates per phone model, not only overall. And check which of your SDKs take wake locks.
When to use it
Use it when
- Products whose users are mostly on Android — in much of the world that is the great majority of them.
- Apps that need deep system integration — background sync, widgets, sharing, custom keyboards, accessibility services.
- Anything that must run acceptably on low-end hardware, where a native build has room the alternatives do not.
- Teams already on the JVM — Kotlin is a short move, and Kotlin Multiplatform can later share the logic with iOS.
Avoid it when
- Building both platforms natively with one small team, which doubles the surface without doubling the people.
- Designs that assume a fixed screen size or orientation — the platform now overrides both on large screens.
- Architectures that assume the process stays alive, which is the assumption Android specifically does not honour.
- Products that cannot commit to the yearly target API upgrade, which is a hard deadline on this platform.
Sources and method
What this page stands on
- 15 sources
- 3 documented failures
- Checked October 13, 2026
Practices and where the terms come from
the sixteen events, what survives, and the platform’s limits- DocumentationParcelables and bundles (opens in a new tab)Android Developers
- DocumentationAndroid 7.0 Behavior Changes (opens in a new tab)Android Developers
- DocumentationAndroid 17 — Behavior changes: all apps (opens in a new tab)Android Developers
- DocumentationAndroid vitals (opens in a new tab)Android Developers
- DocumentationANRs (opens in a new tab)Android Developers
- DocumentationJetpack Compose phases (opens in a new tab)Android Developers
- DocumentationStrong skipping mode (opens in a new tab)Android Developers
- DocumentationAndroid developer verification (opens in a new tab)Android Developers
- DocumentationTarget API level requirements for Google Play apps (opens in a new tab)Play Console Help
- DocumentationKotlin release process (opens in a new tab)Kotlin Documentation
The failures this page learns from
Stagefright, the WebView update and Teams, in “Five cases”- ResearchExperts Found a Unicorn in the Heart of Android (opens in a new tab)Zimperium · Jul 27, 2015
- ArticleStagefright (bug) (opens in a new tab)Wikipedia
- ArticlePSA: If your Android apps keep crashing, update ‘WebView’ and Chrome (opens in a new tab)9to5Google · Mar 23, 2021
- ArticleMicrosoft Teams app blocks 911 calls on Android, Google issues guidance (opens in a new tab)Windows Central · Dec 2021
Research
Google Home: what Kotlin did to the crash rateResearched with Claude. Finding and cross-checking the primary sources was done with Claude (Anthropic). Selection, writing and fact-checking: the Anatomy of IT Product editors.
Found this useful?
Share it with someone who is working on the same problem.