react-native-mapbox-gl
react-native-mapbox-gl copied to clipboard
JS required image not working with ImageSource in release mode
I am getting a blank white screen when loading a map running from a signed APK build on Android. I only see the mapbox info icon.
It works fine on debug for Android on all my devices, it also works if I set debuggable to true in the gradle file but obviously I am not able to send a debuggable build to google play store.
Works fine on release build for iOS. I am also not seeing any errors or anything in the logcat when I debug.
Any help would be greatly appreciated.
how are you generating your APK? Can you post your app/build.gradle
?
@nitaliano I followed the documentation here to generate the APK. https://facebook.github.io/react-native/docs/signed-apk-android.html#content
Here is the app/build.gradle
apply plugin: "com.android.application"
import com.android.build.OutputFile
project.ext.react = [
entryFile: "index.js"
]
apply from: "../../node_modules/react-native/react.gradle"
def enableSeparateBuildPerCPUArchitecture = false
def enableProguardInReleaseBuilds = false
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.imts18"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
signingConfigs {
release {
if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
dependencies {
compile project(':react-native-fs')
compile project(':react-native-splash-screen')
compile project(':react-native-fast-image')
compile project(':react-native-linear-gradient')
compile fileTree(dir: "libs", include: ["*.jar"])
compile project(':mapbox-react-native-mapbox-gl')
compile project(':react-native-sqlite-storage')
compile "com.android.support:appcompat-v7:26.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
}
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
@beisert1 don't ship your app like this if this works, but can you remove proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
under buildTypes.release
I'm wondering if some classes could be getting stripped from the proguard config.
@nitaliano same issue after removing
Could it be in the settings.gradle? I remember I had to remove a duplicate include for mapbox. The one I removed was prefixed with an @ symbol.
rootProject.name = 'TEST18'
include ':react-native-fast-image'
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
include ':react-native-splash-screen'
project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android')
include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-sqlite-storage'
project(':react-native-sqlite-storage').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sqlite-storage/src/android')
include ':app'
include ':mapbox-react-native-mapbox-gl'
project(':mapbox-react-native-mapbox-gl').projectDir = new File(rootProject.projectDir, '../node_modules/@mapbox/react-native-mapbox-gl/android/rctmgl')
@nitaliano Running react-native link marks @mapbox/react-native-mapbox-gl as unlinked for android.
rnpm-install info Platform 'ios' module @mapbox/react-native-mapbox-gl is already linked
rnpm-install info Linking @mapbox/react-native-mapbox-gl android dependency
rnpm-install info Platform 'android' module @mapbox/react-native-mapbox-gl has been successfully linked
rnpm-install info Platform 'ios' module react-native-fast-image is already linked
rnpm-install info Platform 'android' module react-native-fast-image is already linked
rnpm-install info Platform 'ios' module react-native-fs is already linked
rnpm-install info Platform 'android' module react-native-fs is already linked
rnpm-install info Platform 'ios' module react-native-linear-gradient is already linked
rnpm-install info Platform 'android' module react-native-linear-gradient is already linked
rnpm-install info Platform 'ios' module react-native-splash-screen is already linked
rnpm-install info Platform 'android' module react-native-splash-screen is already linked
rnpm-install info Platform 'ios' module react-native-sqlite-storage is already linked
But once it links, it adds @mapbox/react-native-mapbox-gl in the app/build.gradle and the settings.gradle file, however, when I do so I get an error for missing dependency
Error:Unable to find module with Gradle path ':@mapbox/react-native-mapbox-gl' (needed by module 'app'.)
react native link is a disaster it only works for simple use cases not when the repo has heavy native deps like this one. Look at how the example app is setup
@nitaliano Figured out my issue was caused by using using an ImageSource layer and having the image url dynamic by using a prop. The only way I could get this to work in release was by using an image from our server but we need this to be offline.
<Mapbox.ImageSource id="imageSource" url={images[`hall${this.props.navigation.state.params.hallID}`]} coordinates={coords}>
<Mapbox.RasterLayer id="imageLayer" />
</Mapbox.ImageSource>
@beisert1 dynamic urls are not supported in the native SDKS
try something like this
renderImageSource() {
if (!this.state.url) {
return null;
}
return (
<Mapbox.ImageSource id="imageSource" url={this.state.url} coordinates={coords}>
<Mapbox.RasterLayer id="imageLayer" />
</Mapbox.ImageSource>
)
}
Thank you @nitaliano , unfortunately that did not work in the release build but it did work in debug mode.
Is there a proper way to hardcode a local image? I could only get this to work in release build by using a url from our server.
can you show me what your url looks like? is it an image that gets required in the javascript?
@nitaliano The following works in release mode, an image from our server. I can't give exact location for confidential reasons.
<Mapbox.ImageSource id="imageSource" url="https://webserver.com/image.png" coordinates={coords}>
<Mapbox.RasterLayer id="imageLayer" />
</Mapbox.ImageSource>
The following works on iOS release mode and android debug mode but not in android release mode
renderImageSource() {
if (!this.state.url) {
return null
}
return (
<Mapbox.ImageSource id="imageSource" url={this.state.url} coordinates={coords}>
<Mapbox.RasterLayer id="imageLayer" />
</Mapbox.ImageSource>
)
}
or
<Mapbox.ImageSource id="imageSource" url={images[`hall${this.props.navigation.state.params.hallID}`]} coordinates={coords}>
<Mapbox.RasterLayer id="imageLayer" />
</Mapbox.ImageSource>
or
<Mapbox.ImageSource id="imageSource" url="../assets/halls/hall.png" coordinates={coords}>
<Mapbox.RasterLayer id="imageLayer" />
</Mapbox.ImageSource>
or
<Mapbox.ImageSource id="imageSource" url={images.hall} coordinates={coords}>
<Mapbox.RasterLayer id="imageLayer" />
</Mapbox.ImageSource>
we have an images file that references all the local project images.
import images from "../themes/images"
inside the images.js:
hall: require("../assets/halls/hall.png"),
We use this practice in all parts of our app and it works except in Android release build using Mapbox.imageSource
It works with the packager because with the packager the url will be making an http request, when you put React Native into release mode the packager is taken out of the loop here, so the ImageSource will be looking for a path on the native file system.
For now try react-native-fs
to help you get the native path to the file or give this a try https://github.com/mapbox/react-native-mapbox-gl/blob/master/javascript/utils/index.js#L83 when you import an image with javascript that is turned into a number, when you pass that into resolveAssestSource
that react native provides it will return an object that will contain the path to the file, try putting that path as the url.
This is something we can do internally in the SDK in the future
@nitaliano I was not able to get the resolveAssetSource method to work in release mode, however, I was able to get this to work with react-native-fs.
I placed the images in the android/app/src/main/assets folder and used the RNFS.copyFileAssets function to copy those images in the RNFS.DocumentDirectoryPath. Then in the Mapbox.ImageSource I used the file://RNFS.DocumentDirectoryPath to load the image successfully in the release build.
Any news on this? If you use an image with require(...) for MapboxGL.ImageSource it still throws an error if the url is not a remote URL (https://...) or loaded from the local filesystem (file://...). It should be possible to load images provided with the app bundle with require. Having to use a remote file or a file stored to the local filesystem is not an option in many cases. As long as you're in debug mode and connected to the local packager it can resolve the URL but in release mode or when you're disconnected from the packager it still throws an error. Any help appreciated
I am having the same issue. I am using Expo so adding an image in Android folder will not work in my case. @nitaliano