Two android projects sharing common module in same repository using gradle - android

We are creating an app (actually 2) that is split up in 2 separate projects but sharing the same GIT repository (2 separate folders in git root). It is one app for handheld and one for another platform. But they should share some code like Utils, API calls etc.
Folder structure looks like this:
-GIT Root
-- Project (Project)
--- App 1 (Android application)
--- App 2 (Android application)
--- Common (Android library)
App1 and App2 should be able to reach code from common but not the other way of course.
Tried to do like above and using Gradle but it doesn't seem to work. I know that sharing the same git repo for both apps may not be the best way to handle this scenario but I'm having no options here.
Do you think that this is possible to do somehow? (Maybe I'm just not understanding modules correctly or something like that)
I'm new to Gradle which makes this even harder..

This is not too hard to do if all three projects are in the same Git repository. Here is the skeleton of how your projects should be setup:
App1 (Android application)
|_ build.gradle
|_ src
App2 (Android application)
|_ build.gradle
|_ src
Common (Android library)
|_ build.gradle
|_ src
settings.gradle
build.gradle
The top-level build.gradle file can have common gradle settings that you will use for all sub-projects
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
}
}
allprojects {
repositories {
mavenCentral()
}
}
Make sure the settings.gradle file includes all your projects:
include ':App1'
include ':App2'
include ':Common'
Setup Common to be a Android library project. In the build.gradle file for Common add the line:
apply plugin: 'com.android.library'
Setup the other two projects to be Android applications, and include the Common project as a dependency.
apply plugin: 'com.android.application'
dependencies {
compile project(':Common')
:
:
}

You should have three git repos for this. App1, App2 and Common.
Make common a library project using gradle.
apply plugin: 'com.android.library'
You can use the android maven plugin to build the aar locally and make it available to each child app. Add classpath 'com.github.dcendents:android-maven-plugin:1.2' AND apply plugin: 'com.github.dcendents.android-maven'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
classpath 'com.github.dcendents:android-maven-plugin:1.2'
}
}
apply plugin: 'com.github.dcendents.android-maven'
Define group and version of library app
group = 'com.foo.example'
version = '1.0.0-SNAPSHOT'
Install library app locally using ./gradlew installDebug
Child Apps
Now the parent app can be included in the child app as a dependency. Add dependency to build.gradle.
compile('com.foo.example:library:1.0.0-SNAPSHOT#aar') {transitive = true}
Each time you make a change to the library app you will have to reinstall it. Then you have to resync the gradle files in your children app. Tools -> Android -> Sync Project With Gradle Files

Related

Adding Kotlin runtime library to aar in android

WHAT I WANT :smile: :
building kotlin library,
deliver it as an .aar file
Java project that uses my .aar don’t need configure anything, just include my .aar and start playing.
first Q : IT THAT EVEN Possible ? cause i’m loosing hope :smile:
if the project that uses my library doesn’t have Kotlin configured, then it says ClassNotFoundException.
-WHY IS THAT ?
if kotlin have the same byte code as Java byte code, (and 100% compatible),
then why i need to have kotlin when using .aar writen in kotlin in a JAVA Project ?
After some reaserch, i discovered that i must include kotlin runtime library in my project but i don’t know how,
i’ve allready tried basically all the solution overs the net ,
i think fat aar isn’t supported on Android,
Thank You All for your attention.
Update
in my aar project i have a module with the following build.gradle
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
/////
.
.
dependencies {
////
.
.
api "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
in my application that uses the .aar
i have the following in project build.gradle
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
}
in the build.gralde module
implementation(name: 'my-aar-library', ext: 'aar')
and when i run the app, it crash and here is the stack :
09-25 15:14:22.814 3239-3239/com.example.mymodule E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mymodule, PID: 3239
java.lang.NoClassDefFoundError: kotlin.jvm.internal.Intrinsics
at com.com.example.mymodule.views.MyCustomView.<init>(PCMajorHeadereView.kt)
at .
.
.
.
.
.
UPDATE 2 :
PS :
clearly i must add the kotlin runtime-library to my .aar
i tried all over the net, it doesn’t work :'(
Final Update :
solution found thanks to cilling,
note that you must include the runtime-library into the local maven repo,
it can't access online content
Thnx for all
The problem is that your aar doesn't include dependency tree (.pom file), so Gradle is not able to download them during the sync.
So, what's the proper solution? You should use repository manager, like Maven.
You can see #Robyer post how to include all dependencies and publish it on MavenLocal:
https://stackoverflow.com/a/42160584/7508302
That post is about providing source code for library, but there is also ready to use gradle publish script.
Then, in your 'local maven' a library will be published.
And then, you can add to your gradle file (in project you want to use that library): repositories { mavenLocal() } and then add dependecy like this:
implementation ('com.example.android:library:0.0.1-SNAPSHOT#aar') {
transitive = true
}
Full instruction:
1) In your library add a gradle file responsible for publishing on mavenLocal(). See https://stackoverflow.com/a/42160584/7508302 for details
and ready to use script.
2) Push the library to mavenLocal. It's a local maven repository. You don't need to install anything, as the maven repository just has to have proper dir structure.
3) Check mavenLocal dir. There should be a dir tree with your domain name, for example: com -> mycompany -> library -> 0.0.1 and in that folder you should find .pom file. Open it, to see dependencies of your library.
4) Add mavenLocal() to your repository section in project level gradle file. Note, that mavenLocal just points to some place in your files.
5) Add library dependency using just qualified name (for example: com.mycompany:library:0.0.1#aar. Add parameter transitive if you want to fetch transitive dependencies (that transitive parameter means that that library may depend on other modules).
That way gradle should fetch declared dependencies and include them to project.
Call the below call for smile.aar file in build.gradle file.
implementation project(':smile)
Assuming that smile is the .aar file name.
If you want to run Kotlin you must include following in project build.gradle
buildscript {
ext.kotlin_version = '1.3.31'
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
and also include these in app level build.gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
//in dependencies
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

Reusing the same code across multiple Android Studio projects

I have some code I'd like to use across multiple different projects. Let's say it's some e-commerce code that handles things like payments and shopping carts.
It seems inefficient and dangerous to copy-paste everything across different projects. And if I add one feature or fix one bug in the core e-commerce module, I'd like that change to be reflected in other projects using it too.
I would also like to re-use some of the Activities, Fragments, Adapters too.
What is a good approach to this?
When we have a library project that needs to be shared to every project on a local computer, we can make use of Maven.
A. Here the step in your library that we will you for the project:
Make a library project from Android Studio.
Add Gradle Android Maven plugin to root build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
}
}
Add apply plugin for step 1 in your library build.gradle. (NOT root build.gradle):
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
Add the following after the apply plugin, this line to determine your library when adding to project:
group = 'com.yourpackage.yourlibrary'
version = '1.0'
Add the following code in your settings.gradle:
rootProject.name = 'yourlibrary'
Then publish it to your local maven with:
./gradlew install
Or you can use gradle option in Android Studio.
Your library will be installed in $HOME/.m2/repository. Remember that to use the library you need to add like this:
Groupid:artifactid:versionid
Artifactid will be package name of your library.
B. Here the step in your Project which using the library:
Add the following code in your root build.gradle:
mavenLocal() // for local maven.
This for getting the local library maven that we have installed in step A
Then in your app project.gradle, add compile for the library:
compile 'com.yourpackage.yourlibrary:yourlibrary:1.0'
Read more:
Gradle: How to publish a Android library to local repository
https://github.com/dcendents/android-maven-gradle-plugin
https://inthecheesefactory.com/blog/how-to-upload-library-to-jcenter-maven-central-as-dependency/en
From my Knowledge 1. As others said try creating your own Module or Library and use it where ever you need 2.Use Version Control Tools Like Git(If your code changes it will be refleted in your git account)

Gradle: classpath dependency not resolved from nested project

I have a multi-project build set-up with gradle that will contain multiple android apps and libraries.
Sample of the project structure:
root (Project Root)
| android
| module1 (Android Application)
| module2 (Android Library)
| ios (in the future)
I want to apply certain gradle plugins only to some subprojects. (Such as the android gradle plugin only to the android subproject)
Therefore I added the classpath dependency in the :android -> build.gradle and the plugin declaration to the two android subproject: :android:module1 -> build.gradle -> apply plugin: 'com.android.application'and:android:module2 -> build.gradle -> apply plugin: 'com.android.library'
The problem is that gradle cannot found the android gradle plugin:
Error:(1, 1) A problem occurred evaluating project ':Shoppr:presentation'.
Plugin with id 'com.android.application' not found.
Also it is not a version problem as in some other questions (Gradle Version 3.1; Android Gradle Plugin Version: 2.2.1) because when defining the classpath dependencies in :root -> build.gradle or :android:moduleX -> build.gradle all is working as expected.
:root -> build.gradle
allprojects {
repositories {
mavenCentral()
jcenter()
}
}
:android -> build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.1' <-- Should only be applied for android project
}
}
:android:module1 -> build.gradle
apply plugin: 'com.android.application' --> Plugin with id 'com.android.application' not found.
:android:module2 -> build.gradle
apply plugin: 'com.android.library'
I have seen such folder arrangements especially with google sample projects that include and android folder and also a web folder. What you can try is to import the project using the android folder as the project folder since you may not be using gradle to build Ios and web if you have the two more folders for you project.
So close the project and re-import it using the android folder as the project root, i believe this way, gradle should run fine. My project folder is also like this because i have both web and android project in a single repo but during build with android studio, i use the android folder as the project root for the android.
I had a somewhat similar problem. I went from having an android folder with 3 subtasks to dividing it into 3 folders with subtasks:
| android
| shared
-- generates aar
| device1
-- generates 2 apks
| device2
-- generates 1 apk
| gradle
gradlew.bat
gradlew
Both device1 and device2 want to use shared. So I removed settings.gradle and build.grade from the android folder. device1, device2, and shared have their own build.grade and settings.gradle. I build device1 and device2 separately. In order for them to include shared and build, I put symbolic links to shared, gradlew, gradlew.bat, and the gradle folder from the android folder into device1 and device2. And voila, it works! (I'm on an Ubuntu computer, but should be able to do the same on Windows and Mac.)
The disadvantage is that shared is built each time. In our case, that's not too bad, it's not very big.
android gradle [tag:multi-level projects]

Android Studio How to build an aar file with gradle that has remote dependencies

I created a Android Library Module with Android Studio and I was able to use it in the apps and right now I need to use it for my other apps. So I was thinking about using the remote dependecies like Picasso https://github.com/square/picasso
compile 'com.squareup.picasso:picasso:2.5.2'
And I would like to know what are the steps I need to take? I read few article and website. It is very confusing.
To make your library available as a remote dependency there are only three steps you have to take:
Build your library and provide the necessary repository meta data
Put your library with meta data in a repository
Tell your project to look in that repository for dependencies
After that is in place you can have remote dependencies like this in your app's build.gradle file:
compile 'com.example.developer:lib-util:1.0.0'
This will look in all the repositories that you have registered for a group or organization called 'com.example.developer', and then an artifact named 'lib-util' with version '1.0.0'.
Build your library and provide the necessary repository meta data
That may sound complex but it's really not that hard. It's just a directory structure that looks a little like this:
com
|-- example
|-- developer
|-- lib-util
|-- 1.0.0
| |-- lib-util-1.0.0.aar
| |-- lib-util-1.0.0.aar.md5
| |-- lib-util-1.0.0.pom
| |-- lib-util-1.0.0.pom.md5
|-- maven-metadata.xml
|-- maven-metadata.xml.md5
The file lib-util-1.0.0.aar is the compiled library (in Android Archive format). The lib-util-1.0.0.pom file contains information about the library itself, such as the authors and its dependencies. The maven-metadata.xml file contains the necessary information to know which versions are available (in this case just one). And lastly the *.md5 files contain a checksum to verify file integrities. (There are also *.sha1 checksum files that I've left out for brevity.)
To build this structure you can make use of the Maven Gradle plugin. Put it in your library's build.gradle and configure the mavenDeployer properties:
library build.gradle:
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
uploadArchives {
repositories.mavenDeployer {
pom.groupId = 'com.example.developer'
pom.artifactId = 'lib-util'
pom.version = android.defaultConfig.versionName
// Add other pom properties here if you want (developer details / licenses)
repository(url: "file:./releases/")
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
}
The above example is a stock library build.gradle as Android Studio 1.4 produces it for a new library but with the Maven Gradle plugin added and configured.
The second line: apply plugin: 'maven', adds the plugin. The uploadArchives closure configures it.
pom.groupId is the name of the organization/group. This will be written in the .pom file but is primarily used to actually find your library as a remote dependency.
pom.artifactId is the name of your library. Again, this will be put in the .pom file but is used to actually find your lib.
pom.version is the version of your library. You will have to increase this when you make a new release. Also put in the .pom and used to locate your lib.
The line repository(url: "file:./releases/") configures the plugin to write the structure to a filesystem directory relative to the project root.
If you run the following Gradle command in the root directory of your project you should see the Maven directory structure being built.
./gradlew clean uploadArchives
This will first clean your build and then build and perform the uploadArchives task which will create the releases directory.
Put your library with meta data in a repository
You already have a local Maven repository right now, namely on your local filesystem in your lib-util's project directory.
To make it an online remote Maven repository it only has to be reachable by http (or https) get-requests. If you have a server with a webserver like Apache or Nginx or IIS you can configure that to host the files. Or you can check them into your Github account and let that host it. You could even copy those files to Dropbox and use it to host them.
If you want to have it publicly available over Maven Central or JCenter you will have to go to their websites and register for an account where you claim your 'groupId' and you can then use their systems to upload the files so they will be hosted by them.
Tell your project to look in that repository for dependencies
By default Android Studio registers your project to look for dependencies in JCenter. Previously it used to default to Maven Central. So if you have actually uploaded your library to those repositories you wont have to do anything as it will already work.
Suppose you want to configure your project to look for remote dependencies on your local filesystem in /Users/rob/projects/lib-util/releases, and in a self-hosted Maven repository at http://developer.example.com/repo/. Add those repository urls to your project's build.gradle (so not in your library's):
project build.gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven { url '/Users/rob/projects/lib-util/releases/' }
maven { url 'http://developer.example.com/repo/' }
jcenter()
}
}
The example above is the stock project build.gradle as Android Studio provides it with just two extra repositories. Looking dependencies up goes in the order listed. So in this case it first checks the local filesystem, then the self-hosted repo and finally it looks in JCenter.

Gradle - inherit repositories from a module

First of all, I explain my project setups. I use the words Project/Module as used in Android Studio.
I have a setup of my projects like following:
LibraryProject => a project that just groups my libraries, that I use in other projects, if necessary
BackupLibrary (Module)
DatabseLibrary (Module)
MainUtilityLibrary (Module)
DialogLibrary (Module)
MyProject1
App (Project)
DialogLibrary (Module, referenced from DIRFFERENT project)
My Project1 now looks like following:
1) I reference the module from the other project, that I want to use (done in settings.gradle (Project Settings) file:
include ':app'
include ':dialogLibrary '
project(':dialogLibrary ').projectDir = new File(settingsDir, '../LibraryProject/DialogLibrary ')
2) I add the foreign library module as a dependency to my app's build.gradle:
dependencies {
compile project(':dialogLibrary ')
}
My LibraryProject looks like following:
I add the repository and the dependency directly to the module's `build.gradle' (this is enough to build the module on it's own without a problem):
allprojects {
repositories {
maven { url 'https://dl.bintray.com/drummer-aidan/maven' }
}
}
dependencies {
compile 'com.afollestad:material-dialogs:0.7.5.2'
}
Problem
The setup so far does not work for MyProject1. I have to add maven { url 'https://dl.bintray.com/drummer-aidan/maven' } to MyProject1 as well, the compile project(':dialogLibrary ') is not enough. I have to add the dependency that should somehow be inherited from the LibraryModule to MyProject1 Project build.gradleagain like following:
allprojects {
repositories {
mavenCentral()
maven { url 'https://dl.bintray.com/drummer-aidan/maven' } // com.afollestad:material-dialogs
}
}
Otherwise, i can't compile my project. This way seems like doing something twice that probably can be done automatically. But how? This way, whenever I include a module from my LibraryProject, I have to check if I need an additional maven repo...
I think it has to do with the fact that Gradle has no knowledge of the LibraryProject's settings.gradle file while building MyProject1. So it includes the dialogLibrary as if it is a normal subproject of it's own. This explains the reason why the Maven repo is not know to MyProject; LibraryProject's configuration has not been loaded.
Maybe you can include the dialogLibrary through the LibraryProject? Although I did some testing and could NOT get it to work. It probably has to do with a limitation of Gradle. There is a StackOverflow post about multiple settings.gradle files here.
A work around could be to build the Modules of the LibraryProject and use them instead. For example build the DialogLibrary to a jar, upload it to a Maven repository and than in your App project just include DialogLibrary as normal dependency (don't forget to include the Maven repo).

Categories

Resources