Image.resolveAssetSource cannot resolve asset correctly in Android Release mode
See original GitHub issueI have a native UI module in Android that takes props from JS. My images are not under /android folder so I use resolveAssetSource to get root level folder assets from Android.
Native module’s prop is the output of Image.resolveAssetSource(require('imagename'))
.
const img = require('./images/png/marker.png')
const imgProps = Image.resolveAssetSource(img);
..
<CustomImage style={{ width: imgProps.width, height: imgProps.height }} src={imgProps} />
This works pretty good in debug mode. Because asset uri is in full form as below:
{
"__packager_asset": "true",
"width": 80,
"height": 80,
"uri": "http://10.0.2.2:8081/assets/images/png/marker.png?platform=android&hash=412827xxxxxxxxx",
"scale": 1
}
But when I bundle the app and create the signed apk, uri changes and it’s not in a form that I can use. Therefore, the image is not showing up. Uri shows up like below:
{
"__packager_asset": "true",
"width": 80,
"height": 80,
"uri": "images_png_marker",
"scale": 1
}
It seems that bundler flattens folder structure using underscore for each subfolder, removes the file extension and the full path.
This very same issue was mentioned in issue:https://github.com/facebook/react-native/issues/18216, but it was closed without a resolution. No one created a repo. But I’ve created one and attached screenshots.
DEBUG | RELEASE |
---|---|
![]() |
![]() |
React Native version: React Native Environment Info: System: OS: macOS 10.14.4 CPU: (8) x64 Intel® Core™ i7-4850HQ CPU @ 2.30GHz Memory: 81.64 MB / 16.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 8.10.0 - ~/.nvm/versions/node/v8.10.0/bin/node Yarn: 1.5.1 - /usr/local/bin/yarn npm: 5.6.0 - ~/.nvm/versions/node/v8.10.0/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2 Android SDK: API Levels: 23, 25, 26, 27, 28 Build Tools: 23.0.1, 27.0.3, 28.0.3 System Images: android-27 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom IDEs: Android Studio: 3.4 AI-183.5429.30.34.5452501 Xcode: 10.2/10E125 - /usr/bin/xcodebuild npmPackages: react: 16.8.3 => 16.8.3 react-native: 0.59.8 => 0.59.8 npmGlobalPackages: react-native-cli: 2.0.1 react-native-macos-cli: 2.0.1 react-native-rename: 2.4.1
Steps to reproduce:
- Create an app with react-native init
- Create a UI Native component(ImageView) for Android and implement as in
CustomImage.java
- From JS, send props to this component using
Image.resolveAssetSource(require('imagename'))
- Run the app in debug mode and see the marker.png is shown correct
- Run android bundler for release mode and create a signed apk and upload it to either emulator or physical device. See marker.png is not show because URI is not formed correctly.
Note: To see what props are sent to native component, I also print out props in a Text component. URI is formed without file extension or full path. Therefore ImageView cannot find the resource.
The whole thing is reproducible in this bare minimum repo created with latest versions: https://github.com/aliustaoglu/react-native-bug-resolve-asset-source
Files to check: App.js CustomImage.java
Issue Analytics
- State:
- Created 4 years ago
- Reactions:5
- Comments:10 (3 by maintainers)
@rajashekar545 I did something like this:
If ui starts with “http” (or it’s in debug mode) get the bitmap from uri
if not (release mode) then it resolves to R.drawable.images_png_marker. Please note that nested folders are flattened into a single file name. So, to make it come from JavaScript and come as prop I did below:
If interested for IOS I add the folder that has the png files into
Build Phases > Copy Bundle Resources
then from Swift I can get it like this:
This structure works good for me.
Please use this instead.
Image.resolveAssetSource()
doesn’t intend to be used directly and for network imageswidth
andheight
won’t be available.