I'm pretty new to Android development, but I have some experience with Java and Eclipse. I'm looking for ways to create re-usable libraries (controls, helpers, "standard" activities, etc.) that I could use in my own projects, but that could also be distributed to other developers without disclosing the source code.
Normally, I'd package the class files into a JAR file and any other developer could add it to the classpath and use the packaged classes.
How can I do that with Android projects? I've read about Android Library Projects, but as the documentation states they can not be packaged into a JAR, but will be compiled along with the project that references the library project. This means I also have to distribute the source code.
I've also read this post, which asks about the same question but didn't provide a satisfying answer.
So: Is there a way of compiling and packaging a set of classes and other files (including XML layouts, resources and stuff) and distribute only that package without any source codes so that it can be "referenced" and used like a JAR file by any other developer?
I've read about Android Library Projects, but as the documentation states they can not be
packaged into a JAR, but will be compiled along with the project that references the library
project. This means I also have to distribute the source code.
Not true. It does require a bit of extra packaging work, but you can compile your code to a JAR and distribute the JAR in the library project's libs/ directory.
So: Is there a way of compiling and packaging a set of classes and other files (including
XML layouts, resources and stuff) and distribute only that package without any source
codes so that it can be "referenced" and used like a JAR file by any other developer?
Use an Android library project. I have some stuff written up here that describes a bit more of the packaging options, plus pointers to some "parcels" that follow the conventions described therein.
Thanx for your solution. From what I understand, you still can not access the resources private to the library from within the libary code. So assume your library has a string resource named "my_lib_resource" under res/values in the library. You bundle this in the jar along with the source code. Can you access this resource from the library source code using something like:
int id = res.getIdentifier("com.example.mylib:string/my_lib_resource",null,null)
assuming your library package name is com.example.mylib.
For me this does not work.
Brave new world of dependency management:
http://tools.android.com/recent/dealingwithdependenciesinandroidprojects
Related
I have read some sample codes, I find that many project use library module structure, you can see Image A.
Could you tell me the benefit to use library module in Android Studio ?
What code do I need to place it in library ?
And More, both app and lib module use the same namesapce in the sample code, I don't know if it's suitable, could you tell me ?
Image A
Library module gives you two options to create library Android and Java.
Android library module-> Android library compiles into an Android Archive (AAR) file that you can use as a dependency for an Android app module . It allows you to add android specific components like resources and manifest file, which allows you to bundle in shared resources like layouts and drawables in addition to Java classes and methods.
Java Library -> It builds a JAR file. JAR file is useful for many projects especially when you want to share code with other platforms. But it does not allow you to include Android resources or manifest files, which is very useful for code reuse in Android projects. So when you do not need any android specific resources in library you should create a java library.
Library modules are beneficial for projects :-
When you're building multiple apps that use some of the same components, such as activities, services, or UI layouts.
When you're building an app that exists in multiple APK variations, such as a free and paid version and you need the same core components in both.
Quoted from developer.android.com
Other than that same namespace is not problematic unless you have same package name inside App and libraries . You should use a different namespace for libraries.
PS-> If you are familiar with Clean Architecture, The idea behind most of the software design pattern is Separation of concern . In Clean architecture a project is divided into multiple modules. When you implement clean architecture in android you'll see that some of the module you can create as Java library like domain module. Creating module is really useful to follow re-usability and SOLID principles and Inversion of control.
Firstly, don't look into the package name declared in the java directory. Look into the manifest file. You can see that these modules have different package name. It means that all modules in a project must have different package name.
Regarding to your question, what are the benefit of naming library module as lib?
There's no benefit at all. Some people are comfort with lib name, so they can differentiate the demo and library module easily. However, using lib as library's module name requires you to add additional configuration in the lib/build.gradle, i.e. archiveBaseName. This Gradle attribute will rename the JAR/AAR from lib.aar to work-runtime.aar, so people can use it like this:
implementation "androidx.work:work-runtime:$work_version"
If archiveBaseName is not set, people will use it like this:
implementation "androidx.work:lib:$work_version"
In real case, let's take my open source library as the example, MaterialPreference. I used to use lib name on this project, but now I think lib is not a good module name. Using materialpreference as module name will remove additional configuration archiveBaseName. So I feel it is more simple.
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.
I want to create an Android jar library which has activities which use layouts that are all within the jar file.
I have been researching and trying different methods for the last few days and exhausted the related posts here. I have managed to get drawables and other raw assets to reside and be loaded from within the jar. However I have not been able to include valid resources which include the layouts. The official view is that it is not supported yet however I am sure it can be done.
I see that this is possible with .aar libraries when using Gradle but I am unsure if .aar libraries are compatible with older Android projects.
Could anyone shed some upto date info on this issue of resources/layouts in jar libraries and also the compatibility of .aar libraries.
Many thanks
I want to create an Android jar library which has activities which use layouts that are all within the jar file.
That is not possible, sorry. However, you are welcome to create an Android library project that serves this role, and that library project can ship a JAR instead of Java source code (see the Play Services SDK's library project for an example). The layouts would not be inside of the JAR file, though.
The official view is that it is not supported yet however I am sure it can be done.
I am sure that you are incorrect in your assessment.
I see that this is possible with .aar libraries when using Gradle but I am unsure if .aar libraries are compatible with older Android projects.
Project age has nothing really to do with it. If you are using Gradle, AAR files work. If you are not using Gradle, AAR files do not work.
Google's instructions for using the Play Service API (for example) say:
Copy the /extras/google/google_play_services/libproject/google-play-services_lib library project into the source tree where you maintain your Android app projects.
Note: You should be referencing a copy of the library that you copied to your source tree—you should not reference the library from the Android SDK directory.
This seems ugly to me - why not reference it from the SDK directory? Is there some technical reason for this? Or is it so that you have explicit control over when it gets upgraded?
I'd like to point out that this is entirely a limitation of Eclipse, and it is indeed ugly.
The problem is that this library contains resources in addition to source code. Eclipse can only deal with libraries packaged as jar files, which, for the purposes of Android development, cannot contain resources.
So, in order for the library's resource to be compiled into the application, the library's source code, with the resources, must be added to your project.
If you move your build to Maven, and use an IDE that 'understands' Maven, then you can compile a library that contains resources as an 'apklib', and treat it as an external library, in a manner similar to a jar file.
The new Gradle-based build system is built on Maven primitives, but uses a different format for this, 'aar'. Hopefully, it will eventually also support apklib so that Maven builds and Gradle builds can inter-operate.
I just went through the exercise of converting an Android application to a Maven build, including the use of some apklibs. I can tell you that Eclipse with the m2eclipse plugin does not handle apklibs properly. Both IntelliJ and the new Google Android Studio (based on IntelliJ) do handle apklibs with no issues.
It's not about "Play Services Library" specifically. Just like any other libraries that the project makes use of, this library should be referenced from project's source tree.
In this case the external library is in the Android SDK directory and referencing from there is not a good practice too. So yes, it can be called "a technical reason".
Used libraries (Play Services library in this case) shouldn't be referenced from anywhere other than the project's source tree.
I am currently working on a Android Project where we are expected to merge our App with 2 more apps from vendors who wouldn't be sharing their code.So just wanted to know Is there any way we could just include there Source code as JAR Files in our project and then include their resources and point to them(I did do it using getResources().getIdentifier("splash", "layout", getPackageName()) But Its still not working ?? I think I have tried all possible methods so hoping you guys could help me with this.
To quote CommonsWare from this question:
Bear in mind that your packaged classes cannot reference resources (at
least not via R. syntax), and that JARs cannot package resources,
manifest entries, etc. If all you are trying to JAR up is pure Java
code (perhaps using Android APIs), then you should be fine.
Basically, you can only use JARs that contain pure java as libraries in your app, not entire other projects.
The Activities can be compiled into a jar and added to the main Android project and we need to add their project's resources into your Project. The only we could make it work is using the getResources().getIdentifier("splash", "layout", getPackageName()). Even the Widgets like TextView, Button and all those should be referred to using the getResources() method. Like, for example, If you want to perform a action on particular button then we need to identify them by getResources().getIdentifier("Button" /*id in the XML File*/, "id"/*type*/, getPackageName()).
One more thing: you need to specify all the Activities in your Main Android Project's AndroidManifest.xml file with their package name. I hope this solves something.
In order to support faster build times, the r16 tools are creating their own jar files inside of Android Library Projects. You can use this feature to solve this issue. If a vendor would like to release their Android Library Project but without source code, they can make a copy of that Android Library Project that contains everything except for the source code tree. Next, include the jar file from the original Android Library Porject (the one that the r16 tools built.) This will allow you to have a component you can distribute that does not require source code. The consumer of this new Android Library Project will need to manually add any necessary meta data to their own project's AndroidManifest.xml file as needed (Activities, Providers, Permissions, etc).