My app works well on react-native-run-android and on gradlew clean provide me build success.
I used to check and creating the apk by using gradlew assembleRelease.
Recently, I faced an error while trying to create the APK and I cant find the right solution.
as far as I understand, some problem with the build.gradle or any gradle settings - the last feature I put was the mauron background geolocation (im not sure if that cause the problem).
I tried:
on gradle.properties :
android.useAndroidX=true
android.enableJetifier=true
org.gradle.daemon=true
org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx4608m -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
in build.gradle I added: implementation 'androidx.multidex:multidex:2.0.1' in the dependencies.
3.
defaultConfig {
...
multiDexEnabled true
}
dexOptions {
incremental true
javaMaxHeapSize "4g"
// multiDexEnabled true
}
The gradle I used was 6.3. So I upgraded (downloaded from their website v7 but I think the project is still under 6.3).
My question is:
If the app works and build successfuly, was the error because of my code or the gradle settings?
Im over a week with that problem and out of any clue how to get it work.
the error I get:
> Task :app:mergeDexRelease FAILED
D8: Program type already present: org.apache.commons.io.Charsets
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
Program type already present: org.apache.commons.io.Charsets
full picture: https://ibb.co/87pFnv1 , https://ibb.co/FxB8PWX
could anyone help me with it?
The error is not about multidex. It clearly says that one of your package is trying to add a library which is already there.
Since you have the name of the library you can put conditional implementation in your build.gradle to avoid redundant implementation.
for example
Implementation('new package that has module'){
exclude module: 'module to exclude'
}
Finally I solved the problem, Thanks Shashank Shekhar for directing me to the correct problem.
I used mauron85/react-native-background-geolocation package, was working fine until I tried to create apk.
in mauron85 issue #505 there was similar problem and someone fixed it by forking and maintaining the repo.
if anyone face that issue in future, I recommend to use #darron1217/react-native-background-geolocation as it solved the error.
Resolved: I have two packages #react-native-masked-view/masked-view (from previous developer) and #react-native-community/masked-view. Just remove #react-native-masked-view/masked-view package and try build.
https://github.com/react-native-masked-view/masked-view/issues/100#issuecomment-841634389 Thanks to: Navipro70
I followed the official docs to enable the Hermes engine in my app but the following always returns false:
const isHermes = () => !!global.HermesInternal;
console.log('>>>>>>>>>>>>>', isHermes());
The changes I made are setting the following in android/app/build.gradle:
project.ext.react = [
enableHermes: true, // clean and rebuild if changing
]
Then I did a clean build with:
cd android && ./gradlew clean
yarn android
But the console.log always returns false
I too got false when console.logging isHermes(). I realized it was because I was using the normal Chrome debugger(not sure of the internals of why). When I just console.logged in VSCode, I got true. There is a special way (sorry, my 'Copy link to highlight' isn't working, it's about 1/4 of the way down the page) you have to set up the Chrome debugger when you are using Hermes. There seems to be some trouble with getting it to work with newer versions of Chrome though. My plan right now to verify I'm actually using it is to compare the size of the binary before and after enabling Hermes.
I am experiencing some difficulty getting IntelliJ to recognize my Kotlin Tests as mocha tests and generating the green play button in the gutter allowing me to run Kotlin/JS unit tests in the IDE via the Mocha Plugin. Now, I somehow managed to get this working after some trial and error and then inexplicable earlier today it just stopped working and the green play buttons vanished from the gutter. I have tried all the normal stuff such as invalidating the IDE cache, removing .idea/*.iml files and reimporting project. Nothing seems to work.
Image of Working Environment
here is an image of the setup working as expected that I luckily took a snapshot of while I had the chance because I had so much difficulty getting it working.
You can also see that the mocha run configuration is accurately picking up on the fact that the actual file being ran is going to be the output file in my build directory.
My initial instinct led me to believe that this was due to IntelliJ picking up on my map.js files being generated as well, however this is not the case as did not (and do not) have my compile options set to with sourceMap = true or sourceMapEmbedSources = "always", as you can see from this snippet from my build.gradle.kts
compileKotlin2Js {
kotlinOptions {
moduleKind = "commonjs"
}
}
compileTestKotlin2Js {
kotlinOptions {
moduleKind = "commonjs"
}
}
For the record, my gradle build compiles and tests run successfully. To clarify, I am specifically trying to get IntelliJ to recognize the project structure in such a way that the run configurations can make these education decisions for me and speed up my workflow.
I am developing a small dictionary app by using react native with expo.
As I am compiling to Apk file. The size goes up to 30mb and after having installed on a device, it goes to 80mb.
Is this normal?
Are there any ways to reduce the size of the app?
Thank you guys.
For android APK bundle using expo, you can use the following command:
expo build:android -t app-bundle
The size will be much smaller once you upload it to the play store.
This is relevant for React Native SDK 32 and earlier.
the expo is for development the app you should migrate to react-native for production
make a new react app "react-native init"
Copy the source files over from Expo project
Install all dependencies of the Expo project except Expo specific libraries.
Make necessary adjustments to app.json file
Download the signing key of your Android app from Expo using exp
fetch:android:keystore and set it up
This reduces your app dramatically you can also enable proguard and specific build for cpu architecture
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
for more info visit https://medium.com/#aswinmohanme/how-i-reduced-the-size-of-my-react-native-app-by-86-27be72bba640
using expo component
after you done and want publish with less size or just wan't to use a native library expo give you an option called ExpoKit this also can be used with already build with native code react projects
1-run command expo eject to add ExpoKit (choose the "ExpoKit" option)
(no need to do this if you have copied files manually or using native project)
2 -start expo packager with expo start.Leave this running and continue with the following steps.
3-
link library for android and ios, this command mostly do this react-native link, sometime this will not work and you should do it manually for this means visit expokit
PS: I didn't test this so if this not work inform me
Make following changes in build.gradle file located at:
./android/app/build.gradle
Remove x86 from abi filters.
splits {
abi {
reset()
enable true
universalApk false
include "armeabi-v7a", "x86"
}
}
Generate different APK's for different architecture
def enableSeparateBuildPerCPUArchitecture = true
Enable ProGuard :
def enableProguardInReleaseBuilds = true
Also set minifyEnabled true and shrinkResources true
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
Also, you can have different build types for development and release builds(depends on your user base)
buildTypes {
debug {
ndk {
abiFilters "armeabi-v7a", "x86"
}
....
}
release {
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
....
}
Also don't forget to remove the unused FONT Files
As of 2021, there is now a much easier option to reduce Android binary size, since ejecting/migrating to pure react-native, switching to bare workflow and building your own binaries locally requires a lot of work and study if you don't know how to do it already or don't have your environment and tools all set up.
In app.json, make the following changes:
"expo": {
...
"android": {
"enableDangerousExperimentalLeanBuilds": true
}
}
This alone should reduce app size in ~40-50% depending on your project.
There's a few things you should know about using this option, so you should read
https://github.com/expo/fyi/blob/master/managed-app-size.md. It's still WAY easier than ejecting.
on top of that, you should still use app bundles (.aab) to get another ~50% size reduction after uploading to the play store:
expo build:android -t app-bundle
the other way to reduce your app size without manually copy-paste your code in another repo. In app.json or app.config.js just set it enableDangerousExperimentalLeanBuilds to true, by doing this expo won't install the unnecessary node modules when you are running expo build:android -t app-bundle.
If you run into any crashes compare the native node modules which are installed before enabling enableDangerousExperimentalLeanBuilds and install only the required one. You can find the native node modules installed in the expo.io build artefacts.
here are some node module that come along with managed flow which you may not require
expo-ads-admob:8.3.0
expo-analytics-amplitude:8.3.1
expo-ads-facebook:8.4.0
expo-analytics-segment:9.0.0
unimodules-constants-interface:5.3.0
expo-app-auth:9.2.0
expo-apple-authentication:2.2.1
unimodules-app-loader:1.3.0
unimodules-font-interface:5.3.0
unimodules-image-loader-interface:5.3.0
unimodules-permissions-interface:5.3.0
expo-application:2.3.0
expo-av:8.6.0
expo-background-fetch:8.5.0
expo-task-manager:8.5.0
unimodules-task-manager-interface:5.3.0
expo-barcode-scanner:9.0.0
unimodules-barcode-scanner-interface:5.3.0
expo-battery:3.0.0
expo-blur:8.2.0
expo-brightness:8.3.0
expo-calendar:8.5.0
expo-camera:9.0.0
unimodules-camera-interface:5.3.0
unimodules-face-detector-interface:5.3.0
unimodules-file-system-interface:5.3.0
expo-cellular:2.3.0
expo-constants:9.2.0
expo-contacts:8.5.0
expo-crypto:8.3.0
expo-device:2.3.0
expo-document-picker:8.4.0
expo-error-recovery:1.3.0
expo-face-detector:8.3.0
expo-facebook:9.0.0
expo-file-system:9.2.0
expo-firebase-analytics:2.5.0
expo-firebase-core:1.2.0
expo-font:8.3.0
expo-gl:9.1.1
expo-gl-cpp:9.1.2
expo-gl-cpp-legacy:8.4.0
expo-google-sign-in:8.3.0
expo-haptics:8.3.0
expo-image-loader:1.2.0
expo-image-manipulator:8.3.0
expo-image-picker:9.1.1
expo-permissions:9.3.0
expo-in-app-purchases:9.0.0
expo-intent-launcher:8.3.0
expo-keep-awake:8.3.0
expo-linear-gradient:8.3.0
expo-local-authentication:9.3.0
expo-localization:9.0.0
expo-location:9.0.0
expo-mail-composer:8.4.0
expo-media-library:9.2.1
expo-module-template:8.4.0
expo-network:2.3.0
expo-notifications:0.7.2
expo-payments-stripe:8.3.0
expo-print:9.1.0
expo-screen-capture:1.1.1
expo-screen-orientation:2.0.0
expo-secure-store:9.2.0
expo-sensors:9.1.0
unimodules-sensors-interface:5.3.0
expo-sharing:8.4.1
expo-sms:8.3.1
expo-speech:8.4.0
expo-splash-screen:0.6.2
expo-sqlite:8.4.0
expo-store-review:2.2.0
expo-updates:0.3.3
expo-video-thumbnails:4.3.0
expo-web-browser:8.5.0
My suggestion will be for you to upgrade to EAS, with EAS your build size is reduced by more than 3/4, however, at this point, you have to pay $29 but I promise you it's worth it. An app I have been working on prompting into EAS reduced the bundle size from 80MB to 16MB😱. EAS also has EAS submit which enables you submit your app to the stores in a Flash
You can avoid copying the source code from the existing expo project to another project as suggested in this comment
If you use eas build (not expo build) you can try to set up enableProguardInReleaseBuilds param in app.json.
Example:
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"android": {
"enableProguardInReleaseBuilds": true,
}
}
]
]
}
}
Reference: https://docs.expo.dev/versions/latest/sdk/build-properties/#pluginconfigtypeandroid
Upgrade react-native to newer version, for different versions it is giving different size apk.
for 0.57 it was ≈12mb
for 0.59.3 it was ≈30mb
and for 0.59.9 it was ≈15mb
always try to use updated react-native version
There are basically two options for reducing size of apk file from 32mb(expo) to 7mb(react-native cli).
Detach from expo
create new react-native cli project and copy all source from expo to new react-native project.
Upgrade expo version to 31.exporecently launched single-SDK builds for Android. These builds contain only the SDK version the app uses when built and are both faster and slimmer. it helps for smaller standalone app build size. release note
Vote over here so that expo can look into the feature https://expo.canny.io/feature-requests/p/reducing-app-size Problem is react-native uses hermes so the packaging is similar to what native android app from android studio can do but since herme is like latest about 1-2year expo team has not made the support for hermes please vote.. And I also totally agree with #jakobinn
I went through the documentation looking for the way how to disable dexguard when running gradle but keeping plugin: 'dexguard'.
I tried to modify proguardFile getDefaultDexGuardFile('dexguard-debug.pro') to do nothing but unfortunately no luck. I need to set no dexguard functionality for my functional testing suit MonkeyTalk which cannot instrument the apk now.
How to turn the dexguard functionality off?
Update from zatziky's answer for current Android Gradle Plugin (v1.0+) and Dexguard Plugin (6.1.+)
To create a dexguard plugin switch you may do the following
In your root build.gradle add a property to your ext (or create it if not done yet, see here why you would do that)
ext {
enableDexGuardPlugin = false
....
}
In your app build.gradle add the plugin like this:
apply plugin: 'com.android.application'
if(rootProject.ext.enableDexGuardPlugin) {
apply plugin: 'dexguard'
}
and if you have library projects do it like this
apply plugin: 'com.android.library'
if(rootProject.ext.enableDexGuardPlugin) {
apply plugin: 'dexguard'
}
remove all proguard configs from your debug build-types (especially getDefaultDexGuardFile('dexguard-release.pro')) if you dont need them. Unfortunatly at least with lib projects, all buil-types are build even in assembleDebug, so you have to provide a stub for getDefaultDexGuardFile like zatziky said:
private File getDefaultDexGuardFile(String name) { new File(name) }
you may add this to your root build.gradle so every script has it.
Now if you expected huge performance benefits from that you may be disapointed. The key is to disable ALL minifyEnabled on debug builds, since as said before currently gradle android is dumb and builds all build-types (at least with libs). You may use the property above for it: enableDexGuardPlugin
release {
...
minifyEnabled rootProject.ext.enableDexGuardPlugin
...
}
It is not possible to keep the dexguard plugin on.
This is a workaround that Eric La Fortune send me and it works (Dexguard 6.x):
For disabling DexGuard, you would need to revert to the Android plugin. You could create a separate Gradle builld file. Alternatively, you could pick the preferred plugin with Groovy. E.g. in
build.gradle:
boolean dexguard = ......
apply plugin: dexguard ? 'dexguard' : 'android'
You can also call the utility method getDefaultDexGuardFile in the same way:
runProguard true
proguardFile dexguard ?
getDefaultDexGuardFile('dexguard-release.pro') :
getDefaultProguardFile('proguard-android.txt')
You do need to define a dummy version of this method in the build file, in case the standard Android plugin is chosen. It is not called in either case, but it solves the missing method definition for the standard plugin:
private File getDefaultDexGuardFile(String name) { new File(name) }
In the recent versions of DexGuard you can disable processing for specific build variants simply by not listing the 'proguardFile' lines.
So for example, to disable it for the debug build:
buildTypes {
debug {
}
release {
proguardFile getDefaultDexGuardFile('dexguard-release.pro')
proguardFile 'dexguard-project.txt'
proguardFile 'proguard-project.txt'
}
}
Edit - all proguardFiles must be gone for it to work