A simple android gradle plugin to use the patterns of package to smart split the specified classes to multi dex.
Also supports android gradle plugin 2.2.0 multidex.
Solve android studio enable the native multidex feature, but there will be too many classes in main dex. (See Features 7)
Notes: Because instant-run of 2.0.0 above is incompatible with multidex, DexKnife is auto disabled when instant-run mode.
It will auto enable when disabled instant-run or in packaging release.(minsdk < 21)
1.6.1: Compatible with android gradle plugin 2.3.0, auto disable when build with ART-Runtime (See Features 8).
1.6.0: Modify: When only -keep is configured, only keep the specified classes.
1.5.9: Compatible with some ancient version of gradle and android gradle plugin.
1.5.8: Compatible with gradle 3.2, fixed use of only support-split and support-keep resulting in an extra large number of classes.
1.5.7: fixed support-split and support-keep are not work. (修复support-split/support-keep无效的bug)
1.5.6: Experimentally compatible with java 1.7, fix nothing is selected when only -keep. (实验性的支持java 1.7,修复但只有keep选项时没有类被选中)
1.5.5: support individual filter for suggest maindexlist. (单独的maindexlist过滤设置)
1.5.5.alpha: Experimentally compatible with android gradle plugin on 2.2.0. (实验性的支持 2.2.0 plugin)
1.5.4: auto disabled when instant run mode.(instant run 模式时自动禁用DexKnife)
1.5.3: add some track logs and skip DexKnife when jarMerging is null.(增加跟踪日志,并在jarMerging为null跳过处理)
1.5.2: fixed the include and exclude path, and supports filtering single class.(修复include和exclude, 并支持过滤单个类)
1.5.1.exp: Experimentally compatible with android gradle plugin on 2.1.0 (实验性的支持 2.1.0 plugin)
1.5.1: fixed the proguard mode
Features
DexKnife just converts the wildcards of class path to maindexlist.txt, does not participate in other compilation process. It is not automatic tools, you need to have a understanding of the maindexlist features.
If the class can not be found (ie class no def / found) at runtime, enable DexKnife's log function, debug the config of dexKnife and check the config ProGuard. Verify the generated maindexlist.txt match your config. Do not split the classes in the Application class into second dex. (Even if you manually configure the maindexlist will be such a problem.)
DexKnife can only explicitly specify the classes of main dex, can not specify the classes of after the second dex (limitation of dex's param maindexlist). If you need to completely configure the main dex manually, use:
-donot-use-suggest
-split **
-keep android.support.multidex.** # keep multidex lib
-keep # wildcards of other keeping classes, and the count of idx don't overflow 65535
DexKnife does not have dependency detection and requires you to configure it manually because DexKnife does not know your project requirements.
DexKnife uses the original classpath as the configuration, not the obfuscated classpath.
the count of ID that generated by -keep can not overflow 65535, otherwise there will be error of too many class.
If you use the android gradle plugin's native multidex, but the declaration in the manifest is too much, resulting in the number of methods and variables are still overflow, or can not be packaged. You can simply use -suggest-split to move some of the classes in the suggest list out of the main dex.
minsdk < 21. If minsdk >= 21, the android gradle plugin will build with ART-Runtime, MainDexList isn't necessary, DexKnife is auto disable. In debug mode with Android Gradle plugin >= 2.3.0, minsdk is associated with min(Target running device, TargetSdk). Make sure your MinSdkVersion < 21, DexKnife will auto enable in release mode if conditions are compatible.
Usage
1.In your project's build.gradle, buildscript.
buildscript {
....
dependencies {
....
classpath 'com.android.tools.build:gradle:2.3.0' // or other
classpath 'com.ceabie.dextools:gradle-dexknife-plugin:1.6.1'
}
}
please make sure gradle version is compatible with the android gradle plugin, otherwise it can causes some sync error, such as:
Gradle sync failed: Unable to load class 'com.android.builder.core.EvaluationErrorReporter'.
2.Create a 'dexknife.txt' in your App's module, and config the patterns of classes path that wants to put into sencond dex.
(The rest of any classes that is not marked split will be in miandexlist)
Patterns may include:
'*' to match any number of characters
'?' to match any single character
'**' to match any number of directories or files
Either '.' or '/' may be used in a pattern to separate directories.
Patterns ending with '.' or '/' will have '**' automatically appended.
'#' is the comment, config is disabled when '#' adds on line start.
# Global filter, don't apply with suggest maindexlist if -filter-suggest is DISABLE.
# this path will to be split to second dex.
android.support.v?.**
# if you want to keep some classes in main dex, use '-keep'.
-keep android.support.v4.view.**
# you can keep single class in main dex, end with '.class', use '-keep'.
-keep android.support.v7.app.AppCompatDialogFragment.class
# do not use suggest of the maindexlist that android gradle plugin generate.
-donot-use-suggest
# the global filter apply with maindexlist, if -donot-use-suggest is DISABLE.
-filter-suggest
# Notes: Split dex until the dex's id > 65536. --minimal-main-dex is default.
-auto-maindex # default is not used.
# dex additional parameters, such as --set-max-idx-number=50000
# if number is too small, it will cause DexException: Too many classes in --main-dex-list, main dex capacity exceeded
-dex-param --set-max-idx-number=50000
# log the main dex classes.
-log-mainlist
# log the filter classes of suggest maindexlist, if -filter-suggest is enabled..
-log-filter-suggest
#the filter log。Recommend;Global;true;false
-log-filter
# if you only filter the suggest maindexlist, use -suggest-split and -suggest-keep.
# Global filter will merge into them if -filter-suggest is ENABLE at same time.
-suggest-split **.MainActivity2.class
-suggest-keep android.support.multidex.**
Note: if you want to filter the inner classes, use $*, such as: SomeClass$*.class
3.add to your app's build.gradle, add this line:
apply plugin: 'com.ceabie.dexnkife'
and then, set your app
multiDexEnabled true
Notes: You want to set 'multiDexEnabled true' in 'defaultConfig' or 'buildTypes', otherwise ineffective.
如果出现运行时类找不到(i.e. class no def/found),请打开DexKnife的log功能,比对调试下DexKnife或ProGuard配置,并检查生成的maindexlist是否匹配你的配置。不要将在Application中使用到的类,分到第二个dex中。(即使不使用DexKnife,手动配置maindexlist也会出现这样的问题)
Patterns may include:
'*' to match any number of characters
'?' to match any single character
'**' to match any number of directories or files
Either '.' or '/' may be used in a pattern to separate directories.
Patterns ending with '.' or '/' will have '**' automatically appended.
Copyright (C) 2017 ceabie (http://blog.csdn.net/ceabie)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
请发表评论