In this tutorial, we will learn how to add our React Native library to our Native app from Maven. we will publish our library into Github Packages I’ll assume that you followed this tutorial on how your add your react native app to an existing native app the goal is to be able to do it like this
1 2 3 |
... implementation 'com.appfiza.android:my-react-native-lib:1.0.0' ... |
After doing the react-native tutorial, you’ll have something like that
Note : I did a little refactoring here, rather than putting the MyReactActivity in the app module, I put it in the new module my-react-native-lib.
Note 2: In the package.json file I added some dependencies.
Now if we publish everything to Maven, when trying to retrieve our library in another project, it stills need the main dependencies that are :
1 2 |
implementation "com.facebook.react:react-native:+" implementation "org.webkit:android-jsc:+" |
And these two dependencies are in node_modules, you can’t get them from Maven (the new versions), so the only solution I found is to add their aar files as modules and to publish them.
So now go to your node_modules -> react-native -> android -> com -> facebook -> react -> react-native -> 0.64.2
Inside it, you’ll find the file react-native-0.64.2.aar and add it as a module, I don’t know why in the new Android Studio version they removed AAR file importation, if you struggle with that just copy/paste my directory react-native in your android folder.
But there is a step missing, inside 0.64.2 folder, you will find a pom xml file called react-native-0.64.2.pom this will list all the dependencies our aar needs
We need to add them to our module my-react-native-lib
So go to my-react-native.lib’s build.gradle file and add the following implementations
1 2 3 4 5 6 7 8 9 |
implementation "com.facebook.fbjni:fbjni-java-only:0.0.3" implementation "com.facebook.soloader:soloader:0.9.0" implementation "com.facebook.infer.annotation:infer-annotation:0.11.2" implementation "com.facebook.fresco:imagepipeline-okhttp3:2.0.0" implementation "com.facebook.fresco:fresco:2.0.0" implementation "com.facebook.yoga:proguard-annotations:1.14.1" implementation "javax.inject:javax.inject:1" implementation "com.squareup.okhttp3:okhttp-urlconnection:3.12.12" implementation "com.squareup.okhttp3:okhttp:3.12.12" |
Now, same thing for android-jsc dependency, go to node_modules -> jsc-android -> dist -> org -> webkit -> android-jsc -> r245459 as above your import the android-jsc-r245459.aar file as a module.
So now our project structure will look like that
The publishing
For the publishing part, you need to check out my previous tutorial about how to publish a multi-module Android library
Go to project’s build.gradle file and add the following code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
subprojects { apply plugin: "maven-publish" project.afterEvaluate { if (!plugins.hasPlugin("android")) { publishing { publications { release(MavenPublication) { afterEvaluate { artifactId = project.name if (plugins.hasPlugin("java")) { from components.java } else if (plugins.hasPlugin("android-library")) { def generalRelease = components.find { it.name == "generalRelease" } if (generalRelease != null) from generalRelease else from components.release tasks.withType(GenerateModuleMetadata) { enabled = false } pom.withXml { def hasDependencies = !asNode().dependencies.isEmpty() if (hasDependencies) { asNode().dependencies.first().each { def groupId = it.get("groupId").first().value().first() if (groupId == "com.facebook.react") { it.get("groupId").first().value = "com.appfiza.android" it.get("artifactId").first().value = "react-native" it.get("version").first().value = version } if (groupId == "org.webkit") { it.get("groupId").first().value = "com.appfiza.android" it.get("artifactId").first().value = "jsc-android" it.get("version").first().value = version } } } } } /** * To publish libraries that have aar files */ else { if (project.name == "jsc-android") { artifact(file("$projectDir/android-jsc-r245459.aar")) } else if (project.name == "react-native") { artifact(file("$projectDir/react-native-0.64.2.aar")) } else { def inputFile = new File(projectDir, '../../react-native/package.json') def json = new JsonSlurper().parseText(inputFile.text) def reactNativeVersion = json.version as String def (major, minor, patch) = reactNativeVersion.tokenize('.') def engine = "jsc" if (project(':app').ext.react.enableHermes) { engine = "hermes" } artifact(file("../node_modules/$project.name/android/react-native-reanimated-${minor}-${engine}.aar")) } } } } } repositories { maven { url = getRepositoryUrl() credentials { username = System.getenv('GITHUB_USER') password = System.getenv('GITHUB_TOKEN') } } } } } } } def getRepositoryUrl() { return "https://maven.pkg.github.com/BackPackerDz/react-native-to-native-tuto/" } |
What are we doing here? we’re publishing every module to Maven (Java, Android, AAR), so when we’ll try to get our lib from another project it will have all the dependencies needed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
tasks.withType(GenerateModuleMetadata) { enabled = false } pom.withXml { def hasDependencies = !asNode().dependencies.isEmpty() if (hasDependencies) { asNode().dependencies.first().each { def groupId = it.get("groupId").first().value().first() if (groupId == "com.facebook.react") { it.get("groupId").first().value = "com.appfiza.android" it.get("artifactId").first().value = "react-native" it.get("version").first().value = version } if (groupId == "org.webkit") { it.get("groupId").first().value = "com.appfiza.android" it.get("artifactId").first().value = "jsc-android" it.get("version").first().value = version } } } } |
When you publish to Maven with Gradle, by default it will try to publish a Gradle metadata file, that contains all the dependencies needed by the module, it’s the same thing as a pom xml file, so in the first line, we’re disabling it, in our case we just need pom file.
And for com.facebook.react and org.webkit we’re telling to Gradle that if you find those dependencies replace it with react-native and jsc-android, rather than pointing to com.facebook.react it will point to react-native, by doing that we avoid using node_modules
After publishing, if we check our repository it will look like that
I made a project that implements our react-native library you can find it below
https://github.com/BackPackerDz/TestBridgeReact
and here is the link to the react-native lib
https://github.com/BackPackerDz/react-native-to-native-tuto
If you have any questions, feel free to ask 🙏
Thank you for this article. I have question from where you get this maven url https://maven.pkg.github.com/BackPackerDz/react-native-to-native-tuto/ in project build.gradle in Android repo. Or can we direct use library repo url?