1 | import com.android.Version
|
2 | import groovy.json.JsonSlurper
|
3 |
|
4 | buildscript {
|
5 | ext {
|
6 | rnsDefaultTargetSdkVersion = 34
|
7 | rnsDefaultCompileSdkVersion = 34
|
8 | rnsDefaultMinSdkVersion = 21
|
9 | rnsDefaultKotlinVersion = '1.8.0'
|
10 | }
|
11 | ext.safeExtGet = {prop, fallback ->
|
12 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
13 | }
|
14 | repositories {
|
15 | google()
|
16 | mavenCentral()
|
17 | }
|
18 | dependencies {
|
19 | classpath('com.android.tools.build:gradle:4.2.2')
|
20 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion', rnsDefaultKotlinVersion)}"
|
21 | classpath "com.diffplug.spotless:spotless-plugin-gradle:6.11.0"
|
22 | }
|
23 | }
|
24 |
|
25 | def isRunningInContextOfScreensRepo() {
|
26 | return project == rootProject
|
27 | }
|
28 |
|
29 | def isNewArchitectureEnabled() {
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
35 | }
|
36 |
|
37 |
|
38 | if (isRunningInContextOfScreensRepo()) {
|
39 | apply from: 'spotless.gradle'
|
40 | }
|
41 |
|
42 | if (isNewArchitectureEnabled()) {
|
43 | apply plugin: "com.facebook.react"
|
44 | }
|
45 | apply plugin: 'com.android.library'
|
46 | apply plugin: 'kotlin-android'
|
47 |
|
48 | def reactNativeArchitectures() {
|
49 | def value = project.getProperties().get("reactNativeArchitectures")
|
50 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
51 | }
|
52 |
|
53 | def safeAppExtGet(prop, fallback) {
|
54 | def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
|
55 | appProject?.ext?.has(prop) ? appProject.ext.get(prop) : fallback
|
56 | }
|
57 |
|
58 | def resolveReactNativeDirectory() {
|
59 | def reactNativeLocation = safeAppExtGet("REACT_NATIVE_NODE_MODULES_DIR", null)
|
60 | if (reactNativeLocation != null) {
|
61 | return file(reactNativeLocation)
|
62 | }
|
63 |
|
64 | def reactNativeFromAppNodeModules = file("${projectDir}/../../react-native")
|
65 | if (!isRunningInContextOfScreensRepo() && reactNativeFromAppNodeModules.exists()) {
|
66 | return reactNativeFromAppNodeModules
|
67 | }
|
68 |
|
69 | def reactNativeFromProjectNodeModules = file("${rootProject.projectDir}/../node_modules/react-native")
|
70 | if (reactNativeFromProjectNodeModules.exists()) {
|
71 | return reactNativeFromProjectNodeModules
|
72 | }
|
73 |
|
74 | throw new GradleException(
|
75 | "[RNScreens] Unable to resolve react-native location in node_modules. You should add project extension property (in `app/build.gradle`) `REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
|
76 | )
|
77 | }
|
78 |
|
79 | def reactNativeRootDir = resolveReactNativeDirectory()
|
80 | def reactProperties = new Properties()
|
81 | file("$reactNativeRootDir/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
|
82 | def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
|
83 | def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
|
84 |
|
85 | android {
|
86 | compileSdkVersion safeExtGet('compileSdkVersion', rnsDefaultCompileSdkVersion)
|
87 | def agpVersion = Version.ANDROID_GRADLE_PLUGIN_VERSION
|
88 | if (agpVersion.tokenize('.')[0].toInteger() >= 7) {
|
89 | namespace "com.swmansion.rnscreens"
|
90 | buildFeatures {
|
91 | buildConfig true
|
92 | }
|
93 | }
|
94 |
|
95 |
|
96 |
|
97 | if (rootProject.hasProperty("ndkPath")) {
|
98 | ndkPath rootProject.ext.ndkPath
|
99 | }
|
100 | if (rootProject.hasProperty("ndkVersion")) {
|
101 | ndkVersion rootProject.ext.ndkVersion
|
102 | }
|
103 |
|
104 | defaultConfig {
|
105 | minSdkVersion safeExtGet('minSdkVersion', rnsDefaultMinSdkVersion)
|
106 | targetSdkVersion safeExtGet('targetSdkVersion', rnsDefaultTargetSdkVersion)
|
107 | versionCode 1
|
108 | versionName "1.0"
|
109 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
110 | ndk {
|
111 | abiFilters (*reactNativeArchitectures())
|
112 | }
|
113 | externalNativeBuild {
|
114 | cmake {
|
115 | arguments "-DANDROID_STL=c++_shared"
|
116 | }
|
117 | }
|
118 | }
|
119 | if (REACT_NATIVE_MINOR_VERSION >= 71) {
|
120 | buildFeatures {
|
121 | prefab true
|
122 | }
|
123 | externalNativeBuild {
|
124 | cmake {
|
125 | path "CMakeLists.txt"
|
126 | }
|
127 | }
|
128 | }
|
129 | lintOptions {
|
130 | abortOnError false
|
131 | }
|
132 | compileOptions {
|
133 | sourceCompatibility JavaVersion.VERSION_1_8
|
134 | targetCompatibility JavaVersion.VERSION_1_8
|
135 | }
|
136 | packagingOptions {
|
137 |
|
138 |
|
139 |
|
140 |
|
141 | excludes = [
|
142 | "META-INF",
|
143 | "META-INF/**",
|
144 | "**/libjsi.so",
|
145 | "**/libc++_shared.so",
|
146 | "**/libreact_render*.so"
|
147 | ]
|
148 | }
|
149 | sourceSets.main {
|
150 | ext.androidResDir = "src/main/res"
|
151 | java {
|
152 | if (isNewArchitectureEnabled()) {
|
153 | srcDirs += [
|
154 | "src/fabric/java",
|
155 | ]
|
156 | } else {
|
157 | srcDirs += [
|
158 | "src/paper/java",
|
159 | ]
|
160 | }
|
161 | }
|
162 | res {
|
163 | if (safeExtGet('compileSdkVersion', rnsDefaultCompileSdkVersion) >= 33) {
|
164 | srcDirs = ["${androidResDir}/base", "${androidResDir}/v33"]
|
165 | } else {
|
166 | srcDirs = ["${androidResDir}/base"]
|
167 | }
|
168 | }
|
169 | }
|
170 | }
|
171 |
|
172 | repositories {
|
173 | maven {
|
174 |
|
175 |
|
176 |
|
177 | url "$projectDir/../node_modules/react-native/android"
|
178 | }
|
179 | mavenCentral()
|
180 | mavenLocal()
|
181 | google()
|
182 | }
|
183 |
|
184 | dependencies {
|
185 | implementation 'com.facebook.react:react-native:+'
|
186 | implementation 'androidx.appcompat:appcompat:1.4.2'
|
187 | implementation 'androidx.fragment:fragment:1.3.6'
|
188 | implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
|
189 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
190 | implementation 'com.google.android.material:material:1.6.1'
|
191 | implementation "androidx.core:core-ktx:1.8.0"
|
192 |
|
193 | constraints {
|
194 | implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1") {
|
195 | because("on older React Native versions this dependency conflicts with react-native-screens")
|
196 | }
|
197 | }
|
198 | }
|
199 |
|
200 | def isScreensExampleApp() {
|
201 | return project.hasProperty('isScreensExampleApp') && project.property('isScreensExampleApp') == "true"
|
202 | }
|
203 |
|
204 | def getAbsoluteCodegenArtifactsPaperDestination() {
|
205 | if (!project.hasProperty('codegenArtifactsPaperDestination')) {
|
206 | throw new Exception('[RNScreens] Please fill codegenArtifactsPaperDestination variable in android/gradle.properties correct path to paper paper destination')
|
207 | }
|
208 |
|
209 | return "${project.rootDir}/../../${project.property('codegenArtifactsPaperDestination')}"
|
210 | }
|
211 |
|
212 | def getAbsoluteCodegenArtifactsSource() {
|
213 | if (!project.hasProperty('codegenArtifactsSource')) {
|
214 | throw new Exception('[RNScreens] Please fill codegenArtifactsSource variable in android/gradle.properties correct path to codegenerated artifacts')
|
215 | }
|
216 |
|
217 | return "${project.rootDir}/../../${project.property('codegenArtifactsSource')}"
|
218 | }
|
219 |
|
220 |
|
221 | tasks.register("copyCodegenArtifacts") {
|
222 | group 'After build tasks'
|
223 | description 'Tasks which copy codegen artifacts to paper architecture'
|
224 |
|
225 | if (!isScreensExampleApp() || !isNewArchitectureEnabled()) {
|
226 | return
|
227 | }
|
228 |
|
229 | dependsOn tasks.generateCodegenArtifactsFromSchema
|
230 |
|
231 | doLast {
|
232 |
|
233 | def absoluteCodegenArtifactsPaperDestination = getAbsoluteCodegenArtifactsPaperDestination()
|
234 | def absoluteCodegenArtifactsSource = getAbsoluteCodegenArtifactsSource()
|
235 |
|
236 | def existingFiles = fileTree(absoluteCodegenArtifactsPaperDestination).matching {
|
237 | include '**/*.java'
|
238 | }
|
239 |
|
240 | def generatedFiles = fileTree(absoluteCodegenArtifactsSource).matching {
|
241 | include '**/*.java'
|
242 | }
|
243 |
|
244 | def existingFilesMap = [:]
|
245 |
|
246 | existingFiles.forEach { existingFile ->
|
247 | existingFilesMap[existingFile.name] = 1
|
248 | }
|
249 |
|
250 | generatedFiles.forEach { generatedFile ->
|
251 | if (!existingFilesMap.containsKey(generatedFile.name)) {
|
252 | logger.warn("[RNScreens] ${generatedFile.name} not found in paper dir, if it's used in Android you need to copy it manually and implement yourself before using auto-copy feature")
|
253 | }
|
254 | }
|
255 |
|
256 | if (existingFiles.size() == 0) {
|
257 | logger.warn("[RNScreens] Paper destination with codegen interfaces is empty. This might be okay if you don't have any interfaces/delegates used in Android, if that's not the case please check if codegenArtifactsPaperDestination in android/gradle.properties is correct")
|
258 | }
|
259 |
|
260 | if (existingFiles.size() > generatedFiles.size()) {
|
261 | throw new Exception("[RNScreens] Number od generated artifacts should be greather then or equal to paper interfaces. Please check if codegenArtifactsSource in android/gradle.properties is correct")
|
262 | }
|
263 |
|
264 | copy {
|
265 | from absoluteCodegenArtifactsSource
|
266 | include existingFiles.collect { it.name }
|
267 | into absoluteCodegenArtifactsPaperDestination
|
268 | }
|
269 | }
|
270 | }
|
271 |
|
272 | if (isScreensExampleApp() && isNewArchitectureEnabled()) {
|
273 | tasks.generateCodegenArtifactsFromSchema.finalizedBy('copyCodegenArtifacts')
|
274 | }
|