[OK-33404] fix: read Android bundled assets as strings#12550
Open
huhuanming wants to merge 4 commits into
Open
[OK-33404] fix: read Android bundled assets as strings#12550huhuanming wants to merge 4 commits into
huhuanming wants to merge 4 commits into
Conversation
huhuanming
marked this pull request as ready for review
July 19, 2026 07:19
huhuanming
requested review from
ezailWang,
originalix,
revan-zhang and
sidmorizon
as code owners
July 19, 2026 07:19
huhuanming
enabled auto-merge (squash)
July 19, 2026 07:20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
OK-33404 reports that bundled images loaded with React Native
require()cannot be read as Base64 in Android production builds.The affected flow is equivalent to:
Observed behavior:
Expected behavior: callers should be able to pass either a normal URI or the result of
require()to one string-reading API and receive the requested content.Root cause
React Native
require('./image.png')does not return a filesystem path. On native platforms it returns a numeric Metro asset ID, which is resolved byImage.resolveAssetSource().The resolved Android value differs by build mode:
packages_shared_src_assets_blank.That drawable name is intentional and cannot be converted into a normal absolute path because the image is an APK resource rather than a standalone file.
The legacy Android implementation in
expo-file-systemthen takes different native paths depending on the requested encoding:readAsStringAsyncreads a null-scheme resource throughopenResourceInputStream.readAsStringAsyncusesgetInputStream, which supports URI-backed inputs but rejects the scheme-less drawable name.copyAsynchas a resource-aware null-scheme branch and can copy the packaged drawable to a regular file URI.As a result, the failure is specific to the combination of Android production, a numeric
require()asset, a scheme-less resolved resource name, and Base64 encoding.Solution
This PR adds a shared
readAsStringAsync(source, options)wrapper that accepts both normal URI strings and React Native image sources.The wrapper resolves the source first and performs the Android resource-copy path only when all four known conditions are true:
Behavior by path:
require()drawable requested as Base64 is copied to the native cache directory withcopyAsync.file://URI is read with Expo's Base64 reader.The temporary filename contains the Metro asset ID, timestamp, and random suffix. This prevents the main and background JS runtimes, which have separate JS heaps but share the native filesystem, from overwriting or deleting each other's in-flight files.
The existing required-image Base64 conversion now uses this wrapper, so callers receive the same raw Base64 content before the image helper adds the
data:image/...;base64,prefix.Scope and compatibility
readAsStringAsynccallers to migrate. The other Expo FileSystem integrations only write CSV files or create log upload tasks.Validation
yarn agent:check --profile commitprodReleaseAPK through ADB.require('./blank.png')andencoding: 'base64'.true2117bbb5576526b3ebfb7f54cfe783c30388558ae32116a282c75f96256ebf86Related issue