How to avoid DEX 64K LIMIT by importing the right library
Asked Answered
C

6

11

I had this issue where I overflow the 64k method limit in Dalvik when compiling all the library I used. I started to have this issue when I imported the Support Library, as some are already contained in others, it ended up overflowing the limit.

Is there a way to verify if a library is unused in the current project or already imported through another library dependencies?

Currently, I'm excluding those I know for sure but it seems weird to have to do this by hand.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:multidex:1.0.1'
    compile "com.android.support:percent:${supportLibVersion}"
    compile("com.android.support:design:${supportLibVersion}") {
        exclude module: 'support-v4'
    }
    compile("com.android.support:cardview-v7:${supportLibVersion}") {
        exclude module: 'support-v4'
    }

    compile('com.github.nkzawa:socket.io-client:0.4.1') {
        exclude group: 'org.json', module: 'json'
    }
    compile('com.astuetz:pagerslidingtabstrip:1.0.1') {
        exclude module: 'support-v4'
    }
//...
}

Solutions so far:

  1. Use a Gradle plugin – We wrote an extremely easy to use Gradle plugin some time back that lists the number of methods by package along with the total number. You can find more information about it here.
  2. www.methodscount.com – Wondering how many methods a particular library will add to your application? Just enter the ‘compile’ statement on this website and it’ll tell you it’s method count, dependencies, JAR size and DEX size.
  3. Android Studio Plugin – This excellent plugin shows the method count of each dependency right inside Android Studio.
  4. Using the MultiDex Support Library If you are using Android Studio, the process is very straight-forward. If you are not, I highly recommend migrating, as Google may soon drop support for the Eclipse ADT plugin and the old Ant based build system.

Step 1

Add the dependency for the MultiDex support library in your build.gradle

dependencies { 
... 
   compile 'com.android.support:multidex:' 
   ... 
}

Step 2

Enable multi-dexing by setting the multiDexEnabled flag in the buildType or productFlavor section of your gradle configuration.

defaultConfig { 
   ... 
multiDexEnabled true 
... 
}

Now depending on your project, you have 3 options:

If you haven’t created your own Application class, simply declare android.support.multidex.MultiDexApplication as your application class in AndroidManifest.xml

   .... 
   android:name="android.support.multidex.MultiDexApplication" 
   ... 

If you already have your own Application class, make it extend android.support.multidex.MultiDexApplication instead of android.app.Application

If your Application class is extending some other class and you don’t want to or can’t change it, override attachBaseContext() as shown below:

public class MyApplication extends FooApplication { 
   @Override 
   protected void attachBaseContext(Context base) { 
      super.attachBaseContext(base); 
      MultiDex.install(this); 
   } 
}
Constabulary answered 12/5, 2016 at 15:52 Comment(3)
You can use methodscount.com. It list dependencies for each library and shows the method count for each dependency. There is a gradle plugin too.Eversion
That website is magic! Thx manConstabulary
@Constabulary did you check my answer ?Withy
D
11

You can open the terminal and run command gradlew app:dependencies to test which dependencies are already included in the others as transitive dependencies for your project along with the respective versions of each.

For example I got the following dependency chart for one of my projects for the com.android.support:design library I used:

+--- com.android.support:design:23.3.0
|    +--- com.android.support:appcompat-v7:23.3.0
|    |    +--- com.android.support:support-vector-drawable:23.3.0
|    |    |    \--- com.android.support:support-v4:23.3.0
|    |    |         \--- com.android.support:support-annotations:23.3.0
|    |    +--- com.android.support:animated-vector-drawable:23.3.0
|    |    |    \--- com.android.support:support-vector-drawable:23.3.0 (*)
|    |    \--- com.android.support:support-v4:23.3.0 (*)
|    +--- com.android.support:support-v4:23.3.0 (*)
|    \--- com.android.support:recyclerview-v7:23.3.0
|         +--- com.android.support:support-v4:23.3.0 (*)
|         \--- com.android.support:support-annotations:23.3.0
Devotion answered 18/5, 2016 at 11:41 Comment(6)
And how do I remove transitive dependency or duplicates?Constabulary
Your approach to exclude group / module is correct. Only you need to identify the (transitive) dependencies required for you app (along with their versions) and exclude the ones not required. As the next step you can use Proguard to remove unused classes, fields, methods, and attributes from your packaged app, including those from included code libraries (making it a valuable tool for working around the 64k reference limit). Please see developer.android.com/studio/build/shrink-code.html for details.Devotion
When I try to exclude 'support-v4' from com.android.support:design:23.3.0, it's still there when doing gradlew app:dependencies... Why so?Constabulary
Excluding support-v4 from design might not be such a good idea. Let that part optimized using proguard. But support-v4 might be a transitive dependency through any of the other dependency also.Devotion
Good luck trying to c̶o̶m̶p̶i̶l̶e̶ run without support-v4.Studied
almost everything related to support depends on v4... appcompat, v7, ...Orndorff
W
9

