VerifyError when build with ant, OK when build from Eclipse - android

My java project for Android has several configurations. Previously I switched them and build apk from eclipse manually, but recently I've developed several ant tasks to make my life much easier: I launch cmd file and it builds all the configurations (changing config vars each time, moving resources, modifying manifest, etc.).
But today I've found that code compiled by ant (it uses javac) with android workflow (my build.xml includes ${sdk.dir}/tools/ant/build.xml) is different from code generated by ADT tool in Eclipse. And difference is fatal.
On compile stage javac claimed that some files include BOM, and one class is too big (to many static arrays). I've converted all files to utf8 w/o bom, splitted big class into two and javac had no more issues. It was easy.
However if I launch ant-made apk on 4.0.x device or emulator (while works on 1.6, 2.2, 4.1, 4.2) it force closes in runtime and says:
03-01 09:15:16.247: W/dalvikvm(1993): VFY: register1 v3 type 17, wanted 18
03-01 09:15:16.247: W/dalvikvm(1993): VFY: rejecting opcode 0xc8 at 0x0023
03-01 09:15:16.247: W/dalvikvm(1993): VFY: rejected Lcom/myproj/MySomeClass;.doThing (I)V
03-01 09:15:16.247: W/dalvikvm(1993): Verifier rejected class Lcom/myproj/MySomeClass;
03-01 09:15:16.247: W/System.err(1993): java.lang.VerifyError: com/myproj/MySomeClass
...
<stack here>
...
But eclipse-adt-made apk works on 4.0.x pretty well! Moreover - I never saw adt claims about utf bom or class size on compile.
So I assume we should use something else raither than javac in ant build. But Google uses exactly javac in its build.xml. How can we use ADT compiler instead of javac when building with ant?
Of course I still can make builds in eclipse, but ant scripts spends 1 minute when I spend 20 minutes, and it never make silly mistakes while changing cfg vars (there some dependencies between them).
Thanks in advance!
UPDT:
I suspect it is somehow connected with java version I use. Ant executes with 1.7 x86 jdk, while eclipse uses jdk1.6.0_26 x64. Someone says that Dalvik dex doesn't understand some java 1.7 bytecodes, but I should check.
UPDT1: No, I've removed all jdks, then installed both jdk 1.6.0_41 x86 and x64, set eclipse work with 1.6.0_41 x64 and set JAVA_PATH to jdk 1.6.0_41 x86. The same thing - apk compiled in eclipse (Android tools->Export signed apk) works, ant-compiled apk says VerifyError.

