How to shrink code - 65k method limit in dex

2019-01-03 04:43发布

I have a rather large Android app that relies on many library projects. The Android compiler has a limitation of 65536 methods per .dex file and I am surpassing that number.

There are basically two paths you can choose (at least that I know of) when you hit the method limit.

1) Shrink your code

2) Build multiple dex files (see this blog post)

I looked into both and tried to find out what was causing my method count to go so high. The Google Drive API takes the biggest chunk with the Guava dependency at over 12,000. Total libs for Drive API v2 reach over 23,000!

My question I guess is, what do you think I should do? Should I remove Google Drive integration as a feature of my app? Is there a way to shrink the API down (yes, I use proguard)? Should I go the multiple dex route (which looks rather painful, especially dealing with third party APIs)?

12条回答
冷血范
2楼-- · 2019-01-03 04:45

For Eclipse users not using Gradle, there are tools that will break down the Google Play Services jar and rebuild it with only the parts you want.

I use strip_play_services.sh by dextorer.

It can be difficult to know exactly which services to include because there are some internal dependencies but you can start small and add to the configuration if it turns out that needed things are missing.

查看更多
淡お忘
3楼-- · 2019-01-03 04:47

you can use the multidex support library for that, To enable multidex

1) include it in dependencies:

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

2) Enable it in your app:

defaultConfig {
    ...
    minSdkVersion 14
    targetSdkVersion 21
    ....
    multiDexEnabled true
}

3) if you have a application class for your app then Override the attachBaseContext method like this:

package ....;
...
import android.support.multidex.MultiDex;

public class MyApplication extends Application {
  ....
   @Override
   protected void attachBaseContext(Context context) {
    super.attachBaseContext(context);
    MultiDex.install(this);
   }
}

4) if you don't have a application class for your application then register android.support.multidex.MultiDexApplication as your application in your manifest file. like this:

<application
    ...
    android:name="android.support.multidex.MultiDexApplication">
    ...
</application>

and it should work fine!

查看更多
Explosion°爆炸
4楼-- · 2019-01-03 04:48

If using Google Play Services, you may know that it adds 20k+ methods. As already mentioned, Android Studio has the option for modular inclusion of specific services, but users stuck with Eclipse have to take modularisation into their own hands :(

Fortunately there's a shell script that makes the job fairly easy. Just extract to the google play services jar directory, edit the supplied .conf file as needed and execute the shell script.

An example of its use is here.

Just like he said, I replaces compile 'com.google.android.gms:play-services:9.0.0' just with the libraries that I needed and it worked.

查看更多
劫难
5楼-- · 2019-01-03 04:49

In versions of Google Play services prior to 6.5, you had to compile the entire package of APIs into your app. In some cases, doing so made it more difficult to keep the number of methods in your app (including framework APIs, library methods, and your own code) under the 65,536 limit.

From version 6.5, you can instead selectively compile Google Play service APIs into your app. For example, to include only the Google Fit and Android Wear APIs, replace the following line in your build.gradle file:

compile 'com.google.android.gms:play-services:6.5.87'

with these lines:

compile 'com.google.android.gms:play-services-fitness:6.5.87'
compile 'com.google.android.gms:play-services-wearable:6.5.87'

for more reference, you can click here

查看更多
做自己的国王
6楼-- · 2019-01-03 04:51

If using Google Play Services, you may know that it adds 20k+ methods. As already mentioned, Android Studio has the option for modular inclusion of specific services, but users stuck with Eclipse have to take modularisation into their own hands :(

Fortunately there's a shell script that makes the job fairly easy. Just extract to the google play services jar directory, edit the supplied .conf file as needed and execute the shell script.

An example of its use is here.

查看更多
爱情/是我丢掉的垃圾
7楼-- · 2019-01-03 04:56

Play Services 6.5+ helps: http://android-developers.blogspot.com/2014/12/google-play-services-and-dex-method.html

"Starting with version 6.5, of Google Play services, you’ll be able to pick from a number of individual APIs, and you can see"

...

"this will transitively include the ‘base’ libraries, which are used across all APIs."

This is good news, for a simple game for example you probably only need the base, games and maybe drive.

"The complete list of API names is below. More details can be found on the Android Developer site.:

  • com.google.android.gms:play-services-base:6.5.87
  • com.google.android.gms:play-services-ads:6.5.87
  • com.google.android.gms:play-services-appindexing:6.5.87
  • com.google.android.gms:play-services-maps:6.5.87
  • com.google.android.gms:play-services-location:6.5.87
  • com.google.android.gms:play-services-fitness:6.5.87
  • com.google.android.gms:play-services-panorama:6.5.87
  • com.google.android.gms:play-services-drive:6.5.87
  • com.google.android.gms:play-services-games:6.5.87
  • com.google.android.gms:play-services-wallet:6.5.87
  • com.google.android.gms:play-services-identity:6.5.87
  • com.google.android.gms:play-services-cast:6.5.87
  • com.google.android.gms:play-services-plus:6.5.87
  • com.google.android.gms:play-services-appstate:6.5.87
  • com.google.android.gms:play-services-wearable:6.5.87
  • com.google.android.gms:play-services-all-wear:6.5.87
查看更多
登录 后发表回答