Adding an Eclipse "Android Library" project and building via Maven - android

I am trying to include cocos2d into a preexisting app. I've done things the Eclipse way, such as setting "isLibrary" and adding the library project to the build path in Eclipse, and I have the following dependency in my app's pom.xml:
<dependency>
<groupId>cocos2d_android</groupId>
<artifactId>cocos2d_android</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
I thought this would've taken care of the issue, but when I build, the library seems not to be included. I know this because when I start an Activity, SimpleGame, referencing one of the classes in the cocos2d source, the Activity dies and I get this stacktrace in DDMS:
E/AndroidRuntime(10621): FATAL EXCEPTION: main
E/AndroidRuntime(10621): java.lang.NoClassDefFoundError: org.cocos2d.opengl.CCGLSurfaceView
E/AndroidRuntime(10621): at com.xyz.game.SimpleGame.onCreate(SimpleGame.java:22)
...
I'm looking for two things:
1) a reliable way to see if a certain class/jar/whatever was packaged up into my apk, as the steps to get to this point in my app are long and complicated right now
2) Something in the Manifest or pom.xml for either the main app or the library project seems to be missing - something needed to signal to Maven to pick up this other project - what is it?
I'm using Maven 3.0.4 and 3.0.0-alpha-13 of the plugin, building for level 8 and up.

1) a reliable way to see if a certain class/jar/whatever was packaged up into my apk, as the steps to get to this point in my app are long and complicated right now
Build project from command-line (i.e. mvn clean install), maven will output verbose logs during every single phase/goal of build, in the dex goal, you can see something like this:
[INFO] --- android-maven-plugin:3.1.1:dex (default-dex) # myproject ---
[INFO] C:\Program Files\Java\jdk1.6.0_21\jre\bin\java [-Xmx1024M, -jar, C:\Progr
am Files\Android\android-sdk-r16\platform-tools\lib\dx.jar, --dex, --output=C:\workspace\myproject\target\classes.dex, C:\workspace\myproject\target\classes, C:\maven\repository\cocos2d_android\cocos2d_android\1.0.0-SNAPSHOT\cocos2d_android-1.0.0-SNAPSHOT.apklib, C:\maven\repository\com\google\code\gson\gson\1.7.1\gson-1.7.1.jar, ... ...]
The Android Library Project is actually dex-ed as cocos2d_android-1.0.0-SNAPSHOT.apklib with some other regular jar library archives.
2) Something in the Manifest or pom.xml for either the main app or the library project seems to be missing - something needed to signal to Maven to pick up this other project - what is it?
It is ApkLib, which is simply a zip archive of the Android Library Project (src/, res/, AndroidManifest.xml and etc.). We usually create/implement our own Android Library Project with the dependant Android Project as multi-module maven project, however, this is not necessary in case if you need reference Android Library Project written by other developers. Thanks to the developer, android-maven-plugin has already supported non-Maven Android Library Projects, check out Compatible with non-Maven Android Library Projects:
The generated .apklib file will have the layout of a standard Android/Eclipse library project. This means that regardless of your Maven layout, the layout inside the .apklib file will be that source code is in "src/" instead of "src/main/java/", but still interpreted correctly when used in an Android/Maven application project. This is to be compatible with non-Maven developers' library projects, which is important to grow the Android developer community.
Use other non-Maven developers' libraries
It also means we can take any external Android library project zip file (from non-Maven developers) and do mvn install:install-file ... on it and simply start using it as a dependency.
Share your .apklib with non-Maven developers
To share your .apklib file with a non-Maven developer, they will probably feel more comfortable if you rename it to .zip. They can then simply unpack it in a directory and use it from there.
So the workaround is:
Pack your Android Library Project into zip archive properly, then rename it to something.apklib.
Install something.apklib into your Maven local repository by using mvn install:install-file.
In any Android Project that requires Library dependency, simply using:
<dependency>
<groupId>cocos2d_android</groupId>
<artifactId>cocos2d_android</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>apklib</type>
</dependency>
Check out Samples on android-maven-plugin website to see how to use apklib properly.

Scope shouldn't be provided. Provided means:
provided - this is much like compile, but indicates you expect the JDK
or a container to provide it at runtime. It is only available on the
compilation and test classpath, and is not transitive.
Use compile instead.
Extra tip: Since compile is the default, you can remove the <scope>provided</scope> line.

Related