hey you can try my trick, it might be useful for you

  1. First of all you should avoid external libraries. Like in that libraries have same dependencies. So, try to merge that library with android application code. Due to this save much space for methods.

  2. Use useful dependencies and libraries like if you want google play services then include only useful services not all.See example

    compile "com.google.android.gms:play-services-location:9.4.0"
    compile "com.google.android.gms:play-services-maps:9.4.0" 
    

Avoid this

compile 'com.google.android.gms:play-services:9.4.0'
  1. Remove unwanted dependencies.Use very chooseable dependencies in your code.

  2. If all things not work really well then use multidex in your code.But it create Multiple dex files.So, your code will take much time for compilation.

Thanks hope this will help you.

Withy answered 1/10, 2016 at 16:46 Comment(2)
I don't understand your number 1? You recommend to avoid using external library?Constabulary
Yes that means if you used some modules and that contain same dependencies like v7 and you used same dependencies in your app side. So, it's better to use that modules in your code. This way you avoid duplication of libraries and save much spcae.Someetime it happened but mostly we are ignore this thing.Withy
I
4
 defaultConfig
 {    
     multiDexEnabled true 
 }

 dependencies {
     compile 'com.android.support:multidex:1.0.0'
 }

and also add this method into your application class

@Override
protected void attachBaseContext(Context newBase) {

    super.attachBaseContext(newBase);

    MultiDex.install(this);
}
Immemorial answered 24/5, 2016 at 11:26 Comment(0)
S
2

Click On File Then Click On Project Structure Click On app on the left bottom of the popup. You will see multiple Tabs click on Dependencies Tab Then Click On plus at right top chose Library dependency search your desire Library it will show Those Libraries which are available in your IDE

Sicken answered 22/5, 2016 at 9:32 Comment(0)
F
2

Though using Multidex Support Library library solves the problem, it is not perfect. The first thing to do should be to determine how many methods your app currently has and how many of them are being added by each of its dependencies. Earlier you had to do this manually, but now there are a bunch of tools available:

  1. Use a Gradle plugin – This is an extremely easy to use Gradle plugin some time back that lists the number of methods by package along with the total number. You can find more information about it here.
  2. www.methodscount.com – Just enter the ‘compile’ statement on this website and it’ll tell you it’s method count, dependencies, JAR size and DEX size.
  3. Android Studio Plugin – This excellent plugin shows the method count of each dependency right inside Android Studio.

Irrespective of what you tool you end up using, use the information it provides to perform an audit of your app’s dependencies. You should look for unused libraries or ones that can be minimized or even replaced with your own simpler solution. If you are not using Proguard to remove unused code, first enable it and see if it solves the problem(Check this). Using Proguard is well… not fun, but once you manage to make it work properly, it’ll significantly reduce the method count. If all else fails, you’ll have to use the MultiDex support library.

Check out gradle task to strip unused packages on Google Play Services library.

Conclusion

While the Multidex Support Library fixes the DEX 64K problem in most cases, it should be treated as a last resort. Before attempting to use it, you should audit your project for unwanted dependencies and remove as much unused code as possible using ProGuard. If you do go ahead and use it, make sure you test your app on older devices.

Hope this will help you.

Fahy answered 3/10, 2016 at 11:53 Comment(0)
K
0

is there a new way in 2022 to easily count methods/manage proguard rules?

Gradle dexinfo plugin ==> No changes since 2016

Android studio plugin ==> No changes since 2016

www.methodscount.com ==> Offline: returns a web page with eh, let's say there's nothing about development there [Forbidden to -18]

Kieserite answered 27/9, 2022 at 7:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.