AX note · How-to

A market:// link opens a store chooser on SKT-sold Samsung phones: set the Play package first

On two Samsung phones sold by SKT in Korea (Galaxy S21 and S20), three store apps answer a market:// link. Pointing the intent at the Play Store app first skips the chooser and opens the Play listing.

By SugarMount Android development 7 min read Last updated

On a Galaxy S21, tapping a store link in our app's drawer brought up a sheet asking whether to open ONE store (a Korean app store), Galaxy Store (Samsung's store) or Play, instead of the Play listing. It was October 9, 2026, and we were tapping through commit efc0acf, which added a menu of our puzzle games to the drawer of SugarSpeller, on the S21. All 300 unit tests had already passed. Fifty-nine minutes later, commit 8bbe179 changed the store link to target Play first.

Sources: the SugarSpeller repository's git history (f6ef50e, efc0acf, 8bbe179, b6cda27), CHANGELOG entry 1.6.026, the monitoring log (WATCH.md, Oct 23), and adb queries we ran again on a Galaxy S21 and S20 on 2026-10-30.

Contents (9)
  1. Three store apps answer one market:// link
  2. The old code read a failure as "no Play"
  3. Why 300 unit tests and two reviews missed it
  4. Try Play, then plain market, then https
  5. Keeping the chooser, or opening https first
  6. Don't pin Play if your app is on other stores too
  7. Two adb queries and one package assertion
  8. Still open: UTM installs and 16 drawer E2E tests
  9. FAQ

Three store apps answer one market:// link

On October 30 we asked two SKT-sold phones which apps handle market://details?id=…. A Galaxy S21 on Android 15 and a Galaxy S20 on Android 13 both listed three: Play, Galaxy Store and ONE store, each with isDefault=true, meaning its filter accepts implicit intents (it declares CATEGORY_DEFAULT). When such an intent has more than one candidate and no default app is set, Android asks the user to choose.

Comparison: with no target app, a market:// link on the S21 has three store candidates and shows a chooser; with the Play package set there is one candidate and the Play listing opens directly.
Setting the Play package cuts the candidates for the same market:// link from three to one, and the chooser goes away.

The drawer links to Block Turn, Arrow Knots and SugarCard, and all three are on Play only. The game links carry the referrer utm_source=sugarspeller&utm_medium=crosspromo&utm_campaign=drawer, which only Play reads and reports in the Play Console acquisition report. A user who picks another store lands on a page with no app, and even an install that follows doesn't count as cross-promotion.

The old code read a failure as "no Play"

The first version opened market:// and fell back to the https address on ActivityNotFoundException. The comment on that branch said the device had no Play Store app. The assumption was that only Play opens market:// links. That code first went in with the SugarCard menu in commit f6ef50e on September 20, and on October 9 efc0acf moved it unchanged into a launcher shared by the games and SugarCard. Claude co-authored both commits.

On SKT-sold Samsung phones that assumption means the fallback never runs. With three candidates there is no exception; the chooser appears, and the code treats the store as opened. The same check showed that the SugarCard menu had carried the same problem since the September 20 code.

Why 300 unit tests and two reviews missed it

The store test in efc0acf compared the started intent's URI and never looked at its package. Robolectric has no other store apps installed, and by default startActivity doesn't fail there. In the same piece of work, three analysis agents and two adversarial reviews found and closed three test gaps (a missing <queries> entry, hiding the rows on Android 6.0, and the Classic drawer wiring). None of them questioned the market:// assumption.

The chooser showed up when we tapped the menu on the S21 itself. The repository's working notes say runtime checks are done on a release APK, and the check after the fix ran on one (the routine is written up in the release gate note).

Try Play, then plain market, then https

8bbe179 keeps three candidates in a list and opens them in order, moving on only when one throws.

