I built a library that does some network requests with Retrofit. Retrofit is included in the library as a JAR file.
I want to ship the library as .aar file.
The host app that will consume the .aar file will need to have Retrofit too since it needs to do some network requests.
What the host app should do?
Use the Retrofit library of the .aar file?
I've tried that and is
working, the problem is that doesn't sound like a maintainable solution
since the host app will be tied to the Retrofit version inside the
library.
Include another version of Retrofit?
I've tried that and I'm getting errors when I compile the host app since I have multiple versions of the Retrofit files. e.g:
More than one file was found with OS independent path 'okhttp3/internal/publicsuffix/NOTICE'
Is there any other solution?
I read that I can use the transitive option but if I do that the library will be dependent from the Retrofit version of the host app right?
Using the transitive option should be the best from my point of view.
The library is not dependent on the host app but the host app is dependent on the library. Your library will still use the version of Retrofit which you implemented inside the library.
By using the transitive option you are just making sure that the version of retrofit that is being used inside the Library is not being utilized by the host application.
How I can use com.android.setupwizardlib in my project?
This library isn't on jcenter or as gradle dependency.
This library is used in some apps (Such as Greenify) and it uses the XML tag com.android.setupwizardlib.SetupWizardLayout in my Activity
Any solutions about it?
I know how to import a library, I only need help with this specific google library
Greenify SetupWizardLib
It would be simpler for you to use existing packaged libraries for this functionality, such as some of these or a couple of these.
Otherwise, grab the source code and resources, add them to your project (directly or via a separate library module), and make changes as needed to get it to build.
An unreleased android library I am working on has a third party networking library in it - OkHttp in this case.
Projects that use this library as a dependency also are now able to create objects with that networking library.
Can I limit or disable access to the networking library contained within my library?
You could make the dependency transitive however if your code hits the missing code inside their app it will fail ClassNotFound or MethodNotFound
dependencies {
compile('com.squareup.okhttp3:okhttp:3.2.0') {
transitive = false
}
}
Short of that once the code is packaged with your lib it's available to anyone who wants to use it from your lib.
This still won't solve the problem as you would like but you could use proguard to rename the okhttp classes. Users of your lib could still call the okhttp classes but they would be renamed by proguard to something like a,b,c,...
What you want to do is shade the dependency. Here's a description from a blog post about shading dependencies in Gradle:
To Shade a library is to take the contents files of said library, put
them in your own jar, and change their package.This is different from
packaging which is simply shipping the libraries files in side your
own jar without relocating them to a different package. The term
fatjar is commonly used to refer to jars that have the application as
well as its dependencies packaged or shaded into them.
It's easy to do for smaller libraries. I could image it might be difficult for a large library like OkHttp. You can do it manually by simply copying the files into your project and changing the package. There are also some scripts that will do it automatically. They usually use Jar Jar Links.
Normally be default you don't have the dependencies like that:
compile rootProject.ext.okhttp
compiled in your jar only your sources are. So OkHttp classes will not be in your lib.
I have exactly the same case. I use gradle to build and upload to maven.
You can check here
So if your intention is to have the exact dept version in the package and to be hidden you just need to include it in you project as a module and to change some things like the package of OkHttp to avoid conflicts and also the access to currenly public okhttp members. OkHttp is using Okio so you may want to privatize it too.
Note that this kind of shadowing + hiding functionality of the shadowed class can be useful for framework dependencies(ensuring all depts in runtime available) but it is increasing the size of your libs and will not be the best option for apps using your lib as they anyway ensure packaging required depts in the apk.
I have an app and a library that I wrote. My issue is that when including the library as a jar (I see all of the classes included when decompiled),the app itself cannot interact with sub-classes from decencies of the library.
What is a good way to ensure that by including the library the app also pulls in the required dependencies?
What is a good way to ensure that by including the library the app also pulls in the required dependencies?
The best way is to publish the library in a maven repo (private or public).
In this way with gradle you will be able to download the library and all dependencies (described in the pom file).
Adding the jar (or an aar) in a project you have to add also the nested dependencies in the project since the jar and the aar don't contain the nested dependencies.
I have started working on a project where I will need to share a bunch of Java classes across a bunch of apps. In Eclipse it was possible to create one project with all such classes and use it as a library in a workspace with all your dependent projects, but in Android Studio it doesn't seem possible to do so (At least not easily).
I have been reading a bunch of posts and a lot of them suggest setting up a library project, generating an aar file and then using that in my projects. But, as I understand it, this will make my library open-source (Am I right?), which I don't want. I am doing this for a client and I want the code base to be private.
Also, I know that a module can be imported into a new project. But this creates a COPY of the original module. This is not what I want at all. I don't wanna maintain multiple copies of the same classes, which completely defeats the purpose of 'code sharing'.
Is there any good way of achieving what I am looking for? Any help is appreciated.
You have a couple different options.
One option is to maintain your libraries as separate projects and compile them to an archive format, such as JAR or AAR; JAR files are for pure Java libraries, and AAR is for Android libraries (which contain code that accesses Android APIs and/or has Android resources). As was pointed out in the comments, AAR doesn't force you to publish your code to the world any more than JAR files would; it's just an archive file format whose files can be local to your machine or your organization.
With that archive file in hand, you can include it in other projects. If you're part of a multi-developer organization, you may find it convenient to use a repository manager to publish and maintain those libraries within your organization, and you can use Maven coordinate-style specs to include libraries in your projects, which you don't have to manually copy over to your development machine.
The disadvantage of this approach is that it makes it a little harder to make changes to those libraries: you need to load up the project, make changes, build an archive, and distribute the archive.
The other approach is to keep the library as a source module like you did in Eclipse. You observed that Android Studio will make a copy of the module if you import it via UI, but if you bypass the UI and modify the build scripts directly, you can do what you want, which is to use the module in-place and share a single copy among multiple projects. To do this, work in your settings.gradle file and add this:
include ':module_name'
project(':module_name').projectDir = new File(settingsDir, '../relative/path/to/module')
I would strongly encourage you to not use a pure relative path here; in this example, the path is anchored to the settingsDir variable supplied by Gradle, which is defined to be the directory where settings.gradle is found. If you use a pure relative path (i.e isn't anchored to anything), you're dependent on the working directory being the same in all environments where the build file is run (command line vs. Android Studio vs. CI server), which isn't a good thing to assume.
You need to think in the eclipse projects as Android Studio/IntelliJ Idea modules. Then, you can generate android (or java) libraries and then include them in your project.
To mark an Android Studio module as a library you can go to File -> Project Structure -> Facets and there click on Library Module
I was in same situation as you, and i founded an approach using git.
Steps to do, to have library:
Create project in Android Studio.
Create android library module in that project.
In that library module create git repository.
Add modulename.iml in .gitignore file
Use GitHub or Bitbucket for private cloud repository. and push your library to it.
Create new android library model in any project that you want.
Close Android Studio (not sure is that mandatory).
Using explorer go to your created module folder.
Remove all data in it, except modulename.iml.
Clone your library from "GitHub" into it.
That's all.
Now you are able to use library in multiple project whether you are at home or at work. Just after finishing you work not forget to push library changes. And after opening new one pull them.
I think you can automate this thing somehow.
The benefit is that you don't need to build any jar, or aar.
You can certainly create and use a library without making it open source or available to others.
First, you don't need to make it an aar unless it contains Resources.
If it's just plain classes, you can just make it a .jar file.
Either way, the easiest way to share these libraries (either aar or jar) is to set up your own repository. Nexus and Artifactory are the two most common repository managers.
You keep the library in its own project, and then publish it to your own, in-house repository.
Then, projects that need to use the library are configured (in gradle) to use the in-house repository, and get the library from it.