I have a Java Library project in my AOSP build which creates a jar file and hosts it in system/framework
Everything works as expected, however I now wish to create a JAR file from the same library to allow and application to link and compile against it. Goal is to be able to create APKs against this lib (compileOnly) so that the APK can run and use the library on the ROM.
The problem is that Jack seems to be generating only dexed jar files which cannot be used in Android Studio as libraries.
Is there a way to disable DEXing in the Android.mk ?
I know there is an option in Android.bp (cannot recall it) which gives the option for the build to generate normal jar (with .class files).
Note: I cannot use BUILD_DROIDDOC with stubs due to enviroment issues (custom ROM) assuming BUILD_DROIDDOC is only executed with lunch sdk-eng
This is for a custom ROM with Android 8.1 base. I think the custom option of not dexing in Android.dp file is not supported in this version anyway.
Related
For a project, I am using Android gradle scripts with CMake, gradle plugin is version 3:0:0, CMake version 3.6. Both gradle and CMake files are pretty simple and uninteresting (just defining the files used - I can still copy-paste them as required).
I have the following project structure; basically a codebase producing a few tens of .so files (the native part for the Android packages that get packaged into an apk, thereby called 'Executables'), which all depend on the same shared library code (static libraries, thereby called 'Libraries'). The Library code is still (relatively) volatile, so I wish the Executables to have project-level dependencies on them, so that whenever the Executables are built, the Libraries are rebuilt on-demand every time their code is changed.
The structure looks like:
+ LibProjects/
---Bin/ (Originally empty)
---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt)
...
---Lib10/CMakeLists.txt (same)
+ Executables/
---Executable1/CMakeLists.txt (source files here)
--------------/AndroidFiles/build.gradle (and other android project files)(points to the CMakeLists.txt)
...
---Executable40/CMakeLists.txt
The Libraries' CMakeLists redirect their output into the Bin folder using
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/../Bin/${ANDROID_ABI}/${LibraryName})
The executable's projects add dependencies on the libraries "as normal"
add_subdirectory(${PROJECTS_ROOT}/LibProjects/${LibraryName} ${PROJECTS_ROOT}/Framework/Bin/Android/${ANDROID_ABI}/${LibraryName})...
Everything almost works, in the sense that I can get sensible executables and the Executables trigger builds of the libraries.
The problem is that when building the executables sequentially, each one does NOT reuse the library project outputs of the other ones: When I build Executable1, it will build all libraries (normal) and then it will build itself. Afterwards, when I build Executable2, it will NOT reuse the libraries that were already built for Executable1, and so on - this effectively increases my build time by a factor of ~10.
I can find the output of the build of each library inside the /Bin folder as expected, but they are not reused across executables - there are no CMake "project files" (is this the correct term) in the bin folder, all of them get generated inside the executable build directory.
The problem I am trying to resolve is the build times stemming from the fact that each library gets rebuilt for each executable.
At the moment the solutions I am considering is to somehow instruct CMake to use the Bin folder (or another folder) as a working folder for each library in its own folder instead of with the executable, hoping that the gradle android plugin will be smart enough to then spot that neither the cmakefiles nor the object files need to be regenerated, and avoid the rebuild.
The restriction that I have is that I cannot restructure the codebase itself, and that each Executable must be buildable separately of the others - there is absolutely no possibility of a top-level CMake - each Executable should be able to be triggered on its own.
CMake can guess if the build is up-to-date by reading informations froms the current build directory.
When you run CMake manualy in Executables/<x> directory, cmake retrieve information from the build directory associated to Executable/<x> directory. It then check if the timestamp of the built file correspond to the last build performed in this build directory. If not, it rebuild. What happen is that: Lib1 library file is built after you build Executable1, then you run cmake in Executalbe2, it compares the timestamp of Lib1 target file, see that this file was not produced by this instance of the cmake build and then rebuild the lib. And so on.
So you have two options:
1- Either you build the library and install their target files in the bindirectory (using install cmake command and make install bash command for exemple). Then in the Executalbe<x>/CMakeLists you use find_library command instead of add_subdirectory.
2- Or you create a super project which has the following structure:
+ supper_project
---CMakeLists.txt #add_subdirectory(LibProjects/lib<x>)... add_subdirectory(Executables/Executalbe<x>)...
+ LibProjects/
---Bin/ (Originally empty)
---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt)
...
---Lib10/CMakeLists.txt (same)
+ Executables/
---Executable1/CMakeLists.txt (source files here)
--------------/AndroidFiles/build.gradle (and other android project files)
(not any more:points to the CMakeLists.txt)
...
---Executable40/CMakeLists.txt
I managed to work around this problem - but in the end it was by working around rather than with CMake.
I removed the CMakeFile-level dependencies (add_subdirectory) and only left the libraries at the linking level (target_link_libraries Executable [the library files])
Afterwards, I created gradle scripts for each library and added dependencies to these scripts in each application gradle script, so that the building of the libraries gets triggered by gradle dependencies instead of CMake dependencies. It's slower than it would be if gradle could be avoided, but much faster than rebuilding every time, and the overhead is at least constant (a few seconds per project).
I think problem lies in the way you have defined your dependencies.
For each executable you are creating separate targets using add_subdirectory.
e.g. for executable 1 you have add_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1}) and for executable 2 also you have add_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1}), so cmake will create two separate targets for same library1 in each of the executable's subdirectory and thus it will create separate timestamp and cache files. That is why it looks that it is building the same library for multiple times, but in fact for cmake they are different targets.
To fix this you can include all libraries in top level CMakeLists.txt using add_subdirectory and them in each executable's CMakeLists.txt add the dependency using add_dependencies command.
I've made an android library project that uses some native libraries.
I've made the jni wrapper and put the native libs (.so) in the libs// folders. The native libs are compiled using cmake, for armeabi, armeabi-v7a, x86 and mips.
I export this project to a jar and put this jar into a "normal" android project. I then export this project to an apk and can see that my libs are bundles into it.
However, when i install the apk, the libs corresponding to the device are not copied into /data/data/com.my.app/lib and obviously, running the app complains about not finding the libs (UnsatisfiedLinkError).
I've search through SO and everywhere i can but found no answer that solved my case.
i'm using Eclipse, btw
Thanks for your help
UPDATE
OK, i've read the doc in the ndk and seen the examples, and unfortunately, i can't see the solution.
The ndk build the c code into shared libs and places them into the appropriated location in the project. But it doesn't generate anything that says that the libs must be installed with the apk.
My goal is to provide an android library (so a jar), that can be included within an android application. I don't see the real difference between what i'm doing (compile the c libs using cmake and package the jni and java compiled classes into a jar) and what is done with android.mk
If you see what i'm missing, feel free to tell me (even if its obvious).
thanks
UPDATE
i've made a dirty hack: in the libs folder of my application, i've put the jar file containing my classes and my native libs and a copy of the .so files for each arch. Suprise, the libs are no installed in /data/data/com.me.myapp/lib
It seems to confirm that it's a packaging problem.
I export this project to a jar and put this jar into a "normal"
android project. I then export this project to an apk and can see that
my libs are bundles into it.
The issue is that the Android packaging system doesn't handle with binary assets in JARs. For your application project to find and include the generated .so files, you need it to reference the library project as an 'Android library project':
Did you call ndk-build command?
See description below for details.
http://developer.android.com/tools/sdk/ndk/index.html
You can build the shared libraries for the sample apps by going into /samples// then calling the ndk-build command. The generated shared libraries will be located under /samples//libs/armeabi/ for (ARMv5TE machine code) and/or /samples//libs/armeabi-v7a/ for (ARMv7 machine code).
I am trying to build a JAR file that I can import and use it for other android projects.
I created Android project that contains java code (src/main.java) and it calls bunch of native code I wrote (Using System.loadLibrary(...))
Under jni folder, I have bunch of C/C++ codes, for instance jni/sample/sample.cpp.
My question is that when I export this project to JAR, can I build native library at the same time?
In other words, do I need to have pre-built .so file before exporting to JAR file?
My goal is when I export or something like that, it will do:
Build C/C++ code and create .so files --> Build .java ---> JAR
at once.
If you are using Eclipse, you can create a "Launch Group" in your debug/run configurations. That way you can include your Java build and an Android Native Application build in one configuration.
If you are looking to move to a more sophisticated build system, you should look into Maven. It is considerably more complex than the plain old debug/run configurations, but it is much more powerful. It includes an apklib packaging to build libraries for Android. There are a few quirks with using the NDK in an apklib, but reasonable project design can avoid most problems.
I am currently developing an android application that allows me to dynamically load modules.
Therefore I can have as many modules as I like, and my main application just needs to load them.
I've managed to make this work for the most part - but I want to create an executable to "speed up" the module creation process, or even just find a way to simplify the steps involved.
To create a module I currently have to do the following:
Build the android project containing the files required for my
module [none of which are activity classes - so I don't have to
worry about the androidmanifest file at all]
Use the eclipse IDE jar creation tool to select which src files I want to be compiled into .class to put into my jar, and specify my own custom manifest file for this jar, as well as package all the images I use for the module into the jar as well.
Then using the jar file I run the dex creator command on it to generate a .dex file from the class files contained in the jar, and then use the aapt command to push the dex file back into the jar file.
At this point the jar(Now its a module) is created and I can put it on the server for downloading, download the modules in my app and load all the code I need in my app using reflection.
I have looked into building with ant. It looks fairly complicated for what I wish to achieve and I'm not quite sure where to start with it.
I obviously can't use simple javac to compile my java files contained in my module src because all that code makes references to the android sdk as well as a static library shared between my main application and my respective module.
Currently I use the Eclipse IDE to create the inital jar with all my packaged images, class files, manifest, and then I use two separate batch files that call on the android-sdk to create dex and push the dex into the jar.
Can I simplify this process in one easy step instead? Or is trying to do this - a whole project on its own?
I have looked into building with ant. It looks fairly complicated for what I wish to achieve and I'm not quite sure where to start with it.
The documentation for Ant is online, as is the documentation for building Android projects with Ant. The only difference is that you will want to add a <jar> task to your Ant build.xml file, as I have done in several projects, such as this one:
<target name="jar" depends="debug">
<jar
destfile="bin/CWAC-EndlessAdapter.jar"
basedir="bin/classes"
/>
</target>
You are also welcome to consider Maven. While I do not use Maven personally, it has many fans and community-driven Android support.
You are also welcome to write your own build script in any programming language that suits your fancy: Java, Ruby, Perl, Python, etc.
I obviously can't use simple javac to compile my java files contained in my module src because all that code makes references to the android sdk as well as a static library shared between my main application and my respective module.
Every Android IDE, and Ant, and Maven, and so on, "use simple javac to compile [an Android project's] java files". They simply add the appropriate Android SDK JAR file to the build path.
I have an Android project that depends on a non-Android JAR that contains resources (Java resources, not Android resources), which classes within the JAR need to load. When running the application, these resources are not found (i.e., ClassLoader.getResourceAsStream() fails), apparently because the resources are not being included in the APK.
I found some discussion here:
http://code.google.com/p/android/issues/detail?id=10076#c7
But I need to build the APK in Eclipse. Short of doing a command-line build with a deprecated tool (ugh), or duplicating all the resources (ugh), how can I make it work?
Create your jar file with the classes you need and save it your computer. Then in the project explorer right click the project and go to properties -> Java Build Path -> Libraries. Now import the jar file.
You should now have full access to the classes and methods in your code and the jar file will be installed with your APK. My guess is you have utility classes and when you are calling them in your source Eclipse is importing them from another project.
The solution I have given works for sure (I do it myself).