Think I've solved this issue.
I spent hours switching java versions, re-defining default google ant tasks, trying to launch different javac from several jdk as standalone to compile my classes. During last five years I never compiled java with console tools, so it was hard and confusing. I had no luck with any javac, the same verify error.
Then I read Eclipse and Android docs and found that when we build apk in eclipse, ADT uses Eclipse's JDT (Eclipse Compiler for Java) instead of javac to compile java code into classes, and then dx tool to make dalvik code.
So we need to launch JDT instead of normal -compile ant task, right? No, actually everything is easier. As it often happens I started from the end but once I understood that I need this compile tool I was on the right way.
Eclipse Compiler for Java (JDT ECJ) is much smarter tool than actual javac. It's a new tool for me with bunch of parameters, but JDT provides pretty cool ant javac adapter, and we can use it in javac ant task - set "build.compiler" property and then launch normal android ant -compile task:
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter" />
<javac encoding="${java.encoding}" source="1.6" target="1.6" debug="true" extdirs=""
includeantruntime="false" destdir="${out.classes.absolute.dir}"
bootclasspathref="project.target.class.path"
verbose="${verbose}" classpathref="project.javac.classpath"
fork="${need.javac.fork}" >
<src path="${source.absolute.dir}" />
<src path="${gen.absolute.dir}" />
<compilerarg line="${java.compilerargs}" />
</javac>
But this will not work unless you have ecj.jar. And there is no such a file in eclipse! Continuing investigation I've found out that Eclipse Compiler for Java can be downloaded as standalone. To make this work you need to copy this jar to ant/lib folder. But strange thing - ecj 4.2.2 compiled code with the same verify problem. Luckily I've tried ecj 3.5.1 - and it worked! However I'm not satisfied - I still can't say why ecj 4.2.2 doesn't help while 3.5.1 does. What if I upgrade eclipse and it will compile bad classes? I've compared byte code - it differs very slightly (decompiled by jd-gui), so I assume problem is in something inside resulting class files. I'd like to know what's the heck but I even can't imagine what to look for.
Anyway, there is more. When you look to eclipse/plugins folder you'll see a file with name like "org.eclipse.jdt.core_3.6.2.v_A76_R36x.jar". It holds jdtCompilerAdapter.jar file inside (as jar is a zip archive). If you copy it to ant/lib and then copy org.eclipse.jdt.core_xxxxxx.jar file itself you get exactly the same compiler that your current eclipse version has! Voila! This way you can be sure that if eclipse makes a "good" code - ant will do also.
So finally everything resulted in two simple steps:
copy org.eclipse.jdt.core_xxxxxx.jar and jdtCompilerAdapter.jar from inside of it to your ant/lib folder.
add following to you project.properties file:
java.target=1.6
java.source=1.6
build.compiler=org.eclipse.jdt.core.JDTCompilerAdapter
That's all!
But if you have ideas why ecj from eclipse juno package (4.2.2) fails to compile right code I'd like to listen!

Related

How can I build an Android apk without Gradle on the command line?

I wrote an Android app that uses no dependencies or modules, has a single activity, and has a single layout file.
How can I build an apk file of my app on the command line without using Gradle (or other "build systems" or "dependency management" software)?
Use the following steps to build your apk manually, if you don't want use ant/gralde to build. But you must have Android SDK installed at least.
create R.java from aapt
use javac to compile all java source to *.class
use dx to convert all *.class to dex file, e.g output is classes.dex
create initial version of APK from assets, resources and AndroidManfiest.mk, e.g output is MyApplication.apk.unaligned
use aapt to add classes.dex generated in step 3 to MyApplication.apk.unaligned
use jarsigner to sign MyApplication.apk.unaligned with debug or release key
use zipalign to align the final APK, e.g output is MyApplication-debug.apk or MyApplication-release.apk if signing with release key
Done
I have created a sample script to do all the stuffs above, see here
Actually, Some articles have discussed this topic, see the following links.
https://www.apriorit.com/dev-blog/233-how-to-build-apk-file-from-command-line
https://spin.atomicobject.com/2011/08/22/building-android-application-bundles-apks-by-hand/
Try this for building apps with support libraries from command line. https://github.com/HemanthJabalpuri/AndroidExplorer
alijandro gave a perfect answer. I managed to write simple ANT script that builds production APK with AdMob and without gradle usage. A couple useful comments:
If you want to obfuscate classes you have to jar the compiled classes (between javac and dx steps) and run proguard on it
For AdMob you have to extract the following jars from zip archives (like
C:\Users\<User>\AppData\Local\Android\sdk\extras\google\m2repository\com\google\android\gms\play-services-ads\10.2.6\play-services-ads-10.2.6.aar):
play-services-ads-10.2.6.jar
play-services-ads-lite-10.2.6.jar
play-services-base-10.2.6.jar
play-services-basement-10.2.6.jar
play-services-clearcut-10.2.6.jar
play-services-gass-10.2.6.jar
play-services-tasks-10.2.6.jar
These archives should be passed in javac and dx
For AdMob there are several additional simple config steps as well
Gradle does a lot of mess with android projects, so own script looks like a singular solution for projects that are going to go into production
A while back I stumbled across this thread after getting frustrated with both Android Studio and Gradle. Inspired by the answer from alijandro and this template from authmane512, I wrote a series of scripts to compile an Android app (including with dependencies/packages) in Java or Kotlin without any external build system.
Link: https://github.com/jbendtsen/tiny-android-template
There is a little bit of DIY involved here, but given that it's the sort of stuff that something like Gradle would do for you, I would argue that it's useful to know. Besides, it's like wayyyy less slow, and you have a lot more control how your app gets assembled.

