Skip to content

Commit 10a17c6

Browse files
author
Martin Konicek
committed
Add support for split build per architecture
Summary: This allows everyone to deploy significantly smaller APKs to they Play Store by building separate APKs for ARM, x86 architectures. For a simple app, a release APK minified with Produard: - Universal APK is **7MB** - x86 APK is **4.6MB** (34% reduction) - ARM APK is **3.7MB** (47% reduction) Created a sample project, uncommented `// include "armeabi-v7a", 'x86'`: cd android ./gradlew assembleDebug Three APKs were created, unzipped each: one has only x86 binaries, one has ARM binaries, one has both. ./gradlew assembleRelease Three APKs were created, JS bundle is correcly added to assets. react-native run-android The correct APK is installed on the emulator and the app runs fine (Gradle output: "Installing APK 'app-x86-debug.apk'"). With the line commented out the behavior is exactly the same as before, only one universal APK is built. Checked that version codes are set correctly as described in http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits http://developer.android.com/intl/ru/google/play/publishing/multiple-apks.html Closes #5160 Reviewed By: svcscm Differential Revision: D2811443 Pulled By: mkonicek fb-gh-sync-id: 97b22b9cd567e53b8adac36669b90768458b7a55
1 parent 239eb4b commit 10a17c6

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

local-cli/generator-android/templates/src/app/build.gradle

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
apply plugin: "com.android.application"
22

3+
import com.android.build.OutputFile
4+
35
/**
46
* The react.gradle file registers two tasks: bundleDebugJsAndAssets and bundleReleaseJsAndAssets.
57
* These basically call `react-native bundle` with the correct arguments during the Android build
@@ -49,6 +51,22 @@ apply plugin: "com.android.application"
4951

5052
apply from: "react.gradle"
5153

54+
/**
55+
* Set this to true to create three separate APKs instead of one:
56+
* - A universal APK that works on all devices
57+
* - An APK that only works on ARM devices
58+
* - An APK that only works on x86 devices
59+
* The advantage is the size of the APK is reduced by about 4MB.
60+
* Upload all the APKs to the Play Store and people will download
61+
* the correct one based on the CPU architecture of their device.
62+
*/
63+
def enableSeparateBuildPerCPUArchitecture = false
64+
65+
/**
66+
* Run Proguard to shrink the Java bytecode in release builds.
67+
*/
68+
def enableProguardInReleaseBuilds = true
69+
5270
android {
5371
compileSdkVersion 23
5472
buildToolsVersion "23.0.1"
@@ -63,12 +81,33 @@ android {
6381
abiFilters "armeabi-v7a", "x86"
6482
}
6583
}
84+
splits {
85+
abi {
86+
enable enableSeparateBuildPerCPUArchitecture
87+
universalApk true
88+
reset()
89+
include "armeabi-v7a", "x86"
90+
}
91+
}
6692
buildTypes {
6793
release {
68-
minifyEnabled false // Set this to true to enable Proguard
94+
minifyEnabled enableProguardInReleaseBuilds
6995
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
7096
}
7197
}
98+
// applicationVariants are e.g. debug, release
99+
applicationVariants.all { variant ->
100+
variant.outputs.each { output ->
101+
// For each separate APK per architecture, set a unique version code as described here:
102+
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
103+
def versionCodes = ["armeabi-v7a":1, "x86":2]
104+
def abi = output.getFilter(OutputFile.ABI)
105+
if (abi != null) { // null for the universal-debug, universal-release variants
106+
output.versionCodeOverride =
107+
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
108+
}
109+
}
110+
}
72111
}
73112

74113
dependencies {

local-cli/generator-android/templates/src/app/react.gradle

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,33 @@ task bundleReleaseJsAndAssets(type: Exec) {
7474
enabled config.bundleInRelease ?: true
7575
}
7676

77+
void runBefore(String dependentTaskName, Task task) {
78+
Task dependentTask = tasks.findByPath(dependentTaskName);
79+
if (dependentTask != null) {
80+
dependentTask.dependsOn task
81+
}
82+
}
83+
7784
gradle.projectsEvaluated {
85+
7886
// hook bundleDebugJsAndAssets into the android build process
87+
7988
bundleDebugJsAndAssets.dependsOn mergeDebugResources
8089
bundleDebugJsAndAssets.dependsOn mergeDebugAssets
81-
processDebugResources.dependsOn bundleDebugJsAndAssets
90+
91+
runBefore('processArmeabi-v7aDebugResources', bundleDebugJsAndAssets)
92+
runBefore('processX86DebugResources', bundleDebugJsAndAssets)
93+
runBefore('processUniversalDebugResources', bundleDebugJsAndAssets)
94+
runBefore('processDebugResources', bundleDebugJsAndAssets)
8295

8396
// hook bundleReleaseJsAndAssets into the android build process
97+
8498
bundleReleaseJsAndAssets.dependsOn mergeReleaseResources
8599
bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets
86-
processReleaseResources.dependsOn bundleReleaseJsAndAssets
100+
101+
runBefore('processArmeabi-v7aReleaseResources', bundleReleaseJsAndAssets)
102+
runBefore('processX86ReleaseResources', bundleReleaseJsAndAssets)
103+
runBefore('processUniversalReleaseResources', bundleReleaseJsAndAssets)
104+
runBefore('processReleaseResources', bundleReleaseJsAndAssets)
105+
87106
}

0 commit comments

Comments
 (0)