RORK LABJP
BUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verifyBUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verify
Articles/Business
Business/2026-08-11Intermediate

Four Countries, Not the World: Checking Which of My Six Apps the September 30 Deadline Actually Touches

Android developer verification goes live on September 30, 2026 in Brazil, Indonesia, Singapore, and Thailand. Here's how to decide from your own install data whether that date is urgent for you, and what actually blocks indie developers.

Android46Google Play27App Distribution3Indie Development23Expo175

Premium Article

My notes said "fully mandatory in September 2026." That was about Android developer verification. September is next month, and two of the apps I run as an indie developer are distributed on Google Play. So I went back and reread the official pages — and what I found there was a list of four country names.

Brazil, Indonesia, Singapore, Thailand.

What begins on September 30, 2026 is enforcement in those four countries, not worldwide. Global expansion is explicitly listed as 2027. Had I spent August believing "everything stops in September," I would have gotten my priorities badly wrong.

That said, whether four countries is small depends entirely on who you are. In categories where the app barely depends on language — wallpapers being the clearest example — traffic from emerging markets runs higher than most people expect. "Only four countries" is not reassuring until you've looked at your own numbers. This is a record of how I checked mine.

The dates that are actually confirmed, and the stores involved

Let me start with what is officially settled. To keep speculation out of it, the dates and country names below come only from what's published in the Android Developer Console help pages.

WhenWhat happens
November 2025Early access registrants began verifying apps they distribute outside Google Play
March 2026The full Android Developer Console experience opened to all developers
September 30, 2026In Brazil, Indonesia, Singapore, and Thailand, only apps registered by verified developers can be newly installed from the participating stores
2027Expansion to all apps distributed to certified Android devices, globally

The participating stores for this first phase are spelled out too. This is the part people skim past.

CompanyStore
GoogleGoogle Play
HonorHONOR App Market
OPlusOPPO App Market
SamsungGalaxy Store
TranssionPalm Store
vivoV-Appstore
XiaomiGetApps

Google Play sits at the top of that list. I had initially filed this whole thing under "sideloading regulation" — something aimed at people who hand out APKs directly, and therefore not really my problem since I ship through Play. It's the opposite. Installs through Play are covered. "I only ship on Play, so this doesn't apply to me" is the single most dangerous misreading here.

Sideloading itself isn't going away either. Apps from unverified developers remain installable through an advanced flow, after the user acknowledges the risk and completes a one-time setup, and ADB continues to work as the normal path for development. But those are escape hatches for someone holding the device. They are not a distribution strategy.

Deciding whether "four countries" is small for you

Here's the part that actually matters. Once the scope is fixed at four countries, you only need one number: what share of your installs comes from them. If it's one percent, September 30 isn't an emergency. If it's twenty percent, you want to move in August.

Export the country-level install report from Play Console's statistics section and aggregate it. One thing trips me up every single time: the CSV reports Play Console hands you are UTF-16LE with a BOM. Read them as UTF-8 and the column matching fails. If you get an error saying a column can't be found, suspect the encoding before anything else.

// scripts/enforcement-share.mjs
// Aggregates the country-level install CSV exported from Play Console > Statistics.
// Usage: node scripts/enforcement-share.mjs installs_country_202607.csv
import fs from "node:fs";
 
// The four countries where enforcement starts on 2026-09-30 (ISO 3166-1 alpha-2)
const ENFORCED = new Map([
  ["BR", "Brazil"],
  ["ID", "Indonesia"],
  ["SG", "Singapore"],
  ["TH", "Thailand"],
]);
 
const file = process.argv[2];
if (!file) {
  console.error("Usage: node scripts/enforcement-share.mjs <country install CSV>");
  process.exit(1);
}
 
// Play Console reports are UTF-16LE with a BOM. Reading them as utf8 breaks the header row.
const raw = fs.readFileSync(file, "utf16le").replace(/^/, "");
const lines = raw.trim().split(/\r?\n/);
if (lines.length < 2) {
  console.error("No readable rows. Check that the file is UTF-16LE.");
  process.exit(1);
}
 
