← Blog Mobile 30 September 2026 8 min read

Shipping the phone app on Android as sideloading closes

In 2025 Google announced that every Android app would need a verified developer behind it, even apps installed outside the Play Store. The first countries were set to switch on 30 September 2026. We put Luminair's phone app on Google Play in the same weeks. That timing made one question very concrete: what, exactly, makes an Android app yours?

Fig 01  Two timelines that met in SeptemberDates from the sources and git
GOOGLE · ANDROID DEVELOPER VERIFICATION AUG 2025 announced NOV 2025 advanced flow promised MAR 2026 registration opens AUG 2026 advanced flow and 20-device accounts 30 SEP 2026 enforced in four countries 2027 global rollout LUMINAIR · PHONE APP ON ANDROID 27 AUG sent to Play review 3 SEP config.xml 17 SEP “on Google Play” download page 22 SEP renamed 26 SEP screenshots Bottom axis spans August to September 2026 only and is not to the scale of the top one.
Google's dates from the Android Developers Blog, 9to5Google and The Hacker News. Luminair's dates from git commits and our Journal vault note on the Play submission.

The short version

  1. Google now requires a verified developer identity behind Android apps, including ones installed outside Play. Enforcement was set to start on 30 September 2026 in Brazil, Indonesia, Singapore and Thailand, with a global rollout in 2027.
  2. Luminair's phone app is one Capacitor codebase for iPhone and Android. It went to Play review on 27 August 2026, and our download page announced it on Google Play on 17 September.
  3. On Android, an app's identity is its application ID and its signing key. Ours still says org.elionlabs.overwatch, because changing it would make Play treat the app as a new one.
  4. We nearly lost the upload key. We also found that CI could not see two config files our laptops could. Both lessons are below.
02What is closing

Every app gets a name behind it.

For most of Android's history, you could install an app file from anywhere, and nobody needed to know who made it. That is sideloading, and it is part of what made Android open. It is also how a lot of phone scams work: someone on a call talks the victim into installing a fake banking app.

In August 2025 Google announced it would change that. As 9to5Google summarized in November, Google “will require developer verification to install Android apps, including through sideloading.” In the same piece Google promised “a new advanced flow that allows experienced users to accept the risks of installing software that isn't verified.”

In March 2026 the Android Developers Blog described that flow. You turn on developer mode, restart the phone, and then “there is a one-time, one-day wait” before you confirm with a fingerprint, face or PIN. The delay is the point: “Scammers rely on manufactured urgency.” The same post announced free limited distribution accounts for students and hobbyists, to “share apps with a small group (up to 20 devices) without needing to provide a government-issued ID or pay a registration fee.”

In June, The Hacker News reported the date. From 30 September 2026, certified phones in the first four countries “will block normal installs of apps whose developers have not registered an identity with Google, whether the app comes from Google Play or the stores run by Samsung, Xiaomi, OPPO, vivo, Honor, and Transsion.”

For an app on Google Play, verification changes very little. For anyone who planned to skip Play, it changes everything.

For us the decision was easy. The phone app went through Play. The same report says Google's registry “already covers nearly all installs on Google Play”, so a Play developer is most of the way there already.

03One codebase, two stores

The same app, twice packaged.

Luminair's phone app is a companion to the Mac app. The Play store screenshots in the repository describe it in one line: “Every coding session on your Mac, live on your phone.” You read and answer your sessions, queue work and branch out, from anywhere.

It is one codebase. The interface is a React 18 app built with Vite, in mobile/src. Capacitor 6 wraps that same build in a native iOS project and a native Android project, and gives it access to the phone: the camera, speech recognition, a local SQLite database. The Capacitor config asks for that database to be encrypted on both platforms.

Fig 02  One source tree, two store packagesFrom the mobile/ folder · schematic
MOBILE/SRC React 18 + Vite DIST one web build cap sync IOS/APP Xcode project + tracked config.xml ANDROID/APP Gradle project + tracked config.xml App Store Apple signing Google Play upload key org.elionlabs.overwatch The shared app ID sits between the two projects: both platforms use the same one.
Folder names from the repository. cap sync is the Capacitor step that copies the web build into both native projects; the Android release is built from there with Gradle.

One codebase does not mean one release. Each store has its own build numbers, its own review, its own signing and its own paperwork. The Android build number is at 7 today, version name 1.2, and each upload must use a higher number than the last.

The last blocker before submission was not code at all. Play asks whether an app uses the advertising ID. Ours carries that permission through Firebase Analytics, so the honest answer was yes, for analytics. Once that declaration was complete, the release could be sent for review.

04What makes an app yours

An ID, a key, and now a person.

Android's own documentation is blunt about the first two. “Once you publish your app, you should never change the application ID. If you change the application ID, Google Play Store treats the upload as a completely different app.” And: “you must use the same application ID and signing certificate as when originally published.”

Developer verification adds a third piece and ties it to the other two. According to The Hacker News, a developer registering gives Google “a legal name, address, and contact details, may have to upload a government ID, and proves ownership of each app by submitting an APK signed with their private key.”

Fig 03  What stays fixed, what can changeLuminair's Android app · real values
Application ID
org.elionlabs.overwatch

In build.gradle, the Capacitor config and the iOS project. Change it and Play sees a new app.

Fixed for life
Upload signing key
the Play-enrolled key

Every update must be signed with it. It is how Play knows an upload really comes from us.

Fixed, and must not be lost
Display name
Overwatch Luminair

app_name in the Android strings file, and the name on the store listing.

Free to change
Version
1.2 (7)

versionName and versionCode. The code must go up on every upload.

Changes every release
Values from mobile/android/app/build.gradle and strings.xml as of this post. The key's fingerprint is deliberately not shown.
05The name changed, the ID did not

Why our app ID still says overwatch.

Luminair used to be called Overwatch. On 22 September 2026 the rename reached the phone app: the Android app_name and the Capacitor appName both became Luminair.

The application ID did not move. It is still org.elionlabs.overwatch in the Gradle file, the Capacitor config, the Android strings and the iOS project. The strings file even keeps a package_name entry with the old word in it.

That looks untidy, and it is the correct choice. Changing it would have created a second app on Play with no installs, no reviews and no history, and anyone with the old one would never get an update. The name is what people see. The ID is what the store, the phone and now Google's verification registry use to know it is the same app.

A rule worth writing down earlyPick the application ID as if it will outlive the product name, because it will. Our desktop app's bundle ID kept its old name through the same rename, for the same reason.
06The key we nearly lost

“That key does not exist anywhere on this Mac.”

The second piece of identity nearly cost us the release. Our Journal vault has the note from 26 August 2026, the day we tried to upload the first build through Play's publishing API.

Play already had an upload key enrolled for org.elionlabs.overwatch, from an earlier standalone version of the phone app. The note says that key “does NOT exist anywhere on this Mac or in any session: it is lost.” A fresh key had been generated locally, and Play rejected uploads signed with it, as it should.

There were two ways forward: ask Google for an upload key reset, which takes time and review, or find the original. It turned out to be in an archived copy of the old standalone mobile project. Its fingerprint matched the enrolled key, the wrong new key was discarded, and the upload went through. On 27 August, the build went to production review.

Under developer verification this matters even more. Proving you own an app means signing with its key. A team that loses it, and cannot reset it, is not only locked out of updates but out of proving the app is theirs.

  • Keep the upload keystore and its passwords outside the repository, and back them up somewhere you will still have in two years. Our build.gradle reads them from a git-ignored keystore.properties and skips release signing when it is absent.
  • Use Play App Signing, so the key Google signs installs with is not the one on your laptop, and an upload key can be reset if it is lost.
07Make CI see what you see

Two small files, one failed gate.

The last lesson is smaller, and it is about knowing that the thing you ship is the thing you checked.

Capacitor keeps a config.xml in each native project. Our repository hygiene gate, which runs in CI as part of the security audit, requires both files to exist, so a clean build always has the canonical native configuration. But .gitignore rules excluded both files from the repository.

On a laptop the files were there, generated by earlier syncs, so the gate passed. In CI's clean checkout they were missing, so it failed. The fix on 3 September 2026 was to commit both files. Its message sums it up: the gate “requires them but .gitignore excluded them, so CI's clean checkout failed the gate.”

It is the same pattern as any “works on my machine” bug. A local check is only as good as the difference between your working folder and a fresh clone. For anything that proves identity or configuration, the fresh clone is the one that counts.

08What we checked

Checked, and not claimed.

1
Application ID across Gradle, Capacitor config, Android strings and the iOS project
2
Native config.xml files the hygiene gate requires, both tracked since 3 September 2026
7
Android versionCode today, version name 1.2
4
Play store screenshots in the repository, added 26 September 2026

What this post does not claim

  • That we completed Google's developer verification. We describe the requirement and our Play setup; we did not document a verification step in the repository.
  • What happened on 30 September 2026 in the four countries. We cite the date Google set, as reported in June.
  • The exact day the app went live on Play. The review was submitted on 27 August; the download page announced it on 17 September.
  • Anything about how Google treats hobbyist apps beyond what its own post and the two news reports say.

For what the phone app does once it is installed, read Your agents, from your phone.

Sources

Your Mac, in your pocket

Get the Luminair phone app on Google Play or the App Store, and pair it with your Mac.

Download Luminair →