Sunday, May 24, 2015

Multidex - Building Apps with Over 65K Methods

As the Android platform has continued to grow, so has the size of Android apps. When your application and the libraries references reach a certain size, you encounter build errors that indicate your
app has reached a limit of the Android app build architecture. Earlier versions of the build system report this error as follows

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

More recent versions of the Android build system display a different error, which is an indication of the same problem:


trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

Both these error conditions display a common number: 65,536. This number is significant in that it represents that total number of references that can be invoked by the code within a single Dalvik Executable (dec) bytecode file. IF you have built an Android app and received this error, then this document is for you, which explains how to move past this limitation and continues building your app.

In many cases these high numbers are reached by including 3rd-party libraries. Here is a summary of some popular libraries that is included:


NameMaven ArtifactOverall Method Count
Google Play Servicesplay-services:6.1.1129,460
Guavaguava:18.014,842
AppCompat V7appcompat-v7:21.0.012,324
Android Support V4support-v4:21.0.08,078
Jacksonjackson-jaxrs-json-provider:2.4.36,731
Joda-Timejoda-time:2.55,025
Apache Commons Lang3commons-lang3:3.3.23,582
Apache Commons IOcommons-io:2.41,571
Gsongson:2.31,243



Solution

MultiDex

In many cases MultiDex allows you to use multiple Dex files contained within on APK. With a few steps, your classes will split automatically into several DEX files i.e classes.dex, classes2.dex, classes3.dex etc in cas you reach the ethos index limit. 
To integrate MultiDex into your application follow below steps.

First step:

Enable mult-dex mode in your builds - A component of the Android build tools named dx, which is executed during the build process as part of the dex task now accepts a -multi-dex flag.
Add -multi-dex options to dx command line to allow the generation of several dex files when method index limit is about to be reached. In order to achieve that add following line of code in your build.gradle file.
android {
  defaultConfig
    //Enabling multidex support.
     multiDexEnabled true 
  }
}
This essentially modifies all dex* tasks i.e dexDebug, dexRelease and adds the -multi-dex flag to the arguments list when executing dx.
After doing this, a build should generate an APK file with multiple DEX files.


Second step:

Now we would be loading these classes at runtime. For Android L or higher (5.0+) this is natively supported, for devices running API level 20 or lower, we need to make another small effort. Luckily, the Android Support Library (revision 21) is shipped with MultiDex support. The package provides a utility that will take care of the class loading process from the additional DEX files on API levels 4 through 20. For API 21 or higher it does nothing, again, as it is natively supported. The package has the following description:

Monkey patches the application context classloader in order to load classes from more than one dex file. The primary classes.dex must contain the classes necessary for calling this class methods. Secondary dex files named classes2.dexclasses3.dex… found in the application APK will be added to the classloader after first call to install(Context).
This library provides compatibility for platforms with API level 4 through 20. This library does nothing on newer versions of the platform which provide built-in support for secondary dex files.

Take the android-support-multidex.jar file from your SDK folder under extras/android/support/multidex/library/libs folder, and add it as a dependency. Then is can be used in one of the following ways.
If you don't have a custom Application class registered, just set the following attribute on your application element in the manifest file
android:name="android.support.multidex.MultiDexApplication"
However, if you have a custom Application class registered, you can either make that class extend MultiDexApplication instead of Application, or simply override attachBaseContext() like so :
@Override protected void attachBaseContext(Context base) {
  super.attachBaseContext(base)
  MultiDex.install(this)
}
Thats it, now your project should no longer be affected by 65K 
limitation.

Saturday, May 23, 2015

Android Studio Overview and Migrating from Eclipse Projects