val attempts = listOf(
    view("market://details?$query").setPackage(PLAY_STORE),
    view("market://details?$query"),                           // no Play: any store
    view("https://play.google.com/store/apps/details?$query"), // no store app: browser
)

An intent pinned to the Play package throws on a device without Play, which gives the list the failure signal the old code never had. The existing test gained an assertion that the started intent's package is Play, and a new test checks that with only another store present (checkActivities(true)) the plain market:// address opens with no package. Unit tests went to 301/301. Delete the setPackage call and the package comes back null, so the assertion fails (the same check we describe in deleting the guard).

Step diagram: open the app if installed; otherwise market:// with the Play package, then plain market://, then the https address. On the S21 on October 9, Block Turn opened in Play with no chooser.
A later candidate runs only when the one before it throws, so a phone with Play always lands on the Play listing.

On the S21 release APK that day, the installed Arrow Knots launched straight away, Block Turn, not installed, opened in Play with no chooser, and SugarCard went to Play as well. The GA4 log showed game_open{game=arrows,installed=1}, {game=blocks,installed=0} and sugarcard_open{installed=0}. The fix went into the 1.6.026 release branch, so the game menu pointed at Play from the first build users got, published the same morning.

Keeping the chooser, or opening https first

We dropped the idea of leaving the chooser alone because the apps are on Play only. Pinning Play with nothing after it would open nothing on a phone without Play, so plain market and https stay as fallbacks.

On the S21 on October 30, Play and Chrome both handle the Play https listing, and play.google.com is a system-verified link for Play, so opening https first would probably have opened Play too (we didn't tap it to check). But a browser accepts https on nearly every phone, so there is no exception, and which app opens depends on the device's settings. That doesn't fit a list that moves on when a candidate fails, so https stays last.

Don't pin Play if your app is on other stores too

If you send Korean users to an app that is only on Play, set the Play package on the market:// intent. If the app is also on ONE store or Galaxy Store, don't: the pin pulls those stores' users over to Play. On a phone without Play, the second candidate opens another store, which doesn't list our apps. We checked that path only in a Robolectric test; we have no such phone. We also checked only two Samsung phones sold by SKT, not KT or LG U+ models, unlocked models or other makers.

Two adb queries and one package assertion

  1. Connect the phone and run adb shell cmd package query-activities --brief -a android.intent.action.VIEW -d "market://details?id=com.example.app". If the first line says 2 or more activities found, the phone can show a chooser; each candidate also shows its isDefault value.
  2. Run it again with the Play Store app's package, -p com.android.vending, at the end. You should get one.
  3. Change the store link to try Play, then plain market, then https, catching only ActivityNotFoundException to move to the next one.
  4. Assert the started intent's package in a unit test, and check once that the test fails when you remove setPackage.
  5. Put the release APK on a phone sold in Korea and tap the link yourself.

Still open: UTM installs and 16 drawer E2E tests

From October 9 to 22 the game rows were tapped 33 times in GA4 (Block Turn 5, Arrow Knots 16, and 12 from 1.6.026 with no game value). Whether those taps became installs is only in the Play Console acquisition report, and we haven't judged it yet. On the S21, 16 E2E tests that open the drawer fail, and they fail the same way on the baseline build before the change (360bed3), so the game-row E2E tests never ran on the device and we tapped the rows by hand instead. Finding the cause of those failures comes next.

FAQ

Why does a Galaxy phone ask which store to use when I open a Play link?

More than one store app on the phone handles market:// addresses. On SKT-sold Galaxy S21 and S20 phones on 2026-10-30, Play, Galaxy Store and ONE store all did, and when the link names no target app, Android asks the user to pick.

How do I open the Play Store listing directly from my app?

Set the Play Store app as the package of the market://details intent with setPackage. On a device without Play that intent throws ActivityNotFoundException, so keep plain market:// and the https address as fallbacks, in that order.

This note is written from values SugarMount measured itself; an AI coding agent was used to draft it.

All notes on Android development · All AX notes