Ant / Android - Reduce Compile Time

I work on a small Android application project that comprises of ~5k lines of code and a handful of resources. It also has a few library dependencies in the lib/ folder. The problem is that my compile time is very slow. Suppose I perform the following:
ant clean debug
This takes about 28 seconds. Performing a subsequent:
ant debug
Still takes 9 seconds even though I've made not changes to the source between compilation.
It seems like the majority of the slowness happens during the '-dex' target.
How can I improve the speed performance of my Android builds?
Please take a look at this link for my edited 'ant clean debug' output: http://pastebin.com/XY08mr5G
I'm using:
Apache Ant(TM) version 1.8.4, Android Debug Bridge version 1.0.31, Android SDK Tools 22.01,
Android SDK Platform-tools 17, Android SDK Build-tools 17
Thanks.
28 seconds that's not so much for an Ant build script. Compiling to a dex format does take a while. I don't know when you run the ant build script but while you are developing you better use an IDE with compiler such as Eclipse and it will compile in background. Use the Ant build script when you create a build for testing or releasing.
In hindsight, my core issue is that I don't trust Ant to correctly track which sources have been modified since last build. I often find myself running 'ant clean debug' every time I compile simply because I've been burned too many times with botched builds.
If only I had a target to perform a fresh compile of my sources without actually redexing all of my dependency libraries each time!
Here's a proposed solution to my problem. Add this Ant target to my project's build.xml:
<target name="cl">
<delete file="bin/classes.dex" />
<delete file="bin/classes.dex.d" />
<delete dir="bin/classes" />
</target>
Now running 'ant cl debug' takes considerably less time, clocking in at 5 seconds. All of my Java source files are recompiled, but the libraries are not re-dexed each time. (which the 'clean' target requires every time)
I'm content with this solution and will await Android's future Gradle based build system. With any luck, it will provide more versatile targets than this Ant based system.

Automated unit testing for Android / Ant

I have an Android project and JUnit tests in my code.
I wanted to know if there is an ant task to run some tests.
In fact, I have several classic tests which are run using JUnit to test several methods, and some tests that need an android emulator or at least need to be run on an android device.
As I didn't find any documentation, I wanted to know if it's possible to do that kind of thing.
Like
junit-android dir="."...
Thanks a lot for your help and time.
Just to be clear because I've search on the web and didn't find many things, so hope you can help.
I have an Android project that contains NO activities.
Actual build.xml file:
I compile java source code
It generates me a .jar file.
I need to run some tests defined in my project/tests/ folder, using
the previous generated library. Thoses tests need to be runned on an
emulator device using ANT build file, whithout being dependent of
Eclipse.
Project:
src (java source code)
gen
bin
res
tests (Android test project)
AndroidManifest.xml
build.xml
...
The test project generated is containing a build.xml that has been automatically generated using android update command. Sadly, there is no task "run-tests". And how do I specify that I would like to use my library for those tests?
Everything you need to create and run android test projects from the command line, provided by Google itself ;-)
http://developer.android.com/tools/testing/testing_otheride.html
The command line you need is something like:
adb shell am instrument -w <test_package_name>/<runner_class>
To call that from Ant, use the <run-tests/> task, described here.
Create a target in your build.xml like this
<target name="run-tests">
<test-junit includedTests="pathToPackageContainingTests}/*.class" />
</target>
Then you can simply do this
ant clean release run-tests

Long build times with sbt android-plugin

