I have a react-native application with android target.
I also have a separate android application and I need to integrate react-natie part there. But I need to do it without react-native environment dependencies so other developers could work without setting it up.
It seems that the best way to do it is to pack all the react-native application into AAR, then publish it in maven or just add in in lib folder of target application.
To build AAR instead of APK I've done the following in react-native android project:
com.android.application
to com.android.library
applicationId
I've managed to build an AAR, but the problem is it misses all the dependencies like com.facebook.react.ReactActivity
and other classes from this dependencies. There is no bundled js assets in the AAR.
When I'm building APK all these components are there.
In react-native android module level gradle I've set project.ext.react.bundleInDebug: true
I'm building AAR with gradlew build
There were one problem building AAR: gradle failed wit an error:
FAILURE: Build failed with an exception.
* Where:
Script 'C:\proj\react-native\node_modules\react-native\react.gradle' line: 353
* What went wrong:
A problem occurred configuring project ':app'.
> Cannot invoke method doFirst() on null object
This means there is no packageDebug
/packageRelease
tasks that are required by node_modules\react-native\react.gradle' at line #353
There are such tasks when building with application plugin. Probably the problem is here.
To overcome this problem I've added stub-tasks.
Versions I'm using:
react-native: 0.63.5
com.android.tools.build:gradle:4.1.3 (gradle: 6.9)
I've solved my task. As there is so much interest to subject, I will post the solution.
.pom
to include theese dependencies.react-native
and android-jsc-intl
dependenies into my repo manually.In the root build.gradle
subprojects {
apply plugin: "maven-publish"
project.afterEvaluate {
if (!plugins.hasPlugin("android")) {
publishing {
publications {
release(MavenPublication) {
afterEvaluate {
// @ - cant be a part of artifactId
artifactId = project.name.replace('@', '')
if (plugins.hasPlugin("java")) {
from components.java
} else if (plugins.hasPlugin("android-library")) {
if (project.name == "MY_LIBRARY_MODULE") {
groupId 'com.my_librayr'
artifactId 'my_library'
version '1.0.0' // Change version each publication. I use env variable and external script for track version number.
artifact sourceJar
def aarDir = "$buildDir/outputs/aar/"
File[] files = (new File(aarDir)).listFiles()
for (file in files) {
if (file.path.endsWith(".aar")) artifact file.path
}
pom.withXml {
def node = asNode()
((NodeList) node.get('packaging')).get(0).value = 'aar'
def dependenciesNode = node.appendNode('dependencies')
def includeDependency = { Dependency dep ->
println("includeDependency : ${dep.name}")
if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified") return
// To save group names (to load from different places, or to use manually loaded packages), all other dependencies would go to android group
def persistGroupName = [
'com.facebook.react',
'androidx.swiperefreshlayout',
'androidx.appcompat',
'com.google.firebase',
].any { dep.group.startsWith(it) }
def persistGroupNameForArtifactNames = [
'kotlin-stdlib-jdk8',
'android-jsc-intl',
'react-native-appmetrica',
YET_ANOTHER_LIBRARY_MODYULE_OF_YOUR_PROJECT
].any { dep.name.startsWith(it) }
def groupId
if (persistGroupName || persistGroupNameForArtifactNames) {
groupId = dep.group
} else {
groupId = 'android'
}
def depName = dep.name.replace('@', '')
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('artifactId', depName)
dependencyNode.appendNode('groupId', groupId)
dependencyNode.appendNode('version', dep.version)
}
configurations.api.getAllDependencies().each includeDependency
configurations.implementation.getAllDependencies().each includeDependency
configurations.compile.getAllDependencies().each includeDependency
}
} else {
// This branch is needed to change groupId and version of your library. Use it if you have a module your library depends on
if (project.name == YET_ANOTHER_LIBRARY_MODYULE_OF_YOUR_PROJECT) {
groupId 'my_library'
version '1.0.0'
}
def generalRelease = components.find { it.name == "generalRelease" }
if (generalRelease != null) from generalRelease else from components.release
tasks.withType(GenerateModuleMetadata) { enabled = false }
}
}
}
}
}
// Setting repository to buplish to
repositories {
maven {
url "http://nexus.local/megarepo"
credentials {
username "login"
password "password"
}
}
}
}
}
}
}
Adding missing tasks in modules build.gradle
addDummyPackageTask(tasks, "release")
addDummyPackageTask(tasks, "debug")
def addDummyPackageTask(TaskContainer tasks, String typeName) {
def name = "package${typeName.capitalize()}"
if (tasks.findByName(name) == null) {
tasks.register(name) {
doLast {
}
}
}
}
Wont pust more explanations. If you need some more - ask. I will try my best to answer.