I am trying the following:
Include an Android Module in my project.
Excluding it from actual build (if you e.g. press rebuild project).
Background: The Android module compilation takes 20 sec I don't want to wait, because I am only doing desktop tests at the moment. But I can't remove the Android Module completely from the project, would loose refactoring features (would not run later after e.g. I renamed classes in library project).
Any ideas how I can tell him to e.g. not DEX the Android (overwrite the build in Android ANT script with empty one is one way which comes to mind). Any tips are welcome...
Chris
Related
I have a big Android Studio project that has a separate module which contains native code.
The native build is defined with CMake and includes a bunch of source files of C++ code.
I noticed that since a very recent update (might be Android Studio 3.5), NDK rebuilds everything ALL THE TIME.
It can happen with a small change in Java code, switching flavor in an unrelated module in the project, incrementing version code, etc.
This is a major problem, since it can waste 10 minutes at a time for no reason.
I could not find a reasonable way to profile NDK builds in Android Studio and check what's causing the rebuild or what's taking so long.
Unfortunately the project's build files are too big to attach here. Any pointers for things to look after?
For the C/C++ code that you build with cmake, make sure you point cmake to a directory where it can keep its object files and binary outputs.
Let's say you have a dependency on Game in your top level CMakeLists.txt like so:
# dependency: Game
set ( game_src_DIR ../Game )
add_subdirectory( ${game_src_DIR} ${CMAKE_CURRENT_BINARY_DIR}/game )
Then the second parameter to add_subdirectory specified the place where AndroidStudio will keep the object files.
The debug and release object files will live in different subdirs, as will each dependency, so switching debug/release will not clash.
This appears to have been a regression in behavior from Android Studio 3.4 and has been fixed in Android Studio 4.1 Canary 4. Release notes are here.
Often, it helps to split the AS project such that the C++ part, possibly with its Java wrappers become a separate (library) module. This module will hopefully be more stable, not sensitive to increments of app version code.
Such module should not define many flavors, but have careful matching to the flavors of other modules. Sometimes, it makes sense even to disable "debug" variants for such library. There was an effort of the NDK team to better handle debug vs. release build switching, but this is still tricky.
But if after these improvements, insignificant changes to the project still cause massive rebuild, I would suggest to consider ccache.
I do have a project with an app and a library module that contains JNI code. I added a test class to the 'androidTest' folder in order to test all this in a device environment.
At the time doing, Android Studio 2.2.2 was able to identify the code as test (adding all the nice icons to run the whole class test and so on).
Now (a large number of commits and git rebasing later) I want to do some more work, but Android Studio refuses to accept the code as test code, although gradle itself (invoked with :libname:connectedAndroidTest) does perform the tests and writes timing info into some XML in the ./build/outputs/androidTest-results/connected of the library module folder.
The AS editor marks all unit testing related imports in red. When I try to resolve the "problem" AS suggests to "Add library 'runner-0.5' to classpath" although build.gradle already contains that reference.
AFAIR I was also able to select the library module in the "Module" setting in the General tab of the Android Test run configuration. But that doesn't work anymore.
What puzzles me is, that I some had this all working from within the IDE and now it doesn't work anymore. Although the gradle call will still run the test cases that the compiler doesn't complain about anything...
Any ideas anybody?
PS:
I do know that I can move the "androidTest" code into a differen module. However I do already have 10+ modules in my project. And since gradle is able to run the test, why is Android Studio not anymore?
I have an Android studio project that is made of several sub-projects, which are all android apps. It is setup like this:
Project
|---- Main app
|---- Other app 1
|---- Other app 2
|---- Other app 3
|---- etc.
The point is that all the "other app" sub-projects need to be included in the Main app final APK (they are plugins that the Main App can install on-demand when/if the user requests them).
So what I need is to setup the project so that:
Every time "Other app X" is built its APK is copied to Main App's
/assets/ directory
Every time "Main App" is built, it triggers a
build of all the "Other apps" that need building
Now, I'm used to Visual Studio, and there I can just set up project dependencies so that building one project triggers a build of the other projects, and I can set a post-build command that copies the generated binary to another folder quite easily.
With Android Studio and Gradle however I'm getting extremely confused.
First of all: even if I setup the project so that Main App depends on all the Other Apps this doesn't build the Other Apps' APKs, it only compiles their sourcecode (which is useless in my case, I need the final APK of the Other Apps).
Secondly, assuming I've been able to generate such APKs, I can't find a place where to setup a post-apk-generation command to copy those apks to another directory. I've been reading about gradle tasks and the "dependsOn" feature, however from what I understand the task that generates the actual APK ("assemble") is the last one in the build chain, so using dependsOn is no use to me, I would need something like "whenFinishedRun(myTaskThatCopiesTheAPKs)"
Any easy way to do this? Maybe it's because I'm a Gradle noobie, but this build system seems extremely convoluted to me, I'm actually thinking of writing an external program to run mamually to accomplish these tasks...
Rather than operating on the APK, gradle dependencies let you config an AAR dependency that can help with your issue.
Example dependency on aar here - see "amlcurran"
(ADK 21, NDK r8d, Eclipse Juno)
[I've built several Android apps so decent experience using ADK/NDK etc]
Eclipse project setup:
- AppProject (android, java, no jni)
- LibProject (android, java, Yes jni)
Previously, all of it was in one project - builds fine, runs fine, and native debugging worked great.
Then I split off the "reusable" portion to make a library of common code to use with multiple "AppProject" application front ends. (Everything still builds, links, packs, and runs okay)
However, when I run "AppProject", I can no longer debug the native library.
What is the solution?
Possible option #1:
- Modify "LibProject" Android.mk to export a PreBuilt that is used by AppProject?
- (I would have all the debug symbols so I'm thinking that would work okay)
Would I need to cnature the AppProject as well? In other words, so it has an Android.mk to import the output .so from LibProject
Possible option #2
- http://stackoverflow.com/a/14344377/735533
- that workaround uses ndk-gdb
- I'm hoping for a solution where I can debug LibProject in Eclipse directly when running AppProject
Is there a better way to debug the native code located in the dependent project "LibProject" when running the main application "AppProject"?
Tia
For those curious ...
I tried prebuilts ...
And it definitely seems the be the way to go (test project setup worked)
But the structure of my codebase is a bit heavy on the native/non-native crosstalk and didn't want to take the time (yet) to do a proper reorganization at the moment.
However, restructuring as a prebuilt is on my "Important ToDo" list now
Anywhere, here is my solution.
On Linux (unix flavors) ... use links - the sources are linked into each AppProject from LibProject.
Basically the "LibProject" becomes a sort of "template" during development - it is not built or used as a library directly. Rather, each AppProject becomes self-sufficient, standalone, application with the contents of the library project embedded in its own code tree. Best part is native debugging works like a charm again.
Although it sort of defeats the point of making, there are benefits - one common codebase for the "library" portion ... which is really what I desire for the time being.
Also, conversion to use as a true Library dependency by the Application projects for, say, eventual release builds is an easy switch. Once debugged and ready, the Library can be built separately, packed normally with the application "front ends", and upgraded independently of the applications.
I have a rather large Android project, and it takes considerable amounts of time for the sdk to do the resource-parsing / dexing / etc. I'd like to improve this somehow.
I've read that Android library projects can contain resources now too. So we can also put Activities, Fragments, etc. in them.
Does this mean, that if I export parts of my large project into library projects which I reference from the main project, then I don't have to rebuild the already built (and not modified) libraries again, when I rebuild the main project? So I only have to do the resource-parsing / dexing / etc. for the modified libraries and possibly the main project, decreasing the overall build time in most cases.
Does this mean, that if I export parts of my large project into library projects which I reference from the main project, then I don't have to rebuild the already built (and not modified) libraries again, when I rebuild the main project?
Partially no, Android Library Project is not built directly, it is always built along with the dependent Main Project, when SDK compile/build the Main Project, SDK tools compile the Library Project into a temporary JAR file and uses it in the main project. whenever you re-build your Main Project, the referenced Library Project is re-built as a part of main project build life cycle, even though nothing changed in Library Project. Check out timestamp of the temporary JAR generated under your app-lib/bin folder for evidence, it always get changed every time yo build Main Project.
Quoting from official dev guide:
However, a library project differs from an standard Android application project in that you cannot compile it directly to its own .apk and run it on an Android device. Similarly, you cannot export the library project to a self-contained JAR file, as you would do for a true library. Instead, you must compile the library indirectly, by referencing the library in the dependent application and building that application.
When you build an application that depends on a library project, the SDK tools compile the library into a temporary JAR file and uses it in the main project, then uses the result to generate the .apk. In cases where a resource ID is defined in both the application and the library, the tools ensure that the resource declared in the application gets priority and that the resource in the library project is not compiled into the application .apk. This gives your application the flexibility to either use or redefine any resource behaviors or values that are defined in any library.
Android Library Project is different from regular java library project. where you can compile and build everything into and jar library once, and start import/use the class from reference jar dependencies in main project. Currently Android Library Project is designed on source-based mechanism, not compiled-code based library mechanism, as mentioned in this Android blog, although self-contained jar distribution is promised in future release (unfortunately not in neither r15, r16, r17 nor r18 yet).
Yes... The build system rebuilds what needs to be built unless you build Clean.
I wouldn't expect huge time savings here.
In my experience, the slowest step of compilation is actually the dexing of the output files, which can not be performed incrementally, so moving your code into libraries will not speed things up. Similarly, incremental compilation (when it works — it often doesn't with the Android toolchain) will work equally well with unchanged files spread over a bunch of projects as will unchanged files in a single project.
Of course, the best way to find the answer for your actual use case is to experiment on your actual code base. And there may also be code maintainability benefits to splitting your project up into independent modules.