Android studio is a Android focused official IDE designed specifically for Android development, similar to eclipse with the ADT plugin. Contains all the Android SDK Tools to design, test, debug, and profile your app. On top of the capabilities you expect from IntelliJ, Android Studio offers:



  • Powerful code editing (Smart editing, code refactoring)
  • Rich Layout editor
  • Gradle-based build support
  • Maven support
  • Template based wizards
  • Lint tool analysis
  • Easy access to Google service like GCM


  • Android development environment built on intelliJ IDEA

      Android build system overview

      The Android build system is the toolkit you use to build, test, run and package your apps. The build system can run as an integrated tool from the Android Studio menu and independently from the command line. You can use the features of the build system to:
      • Customize, configure, and extend the build process.
      • Create multiple APKs for your app with different features using the same project and modules.
      • Reuse code and resources across source sets.


      The general process for a typical build is outlined below. The build system merges all the resources from the configured product flavors, build types, and dependencies. If different folders contain resources with the same name or setting, the following override priority order is: dependencies override build types, which override product flavors, which override the main source directory.
         The Android Asset Packaging Tool (aapt) takes your application resource files, such as the AndroidManifest.xml file and the XML files for your Activities, and compiles them. An R.java is also produced so you can reference your resources from your Java code.
         The aidl tool converts any .aidl interfaces that you have into Java interfaces.
         All of your Java code, including the R.java and .aidl files, are compiled by the Java compiler and .class files are output.
         The dex tool converts the .class files to Dalvik byte code. Any 3rd party libraries and .class files that you have included in your module build are also converted into .dex files so that they can be packaged into the final .apk file.
         All non-compiled resources (such as images), compiled resources, and the .dex files are sent to the apkbuilder tool to be packaged into an .apk file.
         Once the .apk is built, it must be signed with either a debug or release key before it can be installed to a device.
         Finally, if the application is being signed in release mode, you must align the .apk with the zipalign tool. Aligning the final.apk decreases memory usage when the application is -running on a device.


      Dependency Managment overview
      1. Ant -  Apache Ant is a Java based build tool from Apache Software Foundation. Apache Ant's build files are written in XML and they take advantage of being open standard, portable and easy to understand. Apache Ant is a Java library and command-line tool whose mission is to drive processes described in build files as targets and extension points dependent upon each other. The main known usage of Ant is the build of Java applications. Ant supplies a number of built-in tasks allowing to compile, assemble, test and run Java applications. Ant can also be used effectively to build non Java applications, for instance C or C++ applications. More generally, Ant can be used to pilot any type of process which can be described in terms of targets and tasks. 

      2. Maven - Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information. Maven’s primary goal is to allow a developer to comprehend the complete state of a development effort in the shortest period of time. In order to attain this goal there are several areas of concern that Maven attempts to deal with:
           Making the build process easy
           Providing a uniform build system
           Providing quality project information
           Providing guidelines for best practices development
           Allowing transparent migration to new features
      3.  Gradle - Gradle is the next evolutionary step in JVM-based build tools. It draws on lessons learned from established tools such as Ant and Maven and takes their best ideas to the next level. Following a build-by-convention approach, Gradle allows for declaratively modeling your problem domain using a powerful and expressive domain-specific language (DSL) implemented in Groovy instead of XML. Because Gradle is a JVM native, it allows you to write custom logic in the language you're most comfortable with, be it Java or Groovy.
      Features & Benefits of Gradle
      1. Dependency Management – Flexible approach to dependency management that can reuse existing maven respositories or reference local jars.
      2. Gradle is a advanced build management system based on Groovy
      3. Its an open source build system
      4.  Combines the power of Ant and Maven
      5. Product flavors – Free and Paid versions
      6. Build Type – Debug, QA, release
      7. Binary bundles for libraries (.aar) – Gradle supports the new .aar binary bundle format for the library projects.


      Migrating From Eclipse Projects
      To migrate an Eclipse project to an Android Studio project, you have two options:
      • Importing the Eclipse project directly into Studio. This is the preferred approach, and has numerous advantages:
        • It will detect many source libraries (such as ActionBarSherlock) and binary libraries (e.g. guava.jar), and will replace these with maven dependencies instead, which means you no longer have to maintain the libraries manually
        • It will rewrite the project using the new canonical Android Gradle project structure, which supports instrumentation tests in the same project as the tested code, flavor and build type specific resources, etc

      • Exporting the Eclipse project from Eclipse as a Gradle project. This mechanism is not as flexible (or frequently updated) as the direct Gradle import, but it has two usages:
        • It will let you keep your Gradle project using the same file structure as Eclipse ADT projects (in other words, it does not move files around; everything is kept in place, and a special build.gradle file tells Gradle to look for sources in the old directory structure rather than the new one). This is useful if you want to continue working with both Studio and Eclipse on the same codebase.
        • If your project is doing a lot of Eclipse-specific directory mappings (with path variables, linked resources etc) it's possible that the Android Studio importer can not resolve the paths properly; in that case, try the Eclipse exporter (but please also file a bug so we can fix the importer).
      Importing Directly into Android Studio
      To import into Android Studio, select File > Import, and then select the directory containing your Eclipse ADT project. A wizard will open and guide you through the rest of the import process. When the project import has finished, it will open up a file called "import-summary.txt" which lists all the steps taken during import and suggestions for next steps. For example, it may note files that were not migrated, it may note missing components in your SDK install, and so on.
      Exporting from Eclipse
      Open the project in Eclipse, and from there, export the project. 

      Choose the Gradle option
      Proceed through the wizard. When you are done, you can import the build.gradle file into Android Studio.