const cols = lines[0].split(",").map((c) => c.trim());
const iCountry = cols.findIndex((c) => /country/i.test(c));
// Several install-related metrics ship in the same export; prefer the device-level one.
const iInstalls = cols.findIndex((c) => /install/i.test(c) && /device|unique/i.test(c));
const iFallback = cols.findIndex((c) => /install/i.test(c));
const target = iInstalls >= 0 ? iInstalls : iFallback;
 
if (iCountry < 0 || target < 0) {
  console.error("Could not identify the columns. Actual header:", cols.join(" | "));
  process.exit(1);
}
 
let total = 0;
const hits = new Map();
 
for (const line of lines.slice(1)) {
  const cells = line.split(",");
  const code = (cells[iCountry] ?? "").trim().toUpperCase();
  const n = Number((cells[target] ?? "0").replace(/[^\d.-]/g, "")) || 0;
  if (!code || n <= 0) continue;
  total += n;
  if (ENFORCED.has(code)) hits.set(code, (hits.get(code) ?? 0) + n);
}
 
const affected = [...hits.values()].reduce((a, b) => a + b, 0);
const share = total > 0 ? (affected / total) * 100 : 0;
 
console.log(`Installs counted: ${total.toLocaleString()}`);
for (const [code, label] of ENFORCED) {
  const n = hits.get(code) ?? 0;
  const pct = total > 0 ? ((n / total) * 100).toFixed(2) : "0.00";
  console.log(`  ${label} (${code}): ${n.toLocaleString()} (${pct}%)`);
}
console.log(`Four-country total: ${affected.toLocaleString()} (${share.toFixed(2)}%)`);
console.log(
  share >= 5
    ? "-> Start in August. That leaves room for a paperwork round trip."
    : "-> September 30 is not urgent. Getting ready before the 2027 global rollout is enough."
);

The output looks like this:

Installs counted: 412,880
  Brazil (BR): 21,043 (5.10%)
  Indonesia (ID): 38,512 (9.33%)
  Singapore (SG): 1,204 (0.29%)
  Thailand (TH): 9,870 (2.39%)
Four-country total: 70,629 (17.11%)
-> Start in August. That leaves room for a paperwork round trip.

The five percent threshold is my own call, not a rule. For a solo developer, the registration work itself takes hours at most. If a few hours of paperwork protects more than five percent of your distribution, there's no reason to defer it. Your own cutoff will depend on your scale — look at the number first, then decide.

One thing becomes obvious once you run this per app: the ratio varies enormously between apps from the same developer. An app whose value is carried by Japanese text and an app that barely uses text at all end up with completely different emerging-market profiles. Among the apps I run, the ones with the least on-screen text consistently show the highest share from Southeast Asia. "Our app is domestic anyway" is a feeling, not a measurement — and it has to be checked per app.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You will be able to decide in about thirty minutes, from your own country install split, whether the September 30 date is urgent for your app or not
You will avoid discovering the real bottleneck (a registration number that takes weeks to issue) only after the deadline has passed
You will be able to rank several apps by which to register first, using numbers instead of guesswork
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Business2026-08-20
August 31 Means Something Different Depending on Whether You Plan to Ship an Update
Two separate conditions land on Google Play's August 31 date: API 36 to submit an update, and API 35 to stay discoverable to new users. Here is how I sorted six apps, and who actually gets the extension form.
Business2026-05-12
What I Discovered Expanding My Rork App to Android — Key Differences Between App Store and Google Play
An indie developer with 10+ years experience and over 50 million cumulative downloads shares what surprised him most when expanding a Rork app to Android — from search algorithms to Short Descriptions and Feature Graphics.
App Dev2026-08-18
The three places I had to fix before a Rork project actually targeted API level 36
My app.json said targetSdkVersion 36. The value my build actually read was 35. Here is the script that reports the effective value, and how I split my apps between raising, leaving alone, and requesting an extension.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →