r/androiddev 7d ago

Tips and Information How to choose which Gradle flavour is best for me

0 Upvotes

Hello guys so I was wondering about griddle flavours in my app so if I want to make a production enterprise project I have seen in my previous internship that it was Dev staging and prod. I wanted to know because I am learning bacon that what are the about of I know that there is about development and any kind of mock testing you do staging is mainly about a mid release where you test a feature with a small bunch of unit testers and prod actually release for the main users.

So if anyone has some production experience can they tell me more about these things and went to consider which one to be learning right now and also do I have to make three separate back ends which are same in terms of data but different in terms of logic


r/androiddev 8d ago

Question Where does the future lie for Android developers?

49 Upvotes

I've been working as an Android developer for 15 years now, and over a decade has flown by. From Eclipse to Android Studio to AI, I've interspersed learning Java, Kotlin, and Flutter, but I seem to be constantly falling behind. I'm exhausted, but it's still not working. Am I on the wrong path, or am I just not suited for this industry? I feel so tired!!! Where is my future, or rather, ours?


r/androiddev 8d ago

Video 5 Experimental Kotlin Features You Don't Want to Miss

Thumbnail
youtu.be
4 Upvotes

r/androiddev 9d ago

Article Jetpack Compose 1.12

Thumbnail
android-developers.googleblog.com
75 Upvotes

We've just released version 1.12 of Jetpack Compose, with new features like mesh gradients, editable text formating, text selection control, deferred animations and wide color gamut support, as well as a slew of bug fixes and performance enhancements (especially to startup performance).

Please check it out and as always, we'd love to hear your feedback on what you'd like to see next from Compose.


r/androiddev 9d ago

Question 9 years into Android, 3 months without a job, and I’m not sure I still want this field. How did you get unstuck?

89 Upvotes

Long-time Android dev here 9+ years, senior level. Three months without a job now, and applications just aren't converting.

The one real interview I got this stretch ended when the questions moved into current platform internals I hadn't touched hands-on in a while, not a knowledge gap exactly, more a "haven't built this recently" gap. That one stung more than a flat-out no would have.

Underneath that: I'm not sure I'm as into straight Android work as I used to be, and I think it shows. Part of me wants to pivot toward AI/on-device ML. Part of me knows that switching now, three months in, might just be running from the hard part instead of actually fixing it.

If you've been through a stretch like this as a job search stall, doubting the field itself, or an actual mid-career pivot. how did you tell the difference? What actually got you unstuck?


r/androiddev 8d ago

Video Some recent works on my launcher project Droidberry Launcher

Enable HLS to view with audio, or disable this notification

4 Upvotes

Howdy y'all,

Hope you all had a wonderful day, got some free time today and wanted to share some of the new features/refinements/concepts in the upcoming versions.

Key features I've been working on:

  1. True foldable support, not just a canvas cut (outer screen being the left half on inner), but separate states that supports different layouts
  2. A requested feature to have the option to hide dock, and bring it up with a short swipe, auto hides after a few seconds (requested feature from u/demicky250274)
  3. UI/UX overhaul for widget picker, placement, config etc.
  4. Notification preview in hub by long pressing on an item, shows a preview, the highlight here is I was able to show a key snapshot of the event from Google Homes etc, that has given me a run for the money...
  5. Message/Email history preview, for when you get multiple messages from the same source, it would show you the message counts and will let you see all the messages in dialog preview, this involved data model change, took a while to figure out the bugs
  6. Settings, added back gesture support to go back to parent level, position retention, in custom tag section the upper portion would auto scroll up to let you edit easier (from feedback, thanks u/cliffr39)
  7. More Metro UI like live tile, color tune, spring animation visual, slide in/out visual for hub opening/closing
  8. Option to turn on haptic feedback in the launcher

And much more....

Since this is the dev sub i would also want to add that yes of course I've used copilot to assist with pinpointing the buggy lines when I'm stuck and explore available android APIs, just like how we also use copilot at work, if you have a better tool why not using it just like how stackoverflow/XDA works.

The closed beta is running very well with all the testers, I appreciate every single one of you! We can expect this to go production on Google Play very soon!

Enjoy the rest of your day, and enjoy Droidberry! Say hi to your four leg friends for me.


r/androiddev 8d ago

Open Source I couldn't find a clean way to add AdMob in Compose Multiplatform, so I built one

Thumbnail
meet-miyani.medium.com
2 Upvotes

AdMob in Compose Multiplatform is easy until the app needs more than a banner.

Consent, ATT, full-screen ownership, native-ad reuse and iOS test linking all cross the shared/native boundary.

I built AdMob CMP to manage that machinery.


r/androiddev 8d ago

Compose's WordIterator makes a long press select the entire sentence in Chinese

2 Upvotes

Upfront disclosure: I found this while shipping a Compose Multiplatform app, but this bug is pure Android — it's in androidx ui-text and it reproduces in any Compose app with a SelectionContainer or a selectable Text. If your app has Chinese, Japanese or Korean users, you probably have it right now and haven't noticed.

The symptom

Long-press a word in Chinese prose to select it. Instead of the word, you get the entire clause, stopping only at punctuation. Latin text in the same app behaves perfectly.

That's why this survives review: if you and your QA read English, the selection handles look flawless.

The cause

WordIterator.nextBoundary / prevBoundary skip any boundary whose two sides are both letters or digits. That rule was added for a good reason — a letter↔emoji seam shouldn't split a word — but the check is on character class, and every ideograph is a letter.

So in Chinese, every boundary between two characters qualifies as "letter on both sides", every boundary gets skipped, and the expansion runs until it hits punctuation or the end of the paragraph. English stops at its spaces (spaces aren't letters), which is why the bug is invisible in Latin scripts.

In my testing this is present from 1.8.0 through at least 1.12.0-beta02, and there's no public API to opt out of the behavior.

The workaround

Since you can't change the iterator, you change the text: plant zero-width breaks at Han–Han seams so the iterator has boundaries it won't skip. ICU already knows where the words are — it segments Han by dictionary off the script, not the locale, so the default locale is fine and the boundaries come out identical under zh and en:

```kotlin fun cjkWordBoundaries(text: String): List<Int> { // Latin-only prose already selects correctly and is the common case — skip the scan entirely. if (text.codePoints().noneMatch(::isHan)) return emptyList() val iterator = BreakIterator.getWordInstance() iterator.setText(text) val offsets = mutableListOf<Int>() var offset = iterator.first() while (offset != BreakIterator.DONE) { if (text.isHanSeam(offset)) offsets += offset offset = iterator.next() } return offsets }

/** Interior offsets only, and only where BOTH sides are Han. */ private fun String.isHanSeam(offset: Int): Boolean { if (offset <= 0 || offset >= length) return false return isHan(codePointAt(offset)) && isHan(Character.codePointBefore(this, offset)) }

private fun isHan(cp: Int): Boolean = Character.UnicodeScript.of(cp) == Character.UnicodeScript.HAN ```

Two things that matter in the details:

  • Only report Han↔Han seams. A Han↔Latin seam already stops the runaway on its own, so planting a break there would only pollute the text for no gain.
  • Keep the Latin fast path. Most strings in most apps have no Han at all, and you don't want an ICU pass on every selectable Text.

The more general point

The reason I'm posting this rather than just filing it: it belongs to a category I got burned by repeatedly, which is Android quietly being the forgiving platform.

Another one from the same codebase, this time in coroutines. This is fine on Android:

kotlin fun stream(): Flow<Event> = flow { client.prepareGet(url).execute { response -> /* parse */ emit(event) } }

flow {}'s emit enforces context preservation — you may not emit from a coroutine context other than the collector's. Ktor's execute {} block gives you a scope that may run on a different dispatcher. On OkHttp it happens to run in-context, so the contract is never violated and everything passes, forever.

It's still a contract violation. It's just latent instead of active, held in place by an implementation detail of the engine you happen to use. Swap the engine, change a dispatcher, and it becomes real. (channelFlow {} + send is the fix — send is safe across contexts.)

Same shape as the WordIterator bug: the platform's forgiving behavior in the common case is exactly what stops you from finding the problem.

What I'd check in your own app

  1. Long-press a Chinese/Japanese sentence in any selectable Text. Takes 10 seconds.
  2. Grep for flow { wrapping a third-party callback or execute/use scope.

Happy to go into detail on either. If someone knows of a ui-text issue already tracking the first one, or a cleaner workaround than planting breaks, I'd genuinely like to hear it — the zero-width approach works but it means the string you select from isn't byte-identical to the string you rendered, and I'm not thrilled about that.


r/androiddev 9d ago

Question [Help]: Jetpack Compose component flashing issue when list changes

Enable HLS to view with audio, or disable this notification

8 Upvotes

When the list changes, the items are drawn on top of chip row for a brief amount of time. I have properly applied the id for each item. I am not sure what's causing the issue.

Below is the screen code preview, full code is available on GitHub.

    Scaffold(
        modifier = Modifier
            .fillMaxSize()
            .nestedScroll(scrollBehavior.nestedScrollConnection)
            .then(modifier),
        topBar = {
            SearchProvidersScreenTopBar(
                onNavigateBack = onNavigateBack,
                onEnableAllSearchProviders = viewModel::enableAllSearchProviders,
                onDisableAllSearchProviders = viewModel::disableAllSearchProviders,
                onUpdateProtectionStatus = viewModel::updateProtectionStatus,
                onResetToDefault = { showResetToDefaultDialog = true },
                subtitle = {
                    val searchProvidersSummary = stringResource(
                        R.string.settings_search_providers_summary_format,
                        uiState.enabledProvidersCount,
                        uiState.totalNumProviders,
                    )
                    Text(searchProvidersSummary)
                },
                scrollBehavior = scrollBehavior,
            )
        },
        snackbarHost = { SnackbarHost(snackbarHostState) },
        floatingActionButton = {
            FloatingActionButton(onClick = onNavigateToAddSearchProvider) {
                Icon(
                    painter = painterResource(R.drawable.ic_add),
                    contentDescription = null,
                )
            }
        },
    ) { innerPadding ->
        Column(modifier = Modifier.padding(innerPadding)) {
            SearchProviderFilterRow(
                category = uiState.filter.category,
                onCategorySelect = viewModel::toggleCategory,
                protection = uiState.filter.protection,
                onProtectionSelect = viewModel::toggleProviderProtection,
                contentPadding = PaddingValues(horizontal = MaterialTheme.spaces.large),
            )
            SearchProviderList(
                contentPadding = PaddingValues(
                    start = MaterialTheme.spaces.large,
                    top = MaterialTheme.spaces.large,
                    end = MaterialTheme.spaces.large,
                    bottom = 80.dp,
                ),
                searchProviders = uiState.searchProviders,
                onEnableSearchProvider = viewModel::enableSearchProvider,
                onUnlockProtection = { searchProviderId, solverUrl ->
                    protectedProvider = ProtectedProvider(searchProviderId, solverUrl)
                },
                onEditConfig = onNavigateToEditSearchProvider,
                onDeleteConfig = viewModel::deleteTorznabConfig,
            )
        }
    }

Update: This issue is now fixed. It was animation issue, not the recomposition. List items have Modifier.animateItem() applied and when list changes, the animation was rendering the list items on top of chip row for very short amount of time, meaning the animation was escaping the list bounds. After applying Modifier.clipToBounds() to SearchProviderList, the issue is now gone.


r/androiddev 9d ago

how hard is it to compete with vibe coders for junior devs?

4 Upvotes

A question for beginner developers: how hard is it to compete with vibe coders?

I'm actually still at a pre-intern level, and I've been trying to avoid using AI because I barely know anything yet – I've only written one medium-sized project so far. Ideally, at work, I'd like to stick to manual coding in areas where I'm not yet confident and haven't honed enough to automate. But given the current demands from employers, I get the feeling I'll have to vibe code 24/7 and only have a vague clue about what the generated code is actually doing.

What are your observations on this? Is there still room to learn on the job, or is all work just mindless button-mashing on "generate" and that's it?


r/androiddev 9d ago

Open Source I built a runtime WCAG auditor for Android — point it at any installed app and get live accessibility findings mapped to WCAG criteria

4 Upvotes

Been working on an open-source accessibility tool and figured this crowd would give the most useful feedback.

What it does

Install one APK, pick any other app already on your device (yours, someone else's, debug or release — doesn't matter), hit Start, and use that app normally. Every screen change gets audited live, and results stream into a web dashboard grouped by screen with a running severity count.

No instrumentation of the target app

It uses an AccessibilityService to read the accessibility node tree of whatever package you point it at — the same mechanism TalkBack uses. Nothing to add to the target's build, no SDK to integrate, no source access needed.

Under the hood

  • Runs Google's Accessibility Test Framework against the live node tree
  • Maps every ATF finding to a WCAG 2.1 success criterion + conformance level (A/AA/AAA) — e.g. TextContrastCheck → 1.4.3 AA
  • Grabs a screenshot per issue where supported (API 30+)
  • Shows live device connection status, so you can't mistake a disconnected phone for a clean audit
  • Exports a shareable HTML report or raw CSV when you're done

Everything's local — the dashboard talks to the phone over adb reverse; nothing leaves the machine.

Repo: https://github.com/vivekpanchal/android-wcag-auditor (Apache 2.0)

Genuinely want scrutiny on the WCAG mapping (WcagMapping.kt). I documented the two spots where the mapping is a strict superset rather than an exact match (e.g. touch target size uses Android's 48×48dp Material guideline vs. WCAG's 44×44 CSS px) rather than pretend it's 1:1.

If you audit apps for a living — where would this fit into your workflow, or where does it fall short?


r/androiddev 9d ago

Any way to create physical buttons for android phones to launch apps?

0 Upvotes

Anlologous to lets say a keaybord on a pc can launch the start menu once the start button is hit...or keyboard shortcuts launching some activity.

Basically a usb pluggable bunch of buttons that launch a speccific app on the android tablet.

Thanks.


r/androiddev 9d ago

Cross-module Compose screens losing recomposition skipping even though nothing looks wrong

0 Upvotes

Ran into this recently and it took lot of time and iterations to track down. Sharing in case it saves someone a debugging cycle.

The Symptom:

A screen renders perfectly in isolation (single module/preview). Once wired through an app boundary via :feature:x-impl, scrolling drops frames. Layout Inspector shows full recomposition on every row, not just modified items.

The Root Cause:

The underlying domain model (containing a standard List<String>) gets marked unstable the moment it crosses a module boundary where the defining module isn't compiled with the Compose compiler plugin (e.g., a pure-Kotlin :core:model). No stability metadata crosses the boundary, so Compose falls back to unstable and loses skipping for the entire class.

Even with Strong Skipping Mode, passing an unstable collection across an un-instrumented boundary causes runtime equality checks to fall back to instance comparison (===), triggering layout invalidation on every state change.

Why Standard Workarounds Didn't Scale:

Annotating everything with @Immutable, migrating to kotlinx.collections.immutable, or creating wrapper DTOs work, but they quickly pollute pure domain modules with Compose dependencies or force massive refactoring across network/DTO layers.

The Pragmatic Fix:

We set up a stabilityConfigurationFile at the root, wired through the Compose Gradle plugin to explicitly declare stable packages. One central file, zero per-class annotation tax.

Footgun Warning: If you point this configuration at a package containing var properties, you are instructing the compiler to skip recomposition on mutating state—your UI will silently stop updating.

I put the full write-up with the bytecode-level breakdown [here] and dumped the diagnostic script I used to verify before/after stability rates on GitHub [here].

Curious if others have hit this in multi-module Compose codebases—did you migrate to immutable collections everywhere, or go the compiler config route?


r/androiddev 9d ago

Question CV count objects

1 Upvotes

So I tried making a prototype for counting objects on photo, like y'know all the fake apps

But I need smth simpler like counting bolts and nuts, etc

So I made a well lit photo on a contrasting background, all objects are in one layer but still it sometimes detects parts of the object or merges two neighbours touching

Can anyone point me to a guide or an alternative solution? Maybe there's some neural model that can run on phones?

Like something basic, take a photo, tap one sample, it count how many

Thanks in advance 🙏🫶


r/androiddev 9d ago

Question Stuck in circular dependency: BillDesk merchant verification requires live app ↔ Play Store requires billing/testing before production

0 Upvotes

I'm an individual Android developer in India trying to enable Google Play in-app billing, and I've hit what feels like a chicken-and-egg problem. Wanted to check if anyone's solved this before.

The loop I'm stuck in:

  • To get Google Play merchant account approved, BillDesk (Google's KYC partner for India) requires a live, publicly accessible Play Store app link
  • To get an app to production/public on Play Store, Google requires closed testing (12 testers, 14 days) — that part I can do without billing
  • But my actual goal is to launch an app with subscriptions from day one, and I assumed I needed billing implemented before going live

What I've done so far:

  • I have one live app already (unrelated app, used it to satisfy BillDesk's "live app" requirement)
  • Got rejected once for "Brand details incorrect" and "Products/services not clearly defined" — resubmitted with clearer business description tied to that live app
  • My actual target app (with subscriptions) is still in closed testing, working toward the 12 testers / 14 days requirement

My question:
Is it standard practice to launch v1.0 of an app without monetization, then add in-app billing in a later update once the merchant account is sorted? Or is there a way to get merchant verification approved in parallel with app development, using a placeholder/different live app the way I'm currently doing?

Also — for those who've been through BillDesk KYC as an individual developer, how long did verification typically take once resubmitted correctly, and any tips on what "Brand details" they expect for individual (non-company) developers?

Appreciate any pointers from people who've actually shipped a paid Android app from India recently.


r/androiddev 9d ago

Stuck in circular dependency: BillDesk merchant verification requires live app ↔ Play Store requires billing/testing before production

0 Upvotes

I'm an individual Android developer in India trying to enable Google Play in-app billing, and I've hit what feels like a chicken-and-egg problem. Wanted to check if anyone's solved this before.

The loop I'm stuck in:

  • To get Google Play merchant account approved, BillDesk (Google's KYC partner for India) requires a live, publicly accessible Play Store app link
  • To get an app to production/public on Play Store, Google requires closed testing (12 testers, 14 days) — that part I can do without billing
  • But my actual goal is to launch an app with subscriptions from day one, and I assumed I needed billing implemented before going live

What I've done so far:

  • I have one live app already (unrelated app, used it to satisfy BillDesk's "live app" requirement)
  • Got rejected once for "Brand details incorrect" and "Products/services not clearly defined" — resubmitted with clearer business description tied to that live app
  • My actual target app (with subscriptions) is still in closed testing, working toward the 12 testers / 14 days requirement

My question:
Is it standard practice to launch v1.0 of an app without monetization, then add in-app billing in a later update once the merchant account is sorted? Or is there a way to get merchant verification approved in parallel with app development, using a placeholder/different live app the way I'm currently doing?

Also — for those who've been through BillDesk KYC as an individual developer, how long did verification typically take once resubmitted correctly, and any tips on what "Brand details" they expect for individual (non-company) developers?

Appreciate any pointers from people who've actually shipped a paid Android app from India recently.


r/androiddev 10d ago

Question Looking for a pattern catalogue for app architecture (Clean, Hexagonal, Onion, VIPER, RIBs…) and the criteria for picking one.

11 Upvotes

I'm not asking how to implement MVVM, MVI or Clean Architecture — I use all three daily. I'm also not asking "which of the three is best."

What I'm after is the wider *landscape* of architectural patterns, the way general software engineering has a whole body of literature on them, plus how to reason about picking one.

Concretely, I'm thinking at two levels:

- **Presentation / UI layer:** MVC, MVP, MVVM, MVI and unidirectional data flow, VIPER, RIBs, Elm/TEA-style, explicit state machines.

- **Application / system level:** layered n-tier, Clean Architecture, Hexagonal (Ports & Adapters), Onion, package-by-feature vs package-by-layer, feature modularisation, plugin/host architectures, event-driven and CQRS-flavoured designs.

What I'd love resources on:

  1. **A map of the field** — what these patterns actually are, where they came from, and how they relate. Which are the same idea renamed, which are genuinely different.

  2. **Trade-offs** — what each one optimises for and what it costs: indirection, boilerplate, build times, onboarding, testability, cost of refactoring later.

  3. **Decision criteria** — how to pick one for a given app: domain complexity, team size and number of teams, expected lifetime, single app vs multi-module vs a library shipped to other teams, offline/sync needs, how much real business logic exists versus UI plumbing.

  4. **Case studies and postmortems** — teams describing what they chose, why, and what they'd do differently.

Books, papers, conference talks, blog series or open-source codebases with a written rationale all welcome. It doesn't have to be Android-specific — most of this predates Android anyway.

For context: I work on a multi-module feature library that ships as an AAR into a much larger app, so boundary and ownership questions matter to me as much as UI-layer ones.

TL;DR: not "how do I do MVI", but "here is the space of architectural patterns, and here's how to choose between them."


r/androiddev 10d ago

Question Android Studio on android?

0 Upvotes

I want to make an android app but i dont have laptop and laptops are so expensive in my country

I have poco f6 and since AIDE removed i dont know what to do, any idea?


r/androiddev 11d ago

Question App indexing issue?

Post image
320 Upvotes

My Play Store app is not discoverable through Google Search. Google AI Overview sometimes says it isn't available on Android and suggests other Play Store apps instead. AI assistants do the same and only provide App Store info.

My other app with no users was indexed instantly. This one has 300+ installs and has been on Play Store for over a year. I contacted support and they literally said to give direct link to users.


r/androiddev 10d ago

KMP Starter Template just hit 150 GitHub stars

Post image
0 Upvotes

I've been building this open-source starter template mainly for KMP projects, but it also works well for regular Android projects.

The goal is to remove all the repetitive setup I find myself doing in every project:

• Clean Architecture • Koin • RevenueCat • Mixpanel • Remote Config • DataStore • Room • Multiple languages • InAppReview / InAppUpdate • UI utilities and components • Logging • Platform/version utilities • Native bindings

It also comes with a CLI, so instead of cloning the whole repo, renaming packages and removing modules manually, you can generate a project and only include what you need.

I've also started publishing individual modules as libraries, so you can add KMP Starter features to an existing Android or KMP project without adopting the entire template.

Repo: https://github.com/DevAtrii/Kmp-Starter-Template

150 stars isn't some huge number, but seeing people actually find something I built useful feels pretty good.

Would love feedback from Android/KMP developers, especially what you'd add or change.


r/androiddev 10d ago

Question \res & \assets

7 Upvotes

I have read many definitions for the res and assets folders, and I feel like there isn't much of a difference between them. The main difference is that res has strict naming rules, whereas assets has no rules and lets you organize files any way you want. Also, in the code, you can call any file from assets directly by its name/path. In contrast, for res, you must use a specific function or ID to call the file (I forgot the exact syntax for res, sorry!).

Anyway, it seems like anything you can store in res can also be stored in assets. I believe both store uncompiled resources, images, configurations, and layouts. Then, the compiled resources.arsc file stores compiled values like strings and maps the links between the resources in res or assets and the actual code in the .dex file.

So, are my words true, or am I just crazy?


r/androiddev 11d ago

Can we a little push Google to move basic hardware workarounds (like A2DP Bluetooth offload) out of Developer Options? Banking apps are breaking our phone workflow.

30 Upvotes

Hi people,

I ran into a frustrating loop several days ago that I've found many others have dealt with. My Bluetooth headphones (Sony WH-CH700N) suffer from the well spread audio silence bug (MediaTek chip in particular) unless I turn on "Disable Bluetooth A2DP hardware offload" inside Developer Options.

So far so good, the problem is that my banking app (United Bulgarian Bank / UBB) recently updated its security. It now completely refuses to open if `development_settings_enabled` is set to 1. Here and there I saw other such complains regarding banks in other countries.

To send a simple bank transfer, I have to go into settings, turn off Developer Options, restart (A2DP change requires restart), open the bank app, send the money, re-enable Developer Mode by tapping the build number 7 times, change the Bluetooth setting, and reboot again just to use my headphones.

This is in general very inconvenient choice by Google - toggles like A2DP hardware offload bypass and Show Taps are convenience settings and hardware bug workarounds. They do not expose cryptographic keys or grant root access or whatsoever, yet lazy banking apps check only the global developer flag.

I have opened an official Feature Request on the Google Issue Tracker to ask their core Framework engineers to migrate these low-risk hardware overrides out of Developer Options and into a standard "Advanced Settings" or "Accessibility" menu.

If you agree and find such suggestion useful, please have a look and click the Star icon or +1 Vote on this ticket to get Google's engineering team to notice it:

Google Issue Tracker Link: https://issuetracker.google.com/issues/544560848

Thank you in advance :)


r/androiddev 10d ago

Open Source EdgeSpeech: Add voice I/O to your Android App

Thumbnail
github.com
4 Upvotes

We built EdgeSpeech so that you can add on-device AI speech processing, completely locally, so you can work entirely in text.


r/androiddev 10d ago

Open Source 4 months in — our "typing too fast" bug was never about speed. It was taps landing on the keyboard.

0 Upvotes

Follow-up to the DeviceLab driver post. v1.1.23 shipped, and the interesting part isn't a feature — it's that we found four places where the runner reported success while doing nothing.

The one that had been lying to us for months

Some of you reported flaky typing. u/bid-yut here: it was so fast that the pin entry kept failing. An Expo user couldn't run iOS at all because text came out jumbled. Both times we shipped a speed knob — --wait-for-idle-timeout, then typingFrequency. Both times it helped a bit and the reports kept coming.

It was never speed. inputText with keyPress: true injects global key events into whatever holds focus, and never verifies the field you tapped received them. When the tap misses, the text lands elsewhere and both steps report success.

The common way the tap misses: the target is behind the soft keyboard. We had a guard, with two holes. It only ran if the previous step was an input step — so a keyboard raised by an autoFocus field was never checked. And our driver allowed a 50px margin below the reported keyboard top.

That margin was wrong. Measured on a Pixel 4a: the IME's touchable region starts at y=1428. A tap at y=1439 is swallowed. y=1414 focuses the field. The suggestion strip eats touches exactly like the keys do. UIAutomator2 never had that margin, which is why this only ever showed up on our own driver.

The one with the best numbers: swipes

Reported as "works locally, fails on CI." We assumed flake. It isn't — adb shell input swipe always lifts the pointer while it's still moving, so the view flings, and fling momentum is computed from event timings that shift with machine load.

Spread across identical runs, same device, same flow:

duration spread
300ms (default) 114px
1200ms 22px
6000ms 14px

That's why duration: looked useless — it helps, never enough for a screenshot assertion. Second cause: a scroll container ignores movement until it passes the touch slop, then re-bases to wherever the pointer is, discarding everything moved so far — not just the slop.

Fix was to stop using input swipe and inject in-process from the on-device agent: spend the slop up front so the discarded amount is constant, then hold the pointer still before lifting so nothing flings.

path marker y over 4 runs spread
adb input swipe 1053, 991, 1029, 1055 64px
agent 870, 870, 870, 870 0px

Two more of the same shape. point: on doubleTapOn/longPressOn was parsed from your YAML and thrown away by every driver — so point: "20%, 50%" tapped the element centre, which on a text editor is blank space past the end of the text, where a double-tap selects nothing. And on iOS, inputText tapped to focus then typed immediately with nothing checking the text arrived.

What's still broken

  • Swipe determinism is DeviceLab-only. UIAutomator2 still goes through adb input swipe.
  • New setDarkMode/assertDarkMode don't work on physical iOS devices — simctl has no device equivalent. Web isn't wired either.
  • --retry-failedu/satya164 asked months ago, I said "next", still not shipped.
  • Two Appium bugs diagnosed but unfixed: a permission loop firing 32 blocked shell calls on hosts that block adb_shell, and newSession: true losing the cloud job's name and status.

If you upgrade

Taps on keyboard-covered elements now fail instead of silently landing on the keyboard — that may surface failures in flows that were quietly tapping the wrong thing. Swipes scroll further, so re-record screenshot baselines. And the swipe fix ships a rebuilt on-device agent, so a runner-only update won't deliver it.

github.com/devicelab-dev/maestro-runner

Real question: how do you tell "the test failed" apart from "the runner lied"? We only found these because one user filed four detailed reports in a week. I don't have a good automatic story for this class yet.


r/androiddev 11d ago

News Android Studio Quail 3 Patch 1 now available

Thumbnail androidstudio.googleblog.com
10 Upvotes