EEltaCrew

Field notes

I build and run 24 Android apps and 6 web services. These are the numbers I measured and the problems I hit along the way — console figures, real-device results, answers from Google support — nothing copied from elsewhere.

Why our lottery ticket QR scanner showed zero successes: a path you don't log looks like a failure

In our lottery app's weekly report, 19 people had opened the QR screen and GA4 showed zero successful scans. The scanner wasn't broken. The path that real ticket QR codes took had no logging at all. How we found the measurement gap, what four similar apps do, why we switched to the bundled scanning engine, and the numbers one week after the fix.

2026-10-22 · Android · GA4 · ML Kit

Tapping the logo in the map's corner crashed the app: Naver Map SDK and the AppCompat theme

Four "You need to use a Theme.AppCompat theme" crashes showed up in Crashlytics for our lottery store map app. They came not from users but from the Play pre-launch report's test robot tapping the NAVER logo in the bottom-left corner of the map. The cause, a fix that wraps only the map instead of changing the whole app theme, and a second problem that appeared in dark mode.

2026-10-19 · Android · Naver Map SDK · Jetpack Compose

Requesting ads before the SDK finishes initializing: why the same crash came back three times after we added a guard

After we first fixed the "MobileAds.initialize must be called" crash in our live apps, the same crash came back three more times in different shapes. We had a guard that waited for initialization to finish, but a flag set at the start, a flag set on consent alone, and new ad slots that skipped the guard all left gaps. The cause of each case and the results of checking all 23 apps.

2026-10-15 · Android · AdMob · Google Mobile Ads SDK

A crash from one line of image downsampling: inSampleSize starts at 0

To save memory, we changed the document thumbnails in our QR scanner app to load downsampled. In the next version, the app closed every time the document list opened. The cause was that BitmapFactory.Options.inSampleSize defaults to 0. The code we changed, the crash data, the fix, and how we checked for the same mistake elsewhere.

2026-10-13 · Android · BitmapFactory · Crashlytics

The crashes Crashlytics didn't show: it only sees the builds you added it to

Three days after adding Firebase Crashlytics to 21 apps, we found a user-facing crash in Play Console first. Crashlytics only reports from builds that include the SDK, and crashes from older versions still on users' phones pile up only in Play vitals. Results from checking all 21 apps, and the order we check in now.

2026-10-08 · Android · Crashlytics · Play Console

The day a sync deleted 8,802 stores: one renamed API field and a 100-row list

In our lottery retailer map app, a sync turned every store name into "Unknown" and wiped the 8,802 stores bundled with the app. Three causes — a renamed field in a public data API, a sync that deleted rows based on only the first 100 results, and a geocoder reading keys that do not exist — and how each was fixed.

2026-10-07 · Android · Room · Public data API

Why users quit at the TV pairing code screen: a 6-character code and a Korean keyboard

After fixing a pairing bug in our TV remote app, the share of users who cancelled on the code entry screen went from 9% to 19%. How the GA4 failure reasons were read, how one input field turned out to open the Korean keyboard, and what was changed.

2026-10-06 · Android · EditText · Keyboard

dispatchDetachedFromWindow NullPointerException: tracking an Android crash with none of my code in the stack

MdViewer hit a NullPointerException whose stack trace contained only framework frames. The cause was one line that removed a sibling view inside onDetachedFromWindow, combined with how a parent ViewGroup walks its child array. How it was reproduced, why it happens and how it was fixed.

2026-10-01 · Android · Crash · View

How to open .md files on Android when AI-generated markdown shows up as raw symbols

Open a .md file from ChatGPT, Claude or Codex, an Obsidian note or a GitHub README on your phone and you often see raw #, * and |. Why that happens, three ways to read markdown properly on Android, and what breaks most often, from building a markdown viewer.

2026-09-29 · Android · Markdown · Productivity

R8 on, build green, app broken: five runtime traps that actually hit across 15 apps

I enabled R8 in 15 apps for Play's 2027 code-optimization requirement. Every build passed, but 2 of the first 7 I installed broke at runtime. Gson deserialization, getIdentifier resource lookups, Room _Impl classes, and debuggable builds that silently disable R8: the kinds of failure that never show up in a crash log.

2026-09-16 · Android · R8 · Google Play

One merchant account blocked releases for all 21 of my apps: Korean individual developers and Play Console's "additional information required"

Right after I set up a merchant account to test a donation in-app product, Play Console demanded a business registration number and an e-commerce license number and blocked every release on the account. Deleting the products did not help, deleting the payout account did not help, and support's final answer was "this cannot be reversed". How an individual developer avoids this trap.