I have created a demo application with the sbt android-plugin.
The app is very simple.
I have placed a MainActivity.java file under /src/main/java/my/package/ and when a button is pressed it takes you to a second Activity but done in Scala.
Everything is working fine but the build times are killing me.
When I modify something I run in my device using:
> android:package-debug
> android:start-device
My issue is that it takes almost a complete minute to build a two activities project.
Is there another way to compile and run?
This is my output of android:package-debug
> android:package-debug [info] Wrote
/Users/macarse/Documents/demo/target/src_managed/main/scala/my/package/TR.scala
[info] Compiling 1 Scala source to
/Users/macarse/Documents/demo/target/scala-2.9.0-1/classes...
ProGuard, version 4.6 ProGuard is released under the GNU General
Public License. You therefore must ensure that programs that link to
it (scala, ...) carry the GNU General Public License as well.
Alternatively, you can apply for an exception with the author of
ProGuard. Reading program directory
[/Users/macarse/Documents/demo/target/scala-2.9.0-1/classes] Reading
program jar
[/Users/macarse/.sbt/boot/scala-2.9.0-1/lib/scala-library.jar]
(filtered) Reading library jar
[/Users/macarse/Documents/android-sdk-mac_86/platforms/android-4/android.jar]
Note: You're ignoring all warnings! Preparing output jar
[/Users/macarse/Documents/demo/target/classes.min.jar] Copying
resources from program directory
[/Users/macarse/Documents/demo/target/scala-2.9.0-1/classes] Copying
resources from program jar
[/Users/macarse/.sbt/boot/scala-2.9.0-1/lib/scala-library.jar]
(filtered) [info] Dexing
/Users/macarse/Documents/demo/target/classes.dex [info] Packaging
/Users/macarse/Documents/demo/target/demo-0.1.apk [success] Total
time: 56 s, completed Oct 29, 2011 4:22:54 PM
There are a couple of options:
preinstall scala on the phone/emulator
Include predexed scala as a library
There is also a project called treeshaker for Eclipse which is a lot faster than proguard, but it is not integrated w/ the sbt plugin yet.
It takes long time because proguard need to process Scala standard library to minimize the .apk file you get, and Scala standard library is huge.
I will suggest you switch to Scala 2.8 if you didn't use features of Scala 2.9, because 2.8 has a smaller standard library.
In the other hand, don't use android:package-debug when not necessary. compile will compile your source code, it is sufficient if you only want to make sure your program could be compiled.
Only use android:package-debug when you are about to test it on the Android device, this will save your time.

Upgraded to 2.3, now ant builds don't include the jars in my libs directory

I've been doing all my builds using ant on the command line (Ubuntu 10.04). I loaded up the 2.3 SDK and made the necessary path changed (platform-tools). Now my builds don't include the jars in my libs directory. Any thoughts on what I need to change?
The Ant build system now requires Ant 1.8+
Unfortunately it "works" (broken) with 1.7 because we rely on a new behavior in 1.8, not a new task or attribute that would break 1.7
i'm not familiar with the ant builde for android as i'm usig eclipse(why shouldn't ou ? it generates build.xml autotmatically).
In any case whe you say platform tools you mean $ANDROID_HOME/platforms/android-9 ?
Are you sure it's needed for ant ? i know the ant build file itself is pretty empty and most of the work is done in their java .sh files so it's ard to tell what they are missing, cold it be you found a bug in their new SDK ?
I've got other more serious problems with SDK2.3 (the AVDs are bust). I'd set up Ant builds OK to work on 2.2 and was looking to see if an Ant build would run. My custom build.xml overrode quite a bit of the stuff in ant_rules_r3.xml but still used some of it. I noticed that this has now been removed and replaced with main_rules.xml, which is a bit different. 'project.libraries' replaces 'android.libraries' for one thing. It's probably worth you looking at the differences if your build.xml was based on ant_rules_3.
I'm not going to look at it myself until my main problem is fixed.

Categories

Resources