Managing Android shared resources in repository - android

I have multiple Android projects that I need to manage in various Git repositories, all of which are being managed by repo. I have found a .gitignore file for Android managed by Git, but I don't see things like image files being ignored:
https://github.com/github/gitignore/blob/master/Android.gitignore
I have also read that creating an Android library which contains my resources would allow for a module that is not an .apk, rather a resource for apps to use.
https://developer.android.com/studio/projects/android-library.html
Is there a best practice for storing shared resources?

Creating an Android library project is trivial; distributing it to your other downstream apps is really the interesting part.
Ideally, it would be nice to do this in a way that mimcs how you use other dependencies on Android, namely adding an artifact to the dependencies block in your build.gradle file and having Gradle automatically fetch it. The trouble there is it's a private library that you wouldn't want to host on JCenter, Maven Central, or other public artifact hosting. Some companies have their own internal instances of artifact hosting servers specifically for this.
Fortunately, you can use the maven-publish Gradle plugin to use Maven locally (on your machine) and achieve the same effect. First, in the library project's build.gradle file, you need
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
groupId 'your.package.namespace'
artifactId 'library.name'
version '0.1' // for example
artifacts = configurations.archives.artifacts
artifact sourceJar
}
}
}
Next, you need to publish this library to your local Maven cache by running
./gradlew publishToMavenLocal
Next in your downstream project, add mavenLocal as a repository and add your dependency using the group id, artifact id, and version you used earlier:
repositories {
mavenLocal()
/* more repositories here */
}
dependencies {
compile 'your.package.namespace:library.name:version'
/* more dependencies here */
}
This should achieve what you want.
The downside is every developer will have to pull down the library project at least once and run the command to publish to their Maven local, and if the library project changes at all, the version must be updated, and all devs need to pull down the changes and publish again locally. This can get a little unwieldy.
Many companies run their own artifact hosting server instances internally to avoid this, so you publish once to the internal hosting and downstream projects just update the version in their build.gradle and let it sync automatically. This requires some additional configuration for the publishing block (of the library) and the repositories block (of the downstream projects); I leave it to you to research that if you intend to go that direction.

Related

publishing a library - how to make it so that consuming app doesn't need to add repositories for transient dependencies

I've created an Android library called Library and I want to publish it to a private maven repository and then consume it in an app called App.
I am encountering an issue however which is making the usage of the library untenable for App. The issue is that one of the dependencies of Library is hosted in a "non standard" maven repository, and is forcing the consuming App to add this repository to it's repositories block.
To explain this further; Library has lots of dependencies, most of which are pulled from google and mavenCentral repositories (both of which the consuming App has in the repositories block because all Android apps will include these repositories). However, one of the dependencies, Quikkly, is hosted in a "non standard" maven repository (i.e. one with a non standard URL), which also requires a github personal access token to access. So in my Library repositories block, I have to add this maven repo in order to pull this specific dependency:
maven {
url 'https://maven.pkg.github.com/quikkly/quikkly-android-sdk'
credentials {
username = <github_username>
password = <github_access_token>
}
}
All well and good; I can build Library just fine, and the Quikkly dependency is pulled successfully from this repository.
The issue arises when I use Library in App. I published Library to mavenLocal (or my own private maven repository depending on when I'm ready to actually push a release). When I pull Library into App and then build, the build fails because Quikkly could not be resolved.
The errors show that the locations searched were just the repositories defined in App and not those defined in Library. I can make the build succeed if I add the Quikkly custom maven repo (and github access token) to App but I don't want to force App developers to need to add custom repos just to use my library - surely my library should be responsible for properly packaging it's own dependencies such that consumers just need to use my library via a one line gradle import.
I've done some research on this, and I think the solution involves adding the custom maven repository URL to a <server> element in my libraries .pom file, however the repository also requires a github username and personal access token in order to pull the library from it... my research shows that I need to add these details to "somewhere" (but not in the .pom file as this would be insecure and/or wouldn't even work).
I'm now getting pressured to release something working, but I'm pretty stuck with this. Can anyone help?

How to publish android library to subversion and use it on projects