2026-09-16 · Google Play · Play Console · policy

Data safety forms with zero declarations are getting caught: auditing 21 apps and fixing them with CSV and the API

A phone number the user types in by hand, belonging to someone else, still counts as "phone number collection" to Google. After one rejection I compared all 21 apps' data-safety declarations against their source: 11 were wrong, and 3 had declared nothing at all. Why ad-only apps cannot declare zero, and how to fix the form with CSV and the API instead of the five-step wizard.

2026-09-16 · Google Play · data safety · policy

The #1 app in Play search has the query in its title, verbatim: how one middle dot killed our keyword matching

I measured 157 Korean Play search queries by hand. The top-ranked app always carried the exact query string, spacing included, in its title. Our apps had been invisible for QR queries because I had joined words with a middle dot to make the title look nicer. The evidence behind retitling 13 apps.

2026-09-16 · ASO · Google Play · store optimization

A 301 cannot be taken back: how 43 minutes of a wrong redirect came back as a 404 five days later, plus the Cloudflare edge-cache incident

Moving two web services to subdomains, a broken 301 went out for 43 minutes. The server was fixed at once, but the browser was still following that 301 into a 404 five days later. What to do before emitting a permanent redirect, the only way to rescue one already sent, and the day a deploy "did nothing" because Cloudflare's edge kept the old CSS.

2026-09-16 · web · deployment · HTTP

One language per page: why I dropped IP-country detection and bilingual pages for browser language plus hreflang

Six web services each picked their initial language differently. The one using IP country served English to Googlebot only, so the search-result language could not be controlled; the landing page mixed Korean and English on one page, against Google's "one language per page" expectation. How I unified every site under one rule.

2026-09-16 · web · SEO · localization

Same app, same users, native ads paid 38x more per 1,000 impressions than banners, and why I stopped short of deleting the banner units

Seven days of AdMob data from two TV remote apps, comparing revenue per 1,000 impressions for banners and native advanced ads. How over-exposure kills the rate, how to read native's low fill rate, and why I aborted deleting the banner ad units the next day.

2026-09-16 · AdMob · ad revenue · native ads

Why switching language inside the app sometimes does nothing: setApplicationLocales only recreates activities that are on screen

"I switched to English and it stayed Korean until I restarted the app." The cause is that AppCompat recreates only the activities that are started at that moment; screens that were stopped behind it come back in the old language. The fix I applied to 8 apps, and five traps that came with it.

2026-09-16 · Android · localization · AppCompat

Seven rules I rewrote 13 home-screen widgets against, after placing them next to Samsung's

Putting 13 widgets from 5 apps on a real home screen beside Samsung's weather and wallet widgets showed that "the code exists" and "it looks like a shipped product" are very different. System dark mode, designed empty states, previewLayout and label, dp corner radii, and the theme lag of bitmap widgets.

2026-09-16 · Android · home widgets · UI

Why I put forced in-app updates (IMMEDIATE) into 17 apps: users on old versions earned nothing after the ad SDK swap

When I replaced the ads SDK in July 2026, users who had not updated produced zero revenue. No fix, policy or consent form reaches an old version. How I added Play In-App Update in IMMEDIATE mode to every app, why it can only be verified on a Play-installed build, and what shipped alongside it.

2026-09-16 · Android · Google Play · in-app update

I no longer pick store keywords myself: mine rival titles, verify with autocomplete, measure rank

When I choose the seed words, the result is "my idea of ASO". I switched to scraping the titles of apps that share our search results, keeping only words Play autocomplete confirms as real queries, and measuring where we rank for each. Includes the mistake where one-character prefixes made me miss every core keyword.

2026-09-16 · ASO · Google Play · store optimization

My AdMob account had zero GDPR consent messages: adding UMP to 21 apps in one day

A new app's release log said "no form(s) configured". The AdMob account had no European-regulation consent message at all, and only 3 of 17 live apps even contained UMP code. The order of operations to create the message, add the code to 14 apps and re-release, plus the traps along the way.

2026-09-16 · AdMob · GDPR · UMP

Ad revenue is set by session time, not downloads: AdMob numbers across 15 apps

Eleven apps with more monthly users produced 27 times fewer ad impressions than four TV remote apps. Where the gap between 7.68 and 0.18 impressions per user per day comes from, and how it changed the order I do marketing in.

2026-09-16 · AdMob · ad revenue · app operations