Difference between module, libraries, jar, library projects, gradle projects, aar and jar

I work for a company which has a android mobile application developed by an offshore team. I have access to GitHub repositories.
I am piecing together the android app block by block and it is giving me hell.
How do I distinguish between module, libraries, jar, library projects, gradle projects, aar and jar. Can someone please give me a practical definition. NOT out of a freaking google search. I have Google too.
PS yes I am a noob and not proud of it.
I'm just giving a brief description about each of these. I hope I'm clear.
Module : A Module is an component of your application that can build / test independently and re use it in another application if required.
Libraries : AAR files, JAR files etc.
JAR : Java library
AAR : Just like JAR, only difference is that it also contains android specific files like resources etc.
Gradle Project : Gradle is just a build system which is used by Android Studio to build the android project. Its very much powerful as compared to the build system which was used in Eclipse earlier.
Library Project : An Android library project is similar to an Android app project in that it also includes a project manifest file in the project’s root directory. Also, this directory contains src, res, and other directories that you also find when building an app project.
However, there is a significant difference. You cannot compile a library project into an APK file because a library project doesn’t describe an app. Instead, it provides reusable code and resources that contribute to an app when the app’s project and source code refer to the library project. At build time, this code and these resources are merged into the app’s APK file.
To explain more on this, let me give you an example :
Say you want to use a networking library volley for making API calls, now since this is an open source library from Google you can clone it making customisations as per your requirement.
You can make volley library as your Library Project, build it independently, unit test, etc.
Now say you started building an application where you need to make HTTP calls so you need to add volley library to your project. You have two choices for that :
Compile your library project volley, generate the aar file and add it your app Project.
Add Volley as module in your project. (If you choose this option you can make changes to volley library in same studio project since it will act as a component in your project)
Please let me know if something is not clear.
1.) Module
A module is a collection of source files and build settings that allow you to divide your project into discrete units of functionality. Your project can have one or many modules and one module may use another module as a dependency. Each module can be independently built, tested, and debugged.
There are 4 type of module in Android Studio.
Phone & Table Module
Android Wear Module
Android TV Module
Glass Module
2.) Support Library
The Android Support Library offers a number of features that are not built into the framework. These libraries offer backward-compatible versions of new features, provide useful UI elements that are not included in the framework, and provide a range of utilities that apps can draw on.
Support libraries provide a range of different features:
Backward-compatible versions of framework components.
UI elements to implement the recommended Android layout patterns.
Support for different form factors.
Miscellaneous utility functions.
3.) Jar file
JarFile is used to read jar entries and their associated data from jar files.
for more detail visit this : https://developer.android.com/reference/java/util/jar/JarFile.html
4.) Android Library Project
The Android team introduced a new binary distribution format called Android ARchive(AAR). The .aar bundle is the binary distribution of an Android Library Project.
An AAR is similar to a JAR file, but it can contain resources as well as compiled byte-code. This allows that an AAR file is included in the build process of an Android application similar to a JAR file
5.) Gradle and Gradle Project
Gradle is an automated build toolkit that allows the way in which projects are built to be configured and managed through a set of build configuration files. This includes defining how a project is to be built, what dependencies need to be fulfilled for the project to build successfully and what the end result (or results) of the build process should be. The strength of Gradle lies in the flexibility that it provides to the developer. The Gradle system is a self-contained, command-line based environment that can be integrated into other environments through the use of plug-ins. In the case of Android Studio, Gradle integration is provided through the appropriately named Android Studio Plug-in.
for more detail visit this : http://www.techotopia.com/index.php/An_Overview_of_Gradle_in_Android_Studio

Google Play Services with Maven?

I'm some kind of confused. I want to install Google Play Services for Android and found this question: How can i use google play services in a maven project?
There is a reference to https://github.com/mosabua/maven-android-sdk-deployer/ which provides a project to install a lot of mavenized APIs. So I downloaded and built it to get one of the latest Google Play Services API but when I add
<dependency>
<groupId>com.google.android.gms</groupId>
<artifactId>play-services</artifactId>
<version>5.0.89</version>
<type>aar</type>
</dependency>
to my project, I get a "support-v4-19.1.0.jar" as dependency which includes neither any Google Play Services classes nor do I have any of those layout files supplied with Google Services API. For example: When I look to https://developer.android.com/google/play-services/setup.html, and read the ProGuard part, then there must be at least a class called SafeParcelable, but this included project by Maven does not even have the common package where this class is included. I wonder what's going on here.
The project play-services-5.0.89.aar exists in the Maven repository. But how do I use this? Is there any additional task to do since it's aar or something?
[UPDATE]
Ok, it seems that's only an Eclipse problem, because com.google.android.gms.common.GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext()) is compilable by Maven although Eclipse doesn't find it. That means that the Google Play Services API works within the project.
[UPDATE 2]
Meanwhile I figured out that aar is not supported by Eclipse. But I use a little trick to use apklib and aar (which is supported by android-maven-plugin) with Eclipse. I unpack the package (in Maven repository) and import it as library into Eclipse. Then I add the library reference into the main project's properties. Eclipse finds the classes of these libraries then, so no erroneous Eclipse project anymore (even content assist works) and you can even build it by Maven when you use the android-maven-plugin. In other words: You only need to import aar and apklib as libraries into Eclipse due to code writing to not have an erroneous project. For the build process all this doesn't matter, since Maven does all your build handling.

Why do Google recommend copying libraries into your tree?

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.

How to compile and jar an Android project using Ant?

I'm trying to get a handle on this whole "Ant" buildsystem thing. I've created a build.xml that Android natively gives me by using the command: android update project -p . .
While this has given me a template build.xml file, I would like a couple more options. Specifically, I would like to be able to JAR and/or Compile my project; preferably with a version number.
Bonus Question: How can I exclude files from my JAR build. For example, I have one activity that I've used to test my functionality, but I don't want that to be included in the final JAR.
My build.xml file that Android has given me is Gisted here since it's pretty long (mostly comments).
EDIT: I'm also using IntelliJ so no Eclipse specifics, please!
Specifically, I would like to be able to JAR and/or Compile my project; preferably with a version number.
In Android, version numbers are for apps, not JARs.
That being said, adding a jar target is a matter of adding this to your build.xml file towards the bottom:
<target name="jar" depends="debug">
<jar
destfile="bin/whatever-you-want-to-call-the.jar"
basedir="bin/classes"
/>
</target>
Then, run ant jar to compile and package the JAR file.
You will see this pattern in most of the reusable Android components in my GitHub area (see the cwac- repos).
Bonus Question: How can I exclude files from my JAR build. For example, I have one activity that I've used to test my functionality, but I don't want that to be included in the final JAR.
Use excludes or excludesfile, as described in the jar Ant task documentation.
For reuse of Android and non-android projects I would suggest you take a look at the Android Maven Plugin. It takes advantage of dependency management and other powerful features of Maven and will be much more suitable to what you want to do.
Checkout the webpage and documentation on it and maybe the chapter about Android development in Maven : The Complete Reference I wrote to get a bit more understanding as well as have something to look at about Maven.
The Android plugin supports reuse for normal jar artifacts and if there are Android dependencies within the code you can use apklib projects. Lots of projects like Roboguice, robolectric, actionbarsherlock and others use this feature successfully.

Packaging a jar for Android

I have modularised some simple classes into their own project for reuse elsewhere. These classes typically contain only fields and accessor methods (i.e. nothing Android specific).
They are later packaged up using ant's jar task and stored in a Maven repository.
In an Android project, I've stored said jar file into a libs directory and added to the build path. On running the emulator however, I get a "class not found" exception relating to my package. Other third party libraries (such as GSon) are being picked up fine.
Are there any specific steps required to make a jar file compatible with Android? (This reply seems to suggest otherwise). How can I debug this further?
No as long as you do not need e.g. classes from javax.* that are not in Android. If I were you I would consider looking at using the Android Maven Plugin for your build though. Check out the morseflash example from the official samples collection. It showcases exactly your scenario.
You only need an Android library project if your going to be reusing Android components and resources. In your case, I believe you added the project to the build path, but I'm sure your not exporting it as part of the dependent project.
So open the project properties, open up the Java Build Path options and make sure that you have your JAR selected as an exported dependency in the Order and Export tab.
UPDATE
This is what your entry should read:
<classpathentry exported="true" kind="lib" path="libs/tlvince-dao-0.1.0.jar"/>
I've also forked an updated version of your gist.
This issue was a result of compiling the jar to Java 7. Android does not support Java 7 (yet).
Compiling to Java 6 bytecode by setting target="1.6" in ant's javac task solved the issue.

Categories

Resources