There are many posts about publishing android library in github. Is there any way to publish android library to the svn?
EDIT:
I have created a libray and build the aar file. I have imported the aar file in to a tag of the svn. (Ex: svnpath/project/tags/library0.0.1.aar)
I want to use this library in a separate project. I want to use this library as
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
like this. how can i achieve this?
As discussed in the comments, Subversion (SVN) is not an appropriate tool for what you are trying to achieve. Subversion is a version control system which manages the versioning of source code files and associated resources, much in the same manner as Git does.
What you are looking for is a dependency management system using Maven, for example Artifactory. This will allow you to publish your .aar files to either a public-facing or private repository and import those dependencies into your build.gradle file. Unfortunately the process for setting up such a service is too broad for the scope of this question, but once you have it up and running you can add it to your build.gradle file under the repositories section:
repositories {
maven {
url "<url of Maven server>"
credentials {
// If you choose to use authentication
username = <your artifactory username>
password = <your artifactory password>
}
}
}

How to use a Gradle dependency with local modifications?

I have an Android application using an Android library. The library is a pretty big open-source project on GitHub, and its authors publish the artifacts to Bintray. I can specify the dependency with the usual syntax dependencies { implementation 'group:artifact:version' } in the app's build.gradle.
Now I want to change some code in the library. I git clone it on my machine, I make my changes, then I build the library. But how can I tell my app to use the library I built locally, instead of the one in Bintray?
I don't want to follow the approach in Gradle Local Project Dependency, because that means that the library code is now part of the application project, but I really want to keep things separated.
I think the solution involves publishing to a local Maven repository. I followed the guide at https://proandroiddev.com/tip-work-with-third-party-projects-locally-with-gradle-961d6c9efb02 but the app's Gradle is still picking the original library from Bintray.
Bintray-based projects have the install task. That's the one to be used instead of publishToMavenLocal.
When using install, the artifact version is automatically set to X.X.X before publishing to the local repository. Therefore, in order for the app to pick up the local library, you have to edit the implementation row to group:artifact:X.X.X.
As the guide https://proandroiddev.com/tip-work-with-third-party-projects-locally-with-gradle-961d6c9efb02 suggests, you also need to add mavenLocal() as the first entry in the repositories section in the top-level build.gradle of the application.

what is the purpose of the init.gradle file

Can someone explain the meaning of the purpose of this init.gradle file as it seems like just duplicating code to me:
buildscript {
repositories {
maven {
url "https://someEnterpriseURL"
}
}
}
allprojects {
repositories {
maven {
url "https://someEnterpriseURL"
}
}
}
the reason for the confusion is that in the projects build.gradle file its defined like this:
buildscript {
repositories {
maven {
url "https://someEnterpriseURL"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.1'
}
}
allprojects {
repositories {
maven {
url "https://someEnterpriseURL"
}
}
}
so why even have this defined in the init.gradle file ? how does it help developers to have a init.gradle file when im defining the same thing in the build.gradle file?
Your build.gradle files are per-project and per-module. Your init.gradle files are set up on a per-${GRADLE_USER_HOME} basis (default is in ~/.gradle or in Gradle's home directory for local Gradle installations). I would expect to see init.gradle files used more commonly in large organizations, trying to standardize some Gradle build policies across multiple projects and development teams.
Quoting the Gradle documentation:
Here are several possible uses:
Set up enterprise-wide configuration, such as where to find custom plugins.
Set up properties based on the current environment, such as a developer's machine vs. a continuous integration server.
Supply personal information about the user that is required by the build, such as repository or database authentication credentials.
Define machine specific details, such as where JDKs are installed.
Register build listeners. External tools that wish to listen to Gradle events might find this useful.
Register build loggers. You might wish to customize how Gradle logs the events that it generates.
As you know gradle is combination of Ant tool and Maven tool. You might have seen how ant tool works(adding jars or libs locally) and maven tool(adding jars and libs file from cloud and writing script to download it from cloud during building). So basically this init.gradle file is generally used for some jars available globally(generally used for big organisations placed in cloud) which will contain the url or address of server so as to download the jar and cache it in gradle wrapper(you can see those jar files over cloud once downloaded can be seen in .gradle->caches).
Visualize in a prospect like suppose in an organisation which is have one support jar file which keeps updating every now and then and there is another team in that organisation which needs that jar for their application. So here our guy 'init.gradle' help us to solve this problem. Automatically download the latest jar from the server whenever application is build by the later team.

Studio failed to download library from gradle repository

I already saw this question, but it is not helping me. First of all, I tried to add google play services in my project using:
dependencies{
compile 'com.google.android.gms:play-services:6.5.87'
}
It was showing me error:
Then I updated my studio to 1.0.1 and gradle to 1.0.0. And then I again synced the project with gradle. And it worked! It showed me another option despite of two options shown in above screenshot. It was "Install the library"(something like that). I clicked it and it popped up a dialog, and I installed the library(it was like downloadind using SDK manager and not like gradle downloads).
Now, I tried to download this library using:
compile('com.fortysevendeg.swipelistview:swipelistview:1.0-SNAPSHOT#aar') {
transitive = true
}
And it gives me error:
My android repository is updated:
Also, my internet connection is working fine. I tried to sync project many times, but same error all the time. I am not running gradle in offline mode:
How to fix this? And what is the permanent solution? And why is all this happening?
I found this question: Studio failed to download library from gradle repository which describes the exact same error, and that question had this bit of build script that you need to add to the build file that has the dependency statement in question:
repositories {
maven { url 'http://clinker.47deg.com/nexus/content/groups/public' }
}
When I do this, it works for me.
As to the general question of why this happens (and the better question of why the solution is different for different libraries):
Gradle, the build system that Android Studio uses, has the ability to automatically download library dependencies from the Internet. By and large this is a big boon for developers, because instead of having to manually download archive files, put them in the right place in your project, check them into source control, and repeat the process for new versions, now you just have to add a line of build script and the build system takes care of the housekeeping for you. The major downsides are Internet connectivity woes, which affect different developers to different degrees, and some added confusion about what it means when you get an error.
How does Gradle know where to download dependencies? Most Gradle build scripts contain a block that looks like this:
repositories {
jcenter()
}
or it may be mavenCentral() instead of jcenter(). This tells the build system to look in the JCenter or Maven Central global repositories (and JCenter is in a simplistic way of thinking about it a value-added mirror of MavenCentral); these contain archives of many versions of many, many, many libraries and are very convenient to use.
You can specify other repositories as well. This swipelistview library hasn't been uploaded to Maven Central, so the developer has made a repository for it available via a URL: if you add that URL to your repositories block, it will look for it there.
I was worried about the fact that you're accessing a SNAPSHOT version of the library -- these are supposed to be unpublished by definition. But adding a dependency on the snapshot version of the library in my test project worked for me, and looking around that URL in a web browser reveals that there's only a "1.0-" (trailing dash included) version of the library, so there's some subtletly there I'm missing; if you know more, please edit my answer or comment.
In any event, there are a couple caveats to this explanation. Some libraries aren't on Maven Central or on any Internet-accessible archive (at least they're not officially published by Android), but are instead published as part of the Android SDK download and maintained via the SDK manager. The Android support libraries and Google libraries fall under this category. If you get errors about those not being found, you have to fix it via the SDK manager.
How does the build system know to look in the SDK for those, since you didn't tell it via the repositories block? This behavior is hardcoded into the Android Gradle plugin.
The other caveat is that there's a detail that trips up a lot of people, which is that you actually have two repositories blocks, though with the usual Android Studio setup they're often in different files. One is in a buildscript block, which usually lives in the top-level build.gradle file and looks like this:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
The other often also lives in the top-level build.gradle, but you can augment it with another block in your module's build.gradle file. The top-level one looks like this:
allprojects {
repositories {
jcenter()
}
}
and a module-level one would look like one of the previous examples in this answer. What do all of these mean?
The buildscript block tells Gradle where to find build system plugins. These are plugins that enhance the functionality of the build system itself but don't say anything about your actual project. In Android projects, the Android Gradle plugin is in this category, and unlike the Android/Google libraries, this one does live on Maven Central. The repositories block (in coordination with the dependencies block, which is not the same as the dependencies block for your project, keep reading) in buildscript tells the build system where to go look for these plugins.
The allprojects block in the top-level build file tells the build system to apply the bit of contained script to all build files in the project. In this example, it's telling it to add a repositories block pointing to JCenter to all subprojects. This is a convenience so you don't have to copy/paste it into multiple build files in your modules.
In your modules, you also have a repositories block, which in conjunction with the allprojects thingy, tells the build system where to go to get library dependencies for your project, as was previously discussed.

Categories

Resources