From 80692147737d51910a3dc1c12481f3f91fc0585f Mon Sep 17 00:00:00 2001 From: Artist Date: Mon, 28 Nov 2016 21:33:29 +0800 Subject: [PATCH 01/14] Update dexknife.txt --- DexKnifePlugin/app/dexknife.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DexKnifePlugin/app/dexknife.txt b/DexKnifePlugin/app/dexknife.txt index a377126..33e281b 100644 --- a/DexKnifePlugin/app/dexknife.txt +++ b/DexKnifePlugin/app/dexknife.txt @@ -24,7 +24,7 @@ # 表明限制的方法数小于main dex的必要方法数,调大到合适数值即可 -dex-param --set-max-idx-number=4000 -# 不进行dex分包, 直到 dex 的id数量超过 65536.(设置自动执行分包策略) +# 注释掉将执行自定义dex分包,否则执行默认分包. #-auto-maindex # 显示miandex的日志. From ff9d4eb8cd1adf21f23f703a76cc9a60e0f664e1 Mon Sep 17 00:00:00 2001 From: Artist Date: Mon, 28 Nov 2016 21:35:17 +0800 Subject: [PATCH 02/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da9dcf6..9a9c0a0 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,7 @@ dexKnife{ # 表明限制的方法数小于main dex的必要方法数,调大到合适数值即可 -dex-param --set-max-idx-number=4000 -# 不进行dex分包, 直到 dex 的id数量超过 65536.(设置自动执行分包策略) +# 注释掉将执行自定义dex分包,否则执行默认分包. #-auto-maindex # 显示miandex的日志. From cbc40ef5c4df2100110978420fab4aa38dfd8d22 Mon Sep 17 00:00:00 2001 From: tangxiaolv Date: Tue, 21 Feb 2017 10:02:00 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E5=85=BC=E5=AE=B9Gradle=203.2+?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DexKnifePlugin/app/build.gradle | 25 ++- DexKnifePlugin/app/mutidex.jks | Bin 0 -> 2205 bytes .../app/src/main/res/values/strings.xml | 2 +- DexKnifePlugin/build.gradle | 5 +- .../dexknife-plus/gradle.properties | 2 +- .../com/ceabie/dexknife/DexSplitTools.java | 192 +++++++++++------- .../ceabie/dexknife/SplitToolsFor150.groovy | 3 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- README.md | 4 +- 9 files changed, 142 insertions(+), 93 deletions(-) create mode 100644 DexKnifePlugin/app/mutidex.jks diff --git a/DexKnifePlugin/app/build.gradle b/DexKnifePlugin/app/build.gradle index 6a761f9..aa8d0ba 100644 --- a/DexKnifePlugin/app/build.gradle +++ b/DexKnifePlugin/app/build.gradle @@ -2,18 +2,28 @@ apply plugin: 'com.android.application' apply plugin: 'dexknifePlus' android { - compileSdkVersion Integer.parseInt(project.COMPILE_SDK_VER) - buildToolsVersion project.BUILD_TOOLS_VER + compileSdkVersion 23 + buildToolsVersion '23.0.3' defaultConfig { - minSdkVersion Integer.parseInt(project.MIN_SDK_VER) - targetSdkVersion Integer.parseInt(project.TARGET_SDK_VERSION) + minSdkVersion 14 + targetSdkVersion 23 versionCode 1 versionName "1.0" multiDexEnabled true } + //签名 + signingConfigs { + key { + storeFile file('mutidex.jks') + storePassword '123456' + keyAlias 'king' + keyPassword '123456' + } + } + productFlavors{ dev{ @@ -26,12 +36,13 @@ android { buildTypes { release { - minifyEnabled false + minifyEnabled true + signingConfig signingConfigs.key proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { -// minifyEnabled true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } @@ -48,7 +59,7 @@ dexKnife{ //1.如果没有可选参数,将根据enabled决定是否分包。 //2.如果有可选参数,需满足必选参数和可选参数的条件才允许分包 productFlavor 'mock' - buildType 'debug' + //buildType 'debug' /* *eg:当前productFlavors = dev,buildType = debug, diff --git a/DexKnifePlugin/app/mutidex.jks b/DexKnifePlugin/app/mutidex.jks new file mode 100644 index 0000000000000000000000000000000000000000..ed545447f3abbbde6ebe83f62e1bc553f118224b GIT binary patch literal 2205 zcmcK5`8(7L7Xa|t3`T=Y*^LZZjQElmB-B&}V+j+(C6RrvZbCI?vV}-DWbPC)wx-5% zZ^{~BwAqcFFxd(jA#2yu`@YX}`vcw|&JUlT&U2RMob9>oIS>d0*$ME^fcg6ddGCPi zN+x=MKmuTZ3flri;Rq}o3pa98x5<)Ld0ivx$|wBml~3EU#;FL8>~?hQC!iGj7oaamg;y6bNW$1 z$D6O8l%}f8NoMz0K5BGr(ZU`E^vkAIk)(!t%AwxsUF?>17KZ~Y3Hc}tx`#(+3perl z*hO*)Pi1chYojM_HlgkC2Nu-XR9A~E9LLN3>P=VczlQ!uJTvaR@$M;LJhdmjKfI$_ z%BEx*BN8n+TM-!$x>3E?Ex7RdlP23QeoijE{D`$SVh%(sMPxsWdhTogA z<(*2~V&CcuSVYFMwy%#_qW89_lBMKHjxCQpN>Hj=QTHw93x|j{T-=Mh{*rt2;s^{R z;DTEGdthB2;X&7u8)I^0Pm0wa9?kg>N-{{>m{o4HIl{rCPX$%zjX$>xRJcOmW5v>a zv(|eMzx!lWeq+d%-Pdlv;KaClkz6o%gppphjn+qo+Nuc$6kniZRK>cdJ%#8hTg`pF z(NbL_+a;{gxS8#+;#wwpLy4?jX4JM1Wj{X}&O@hjv|O$MHA0JQ<_TO7;yfa!=*T^E zYO+4``U-0AeVNqJrFQPX@p!Fi+YL&oP(qX8f`4H-2j4LsU|2gBTxh@=ZTU<(tm5iM zYq|I==-OnvPF_3vs=XD{yh`1vf$N}qsiP@Ap{AKemu@a15@L+l5%0zYvGv@RE#_$X zogkB;g}GSh`>m(|@kcYnhijSwcs@@yjpd9KBm^*Cr3!SKVmx$n*?%yI!$&qpB2wbM zHzzcgO#?k~VXJtFdXI=v6$-ls>ojNTFrH!pGz8MPZ)Z*$o*b0v!TgSjY{}X-;Vjie z3R4ULspTzbe*MFt3u84g`40?UT&25r{u#Gu{xoX^CvbW8dl{EmP=0K#qMKD?+?vzA z-&h6A&|sn4m3QB_Zu6TrZId$_H0eOJNP?40?gX3qXd$@oo?(B4BlgnFlDsycySzEx=s z8N#+^mKja3>InN^bbZ3+Nuv4i@+{OtPY>KkUV%km?{E4SD}B~pzFEp+(rL8^;op`(d{rV}KoBoVb1RwYuN64td8)Q4FS# zZ(+7^?ur!ss_(9@h#zTDy)FH9xwDSe&nCinj+nDIMPIKzHvCu(aZ>HmP?HlicUBt} z-ZyCveH&Z1u!2<;d zoJL24SgT_Y8II2ER;SsFwMlU@m(?hKOPZuy9!mme9r^mXb>eY5;nyuR2;%c|vDgK0I56)$HmC zrd%Bo3+Melb;w-A{F&8o6dm#;u!-Uz_pD;UWv;HyEavA~6mZly3h0AC&~pG4Y6nmu zhS^XE7y^MI@J^2aBwSc6)+}}v2?mP@fB>=<5)gqy9bjFDVIWGSSMHlVF_^uPSS=B9!%|1Nds5kRS6F%UonBOp{T7!)nT za2|;aJ=f5ff3Q(}q+H)-{qm0qH1TcD^sI4y1NN|l#EWria2jT-Bnw_m``jw{rt0DJ zgYY4X>kgj$i2)-OS}sjGhQ#Y05qGl70eyG#^-dW$RPBO^NUfg~H`Kh+d%-#@*?%^eHW-3RxcJY%+- zVoPCUq~qOgaPA^~P8ptwLfM5bNnL3^q3F#fi6wq#p6sF(?K6q4AEzxi$+P1;@Y#DP ze>E2Olz4V$Lim{6$l7y6m4o|Hxa~?2+M)A*)*bCgZK_;L=}Atkt)LdI5+P792>e(H zPy`fqrmr9hlZ5R-GA#m2w@v5Q%P)~?x6xCiCXwr9A77HTbaf=Aw+(VTxB&X=q(>Jp6p|7jQ$`Yy&!B6*!LWo#;p^N?0O@& zxASTGXSZyIn{n|*yT72)m)@K2*GZv%Mz8Cdhb-lL@4~G!xaq2PMX>BcPRecNN#q{$6viY?)=JCVIi`%7S88=}yHKa-{XlT!{gOA! z#x}FohMwdd0MU=j?YCJjS&~-n&piFZ*Q+(`=H^VpnzKp$4+?J?#+O`vDG}~&9$Q^5 zRpa1juRIp7<8xl~)`15lmu`Iv{D8_n!%Ut9CJCTreF1SC;L*|jEMv@;N~bMr4Ardl Klb){+DE - demo + MultiDexPluginApp Hello world! Settings diff --git a/DexKnifePlugin/build.gradle b/DexKnifePlugin/build.gradle index d88678c..0e9a366 100644 --- a/DexKnifePlugin/build.gradle +++ b/DexKnifePlugin/build.gradle @@ -1,12 +1,13 @@ buildscript { repositories { + //maven { url uri('./repo') } jcenter() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.0' - classpath 'com.library.tangxiaolv:dexknife-plus:1.0.1' + classpath 'com.android.tools.build:gradle:2.2.3' + classpath 'com.library.tangxiaolv:dexknife-plus:1.0.3' } } diff --git a/DexKnifePlugin/dexknife-plus/gradle.properties b/DexKnifePlugin/dexknife-plus/gradle.properties index 184c457..e492aa4 100644 --- a/DexKnifePlugin/dexknife-plus/gradle.properties +++ b/DexKnifePlugin/dexknife-plus/gradle.properties @@ -1,6 +1,6 @@ #Gradle:groupId:libraryName:publicVersion LOCAL_VERSION=0.0.5 -PUBLIC_VERSION=1.0.1 +PUBLIC_VERSION=1.0.3 GROUP_ID=com.library.tangxiaolv #Modelһ LIBRARY_NAME=dexknife-plus diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java index a545af3..860d4af 100644 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java +++ b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.ceabie.dexknife; import org.gradle.api.Project; import org.gradle.api.file.FileTreeElement; +import org.gradle.api.specs.NotSpec; +import org.gradle.api.specs.OrSpec; import org.gradle.api.specs.Spec; import org.gradle.api.specs.Specs; import org.gradle.api.tasks.util.PatternSet; @@ -81,27 +82,27 @@ protected static void endDexKnife() { System.out.println("DexKnife Finished: " + time); } - public static boolean processMainDexList(Project project, boolean minifyEnabled, - File mappingFile, - File jarMergingOutputFile, File andMainDexList, - DexKnifeConfig dexKnifeConfig) throws Exception { + public static boolean processMainDexList(Project project, boolean minifyEnabled, File mappingFile, + File jarMergingOutputFile, File andMainDexList, + DexKnifeConfig dexKnifeConfig) throws Exception { if (!minifyEnabled && jarMergingOutputFile == null) { - System.out.println( - "DexKnife Error: jarMerging is Null! Skip DexKnife. Please report All Gradle Log."); + System.out.println("DexKnife Error: jarMerging is Null! Skip DexKnife. Please report All Gradle Log."); return false; } - return genMainDexList(project, minifyEnabled, mappingFile, jarMergingOutputFile, - andMainDexList, dexKnifeConfig); + try { + return genMainDexList(project, minifyEnabled, mappingFile, jarMergingOutputFile, + andMainDexList, dexKnifeConfig); + } catch (Exception e) { + e.printStackTrace(); + } + + return false; } /** * get the config of dex knife - * - * @param project project - * @return DexKnifeConfig - * @throws Exception exception */ protected static DexKnifeConfig getDexKnifeConfig(Project project) throws Exception { BufferedReader reader = new BufferedReader(new FileReader(project.file(DEX_KNIFE_CFG_TXT))); @@ -188,16 +189,15 @@ protected static DexKnifeConfig getDexKnifeConfig(Project project) throws Except addParams.add(DEX_MINIMAL_MAIN_DEX); } + // 使用ADT建议的mainlist if (dexKnifeConfig.useSuggest) { + + // 将全局过滤应用到建议的mainlist if (dexKnifeConfig.filterSuggest) { splitSuggest.addAll(splitToSecond); keepSuggest.addAll(keepMain); } - // for (String s : splitSuggest) { - // System.out.println("Suggest: " + s); - // } - if (!splitSuggest.isEmpty() || !keepSuggest.isEmpty()) { dexKnifeConfig.suggestPatternSet = new PatternSet() .exclude(splitSuggest) @@ -206,9 +206,6 @@ protected static DexKnifeConfig getDexKnifeConfig(Project project) throws Except } if (!splitToSecond.isEmpty() || !keepMain.isEmpty()) { - // for (String s : splitToSecond) { - // System.out.println(s); - // } dexKnifeConfig.patternSet = new PatternSet() .exclude(splitToSecond) .include(keepMain); @@ -259,12 +256,12 @@ private static Spec getMaindexSpec(PatternSet patternSet) { } if (includeSpec != null && excludeSpec != null) { - maindexSpec = Specs.or(includeSpec, Specs.not(excludeSpec)); + maindexSpec = new OrSpec<>(includeSpec, new NotSpec<>(excludeSpec)); } else { if (excludeSpec == null) { maindexSpec = Specs.satisfyAll(); } else { - maindexSpec = Specs.not(excludeSpec); + maindexSpec = new NotSpec<>(excludeSpec); } } } @@ -276,17 +273,23 @@ private static Spec getMaindexSpec(PatternSet patternSet) { return maindexSpec; } + + private static boolean isPatternSetEmpty(PatternSet patternSet) { + return patternSet.getExcludes().isEmpty() && patternSet.getIncludes().isEmpty() + && patternSet.getExcludeSpecs().isEmpty() && patternSet.getIncludeSpecs().isEmpty(); + } + /** * generate the main dex list */ private static boolean genMainDexList(Project project, boolean minifyEnabled, - File mappingFile, File jarMergingOutputFile, - File andMainDexList, DexKnifeConfig dexKnifeConfig) throws Exception { + File mappingFile, File jarMergingOutputFile, + File andMainDexList, DexKnifeConfig dexKnifeConfig) throws Exception { System.out.println(":" + project.getName() + ":genMainDexList"); - // get the adt's maindexlist - HashSet mainCls = null; + // 1.get the adt's maindexlist + Map adtMainClasses = null; if (dexKnifeConfig.useSuggest) { PatternSet patternSet = dexKnifeConfig.suggestPatternSet; @@ -294,31 +297,43 @@ private static boolean genMainDexList(Project project, boolean minifyEnabled, patternSet = dexKnifeConfig.patternSet; } - mainCls = getAdtMainDexClasses(andMainDexList, patternSet, - dexKnifeConfig.logFilterSuggest); System.out.println("DexKnife: use suggest"); + adtMainClasses = getAdtMainDexClasses(andMainDexList, patternSet, dexKnifeConfig.logFilterSuggest); } File keepFile = project.file(MAINDEXLIST_TXT); keepFile.delete(); - ArrayList mainClasses = null; - if (minifyEnabled) { - System.err.println("DexKnife: From Mapping"); - // get classes from mapping - mainClasses = getMainClassesFromMapping(mappingFile, dexKnifeConfig.patternSet, - mainCls); + // 2.process the global filter + List mainClasses = null; + if (dexKnifeConfig.patternSet == null || isPatternSetEmpty(dexKnifeConfig.patternSet)) { + // only filter the suggest list + if (adtMainClasses != null && adtMainClasses.size() > 0) { + mainClasses = new ArrayList<>(); + Set> entries = adtMainClasses.entrySet(); + for (Map.Entry entry : entries) { + if (entry.getValue()) { + mainClasses.add(entry.getKey()); + } + } + } } else { - System.out.println("DexKnife: From MergedJar: " + jarMergingOutputFile); - if (jarMergingOutputFile != null) { - // get classes from merged jar - mainClasses = getMainClassesFromJar(jarMergingOutputFile, dexKnifeConfig.patternSet, - mainCls); + if (minifyEnabled) { + System.err.println("DexKnife: From Mapping"); + // get classes from mapping + mainClasses = getMainClassesFromMapping(mappingFile, dexKnifeConfig.patternSet, adtMainClasses); } else { - System.err.println("DexKnife: The Merged Jar is not exist! Can't be processed!"); + System.out.println("DexKnife: From MergedJar: " + jarMergingOutputFile); + if (jarMergingOutputFile != null) { + // get classes from merged jar + mainClasses = getMainClassesFromJar(jarMergingOutputFile, dexKnifeConfig.patternSet, adtMainClasses); + } else { + System.err.println("DexKnife: The Merged Jar is not exist! Can't be processed!"); + } } } + // 3.create the miandexlist if (mainClasses != null && mainClasses.size() > 0) { BufferedWriter writer = new BufferedWriter(new FileWriter(keepFile)); @@ -339,13 +354,24 @@ private static boolean genMainDexList(Project project, boolean minifyEnabled, throw new Exception("DexKnife Warning: Main dex is EMPTY ! Check your config and project!"); } + /** + * Gets main classes from jar. + * + * @param jarMergingOutputFile the jar merging output file + * @param mainDexPattern the main dex pattern + * @param adtMainCls the filter mapping of suggest classes + * @return the main classes from jar + * @throws Exception the exception + * @author ceabie + */ private static ArrayList getMainClassesFromJar( - File jarMergingOutputFile, PatternSet mainDexPattern, HashSet mainCls) + File jarMergingOutputFile, PatternSet mainDexPattern, Map adtMainCls) throws Exception { ZipFile clsFile = new ZipFile(jarMergingOutputFile); Spec asSpec = getMaindexSpec(mainDexPattern); ClassFileTreeElement treeElement = new ClassFileTreeElement(); + // lists classes from jar. ArrayList mainDexList = new ArrayList<>(); Enumeration entries = clsFile.entries(); while (entries.hasMoreElements()) { @@ -355,8 +381,7 @@ private static ArrayList getMainClassesFromJar( if (entryName.endsWith(CLASS_SUFFIX)) { treeElement.setClassPath(entryName); - if (asSpec.isSatisfiedBy(treeElement) - || (mainCls != null && mainCls.contains(entryName))) { + if (isAtMainDex(adtMainCls, entryName, treeElement, asSpec)) { mainDexList.add(entryName); } } @@ -370,23 +395,23 @@ private static ArrayList getMainClassesFromJar( /** * Gets main classes from mapping. * - * @param mapping the mapping file + * @param mapping the mapping file * @param mainDexPattern the main dex pattern - * @param mainCls the main cls + * @param adtMainCls the filter mapping of suggest classes * @return the main classes from mapping * @throws Exception the exception * @author ceabie */ - private static ArrayList getMainClassesFromMapping( + private static List getMainClassesFromMapping( File mapping, PatternSet mainDexPattern, - HashSet mainCls) throws Exception { + Map adtMainCls) throws Exception { String line; - ArrayList mainDexList = new ArrayList<>(); - BufferedReader reader = new BufferedReader(new FileReader(mapping)); + List mainDexList = new ArrayList<>(); + BufferedReader reader = new BufferedReader(new FileReader(mapping)); // all classes - ClassFileTreeElement treeElement = new ClassFileTreeElement(); + ClassFileTreeElement filterElement = new ClassFileTreeElement(); Spec asSpec = getMaindexSpec(mainDexPattern); while ((line = reader.readLine()) != null) { @@ -395,16 +420,16 @@ private static ArrayList getMainClassesFromMapping( if (line.endsWith(":")) { int flagPos = line.indexOf(MAPPING_FLAG); if (flagPos != -1) { + String sOrgCls = line.substring(0, flagPos).replace('.', '/') + CLASS_SUFFIX; + String sMapCls = line.substring(flagPos + MAPPING_FLAG_LEN, line.length() - 1) + .replace('.', '/') + CLASS_SUFFIX; - String sOrg = line.substring(0, flagPos).replace('.', '/') + CLASS_SUFFIX; - treeElement.setClassPath(sOrg); + filterElement.setClassPath(sOrgCls); - if (asSpec.isSatisfiedBy(treeElement) - || (mainCls != null && mainCls.contains(sOrg))) { - String sMap = line.substring(flagPos + MAPPING_FLAG_LEN, line.length() - 1) - .replace('.', '/') + CLASS_SUFFIX; - - mainDexList.add(sMap); + boolean isAtMainDex = isAtMainDex(adtMainCls, sMapCls, filterElement, asSpec); + System.out.println("Filter: " + sOrgCls + " [" + isAtMainDex + "]"); + if (isAtMainDex) { + mainDexList.add(sMapCls); } } } @@ -415,46 +440,59 @@ private static ArrayList getMainClassesFromMapping( return mainDexList; } + private static boolean isAtMainDex( + Map mainCls, String sMapCls, + ClassFileTreeElement treeElement, Spec asSpec) { + + if (mainCls != null) { + Boolean inAdtList = mainCls.get(sMapCls); + if (inAdtList != null) { + return inAdtList; + } + } + + return asSpec.isSatisfiedBy(treeElement); + } + /** - * get the maindexlist of android gradle plugin + * get the maindexlist of android gradle plugin. + * if enable ProGuard, return the mapped class. */ - private static HashSet getAdtMainDexClasses(File outputDir, PatternSet mainDexPattern, - boolean logFilter) - throws Exception { + private static Map getAdtMainDexClasses( + File outputDir, + PatternSet mainDexPattern, + boolean logFilter) throws Exception { + if (outputDir == null || !outputDir.exists()) { - System.err.println( - "DexKnife Warning: Android recommand Main dex is no exist, try run again!"); + System.err.println("DexKnife Warning: Android recommand Main dex is no exist, try run again!"); return null; } - HashSet mainCls = new HashSet<>(); + HashMap mainCls = new HashMap<>(); BufferedReader reader = new BufferedReader(new FileReader(outputDir)); ClassFileTreeElement treeElement = new ClassFileTreeElement(); - Spec asSpec = mainDexPattern != null ? getMaindexSpec(mainDexPattern) - : null; + Spec asSpec = mainDexPattern != null ? getMaindexSpec(mainDexPattern) : null; String line, clsPath; while ((line = reader.readLine()) != null) { line = line.trim(); int clsPos = line.lastIndexOf(CLASS_SUFFIX); if (clsPos != -1) { + boolean satisfiedBy = true; + if (asSpec != null) { clsPath = line.substring(0, clsPos).replace('.', '/') + CLASS_SUFFIX; treeElement.setClassPath(clsPath); - boolean satisfiedBy = asSpec.isSatisfiedBy(treeElement); - if (!satisfiedBy) { - if (logFilter) - System.out.println("DexKnife-Suggest: [Split] " + clsPath); - continue; + satisfiedBy = asSpec.isSatisfiedBy(treeElement); + if (logFilter) { + System.out.println("DexKnife-Suggest: [" + + (satisfiedBy ? "Keep" : "Split") + "] " + clsPath); } - - if (logFilter) - System.out.println("DexKnife-Suggest: [Keep] " + clsPath); } - mainCls.add(line); + mainCls.put(line, satisfiedBy); } } @@ -483,4 +521,4 @@ static int getAndroidPluginVersion(String version) { return ver; } -} +} \ No newline at end of file diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy index e555460..84932d3 100644 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy +++ b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy @@ -18,7 +18,6 @@ package com.ceabie.dexknife import com.android.build.api.transform.Format import com.android.build.api.transform.Transform import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.internal.incremental.InstantRunBuildContext import com.android.build.gradle.internal.pipeline.TransformTask import com.android.build.gradle.internal.transforms.DexTransform import org.gradle.api.Project @@ -127,7 +126,7 @@ public class SplitToolsFor150 extends DexSplitTools { private static boolean isInInstantRunMode(Object variant) { try { def scope = variant.getVariantData().getScope() - InstantRunBuildContext instantRunBuildContext = scope.getInstantRunBuildContext() + def instantRunBuildContext = scope.getInstantRunBuildContext() return instantRunBuildContext.isInInstantRunMode() } catch (Throwable e) { } diff --git a/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties b/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties index e5ad1b4..e17444a 100644 --- a/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties +++ b/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Tue Sep 20 15:06:11 CST 2016 +#Mon Dec 26 17:59:14 CST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/README.md b/README.md index 9a9c0a0..1c0f7e8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ #Android傻瓜式分包插件 注1:不想看前半部分的话可以直接跳过到最下面配置部分。 -注2:本插件是基于[DexKnifePlugin 1.5.6](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 +注2:本插件是基于[DexKnifePlugin 1.5.9](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 ##填坑之路 ###坑1:65536 ,So easy! @@ -10,7 +10,7 @@ **解决:** ``` dependencies { - compile 'com.android.support:MultiDex:1.0.1' + compile 'com.android.support:MultiDex:1.0.2' } ``` 继承 Application ,重写 attachBaseContext(Context) From 75f6cc8cc071d8890dc63da1a8f0849b91b77c35 Mon Sep 17 00:00:00 2001 From: tangxiaolv Date: Tue, 21 Feb 2017 10:14:39 +0800 Subject: [PATCH 04/14] update README.md --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1c0f7e8..5021cef 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ #Android傻瓜式分包插件 注1:不想看前半部分的话可以直接跳过到最下面配置部分。 -注2:本插件是基于[DexKnifePlugin 1.5.9](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 +注2:本插件是基于[DexKnifePlugin 1.6.0](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 ##填坑之路 ###坑1:65536 ,So easy! @@ -10,7 +10,7 @@ **解决:** ``` dependencies { - compile 'com.android.support:MultiDex:1.0.2' + compile 'com.android.support:MultiDex:1.0.1' } ``` 继承 Application ,重写 attachBaseContext(Context) @@ -111,9 +111,14 @@ afterEvaluate { ``` buildscript { dependencies { - classpath 'com.library.tangxiaolv:dexknife-plus:1.0.1' + classpath 'com.library.tangxiaolv:dexknife-plus:1.0.3' } } + +Notes:Version Mappting +1.0.3 -> DexKnifePlugin 1.6.0 +1.0.2 -> DexKnifePlugin 1.5.9 +1.0.1 -> DexKnifePlugin 1.5.6 ``` **第二步:在你的App模块的build.gradle添加插件** ``` From 58cfa586628928302a5041a4f9e2ce0af769bda3 Mon Sep 17 00:00:00 2001 From: Artist Date: Mon, 13 Mar 2017 14:42:19 +0800 Subject: [PATCH 05/14] Update README.md --- README.md | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 5021cef..5f401d4 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,12 @@ **解决:** ``` +android{ + defaultConfig { + multiDexEnabled true + } +} + dependencies { compile 'com.android.support:MultiDex:1.0.1' } @@ -107,24 +113,38 @@ afterEvaluate { 于是乎就将Gradle脚本整合进了插件,这样只需维护一个配置文件就行了。读者可以根据自己需求自行选择分开配置还是整合配置。通过这种方式我们把主Dex的方法数维持在15000左右,从此再也不用担心方法数问题了!!! ##配置部分 -**第一步:添加根目录Gradle** +**第一步:添加分包支持** +``` +android{ + defaultConfig { + multiDexEnabled true + } +} + +dependencies { + compile 'com.android.support:MultiDex:1.0.1' +} +在继承的 Application中重写 attachBaseContext(Context) + +@Override +protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + MultiDex.install(this); +} +``` +**第二步:添加根目录Gradle** ``` buildscript { dependencies { classpath 'com.library.tangxiaolv:dexknife-plus:1.0.3' } } - -Notes:Version Mappting -1.0.3 -> DexKnifePlugin 1.6.0 -1.0.2 -> DexKnifePlugin 1.5.9 -1.0.1 -> DexKnifePlugin 1.5.6 ``` -**第二步:在你的App模块的build.gradle添加插件** +**第三步:在你的App模块的build.gradle添加插件** ``` apply plugin: 'dexknifePlus' ``` -**第三步:配置参数** +**第四步:配置参数**   ``` dexKnife{ //必选参数 @@ -144,7 +164,7 @@ dexKnife{ * */ } ``` -**第四步:在你的App模块目录下新建dexknife.txt,并自定义配置** +**第五步:在你的App模块目录下新建dexknife.txt,并自定义配置** ``` #为注释符 @@ -179,7 +199,7 @@ dexKnife{ #-log-mainlist ``` -**第五步:在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用** +**第六步:在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用** ##已知错误 From dc4324f3bd2f31d184a67defbea1ac6ad6a1a4b6 Mon Sep 17 00:00:00 2001 From: Artist Date: Mon, 13 Mar 2017 14:42:58 +0800 Subject: [PATCH 06/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f401d4..d022d0c 100644 --- a/README.md +++ b/README.md @@ -124,8 +124,8 @@ android{ dependencies { compile 'com.android.support:MultiDex:1.0.1' } -在继承的 Application中重写 attachBaseContext(Context) +在继承的 Application中重写 attachBaseContext(Context) @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); From b1cc65990502b6e5f1750e37d47cfc1e69168055 Mon Sep 17 00:00:00 2001 From: Artist Date: Wed, 22 Mar 2017 18:43:51 +0800 Subject: [PATCH 07/14] Update README.md --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d022d0c..e5d2f30 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -#Android傻瓜式分包插件 +# Android傻瓜式分包插件 注1:不想看前半部分的话可以直接跳过到最下面配置部分。 注2:本插件是基于[DexKnifePlugin 1.6.0](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 -##填坑之路 -###坑1:65536 ,So easy! +## 填坑之路 +### 坑1:65536 ,So easy! **原因:**Dalvik 的 invoke-kind 指令集中,method reference index 只留了 16 bits,最多能引用 65535 个方法。 参考=>[由Android 65K方法数限制引发的思考](http://jayfeng.com/2016/03/10/%E7%94%B1Android-65K%E6%96%B9%E6%B3%95%E6%95%B0%E9%99%90%E5%88%B6%E5%BC%95%E5%8F%91%E7%9A%84%E6%80%9D%E8%80%83/). @@ -28,7 +28,7 @@ protected void attachBaseContext(Context base) { } ``` -###坑2:Too many classes in –main-dex-list ,what? +### 坑2:Too many classes in –main-dex-list ,what? **原因:**通过上面的官方分包,已经把原Dex分为1主Dex加多从Dex。主Dex包含所有4大组件,Application,Annotation,multidex等及其必要的直接依赖。由于我们方法数已达到16W之巨,上百个Activity全部塞进主Dex,又成功的把主Dex撑爆了。 **解决:** @@ -47,17 +47,17 @@ afterEvaluate { ``` 参考=>[Android Dex分包之旅](http://yydcdut.com/2016/03/20/split-dex/index.html) -###坑3:gradle 1.5.0之后不支持这种写法 ,what the fuck? +### 坑3:gradle 1.5.0之后不支持这种写法 ,what the fuck? **原因:**官方解释Gralde`1.5.0`以上已经将(jacoco, progard, multi-dex)统一移到[Transform API](http://tools.android.com/tech-docs/new-build-system/transform-api)里,然而Transform API并没有想象的那么简单好用,翻遍Google终于找到一个兼容Gradle `1.5.0`以上的分包插件[DexKnifePlugin](https://github.com/ceabie/DexKnifePlugin)。 扩展=>这篇[Android 热修复使用Gradle Plugin1.5改造Nuwa插件](http://blog.csdn.net/sbsujjbcy/article/details/50839263)比较好的介绍了Transform API的使用。 -###坑4:NoClassDefFoundError ,are you kiding me? +### 坑4:NoClassDefFoundError ,are you kiding me? **原因:**通过插件手动指定main dex中要保留的类,虽然分包成功,但是main dex中的类及其直接引用类很难通过手动的方式指定。 **解决方式:** [美团Android DEX自动拆包及动态加载简介](http://tech.meituan.com/mt-android-auto-split-dex.html),他们是通过编写了一个能够自动分析Class依赖的脚本去算出主Dex需要包含的所有必要依赖。看来写脚本是跑不掉了。 -###坑5:自定义脚本 ,read the fuck source! +### 坑5:自定义脚本 ,read the fuck source! **问题一:**哪些类是需要放入主Dex中? 查看sdk\build-tools\platform-version\mainDexClasses.rules发现放入主Dex相关类有Instrumentation,Application,Activity,Service,ContentProvider,BroadcastReceiver,BackupAgent的所有子类。 @@ -101,18 +101,18 @@ afterEvaluate { } ``` -###坑6:主dex依然爆表,shit again! +### 坑6:主dex依然爆表,shit again! 其实上面那段脚本已经成功筛选出我们想要放入主Dex的`manifest_keep列表`和`maindexlist列表`,但是在打包的时候还是把所有类打进主Dex(已无语)。这个时候就需要跟[DexKnifePlugin](https://github.com/ceabie/DexKnifePlugin)插件配合使用,首先在gradle中加上上述脚本,然后使用插件时在配置文件中加上 `-split **.**`和`#-donot-use-suggest`。DexKnifePlugin插件运行原理很简单,在生成Dex任务之前首先读取自己的配置文件(包含前面我们通过Gradle脚本生成的`maindexlist`列表),然后扫描combined.jar(包含工程中所有.class文件)匹配出我们自定义的maindexlist.txt,再替换掉build/multi-dex/maindexlist.txt,和build实例。这样分包的时候就会基于我们的规则生成主Dex。 -###坑7:ANR,HAHAHA! +### 坑7:ANR,HAHAHA! 我们最低API=16,测试并未发现ANR问题,所以暂时没考虑景上添花,这个问题比较好解决。 参考=>[Android Dex分包之旅](http://yydcdut.com/2016/03/20/split-dex/index.html) -###Congratulation +### Congratulation 恭喜,填坑终于结束,不过还有点不爽的是需要同时维护Gradle脚本和插件的配置。 于是乎就将Gradle脚本整合进了插件,这样只需维护一个配置文件就行了。读者可以根据自己需求自行选择分开配置还是整合配置。通过这种方式我们把主Dex的方法数维持在15000左右,从此再也不用担心方法数问题了!!! -##配置部分 +## 配置部分 **第一步:添加分包支持** ``` android{ @@ -201,7 +201,7 @@ dexKnife{ **第六步:在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用** -##已知错误 +## 已知错误 注:分包的时候如果发现一些莫名的错误,可以关掉instant run,一般都能解决 From 7333162f6107622113e37d3e03920a6b05e7b13e Mon Sep 17 00:00:00 2001 From: ceabie Date: Sun, 9 Apr 2017 22:54:37 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=8C=85=E5=90=8D=EF=BC=8Cdexknife=E6=94=B9=E7=94=A8maven?= =?UTF-8?q?=E5=BC=95=E5=85=A5=EF=BC=8C=E5=8D=87=E7=BA=A7=E5=88=B01.6.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DexKnifePlugin/dexknife-plus/build.gradle | 1 + .../ceabie/dexknife/ClassFileTreeElement.java | 101 ---- .../com/ceabie/dexknife/DexKnifeConfig.java | 35 -- .../com/ceabie/dexknife/DexSplitTools.java | 524 ------------------ .../dexknife/InjectAndroidBuilder.groovy | 178 ------ .../ceabie/dexknife/SplitToolsFor130.groovy | 71 --- .../ceabie/dexknife/SplitToolsFor150.groovy | 136 ----- .../dexknife/DexKnifeExtension.groovy | 2 +- .../dexknife/DexKnifePlusPlugin.groovy} | 37 +- .../gradle-plugins/dexknifePlus.properties | 2 +- 10 files changed, 10 insertions(+), 1077 deletions(-) delete mode 100644 DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/ClassFileTreeElement.java delete mode 100644 DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifeConfig.java delete mode 100644 DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java delete mode 100644 DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/InjectAndroidBuilder.groovy delete mode 100644 DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor130.groovy delete mode 100644 DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy rename DexKnifePlugin/dexknife-plus/src/main/groovy/com/{ceabie => tangxiaolv}/dexknife/DexKnifeExtension.groovy (77%) rename DexKnifePlugin/dexknife-plus/src/main/groovy/com/{ceabie/dexknife/DexKnifePlugin.groovy => tangxiaolv/dexknife/DexKnifePlusPlugin.groovy} (75%) diff --git a/DexKnifePlugin/dexknife-plus/build.gradle b/DexKnifePlugin/dexknife-plus/build.gradle index 3aafa1b..02e3c83 100644 --- a/DexKnifePlugin/dexknife-plus/build.gradle +++ b/DexKnifePlugin/dexknife-plus/build.gradle @@ -25,6 +25,7 @@ configurations { dependencies { compile gradleApi() compile localGroovy() + compile 'com.ceabie.dextools:gradle-dexknife-plugin:1.6.2' provided 'com.android.tools.build:builder:2.1.3' provided 'com.android.tools.build:gradle-core:2.1.3' } diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/ClassFileTreeElement.java b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/ClassFileTreeElement.java deleted file mode 100644 index f08b325..0000000 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/ClassFileTreeElement.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2016 ceabie (https://github.com/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. - */ -package com.ceabie.dexknife; - -import org.gradle.api.file.FileTreeElement; -import org.gradle.api.file.RelativePath; -import org.gradle.internal.nativeintegration.filesystem.FileSystem; - -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Mock the file tree element of Filter. - * - * @author ceabie - */ -public class ClassFileTreeElement implements FileTreeElement { - private RelativePath mRelativePath; - private File mFile; - - public void setClassPath(String name) { - mFile = new File(name); - mRelativePath = RelativePath.parse(!isDirectory(), name); - } - - @Override - public File getFile() { - return mFile; - } - - @Override - public boolean isDirectory() { - return false; - } - - @Override - public long getLastModified() { - return 0; - } - - @Override - public long getSize() { - return 0; - } - - @Override - public InputStream open() { -// try { -// return mZipFile.getInputStream(mZipEntry); -// } catch (IOException e) { -// e.printStackTrace(); -// } - - return null; - } - - @Override - public void copyTo(OutputStream outputStream) { - } - - @Override - public boolean copyTo(File file) { - return true; - } - - @Override - public String getName() { - return mFile.getName(); - } - - @Override - public String getPath() { - return mFile.getPath(); - } - - @Override - public RelativePath getRelativePath() { - return mRelativePath; - } - - @Override - public int getMode() { - return isDirectory() - ? FileSystem.DEFAULT_DIR_MODE - : FileSystem.DEFAULT_FILE_MODE; - } -} diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifeConfig.java b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifeConfig.java deleted file mode 100644 index 8fc9018..0000000 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifeConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 ceabie (https://github.com/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. - */ -package com.ceabie.dexknife; - -import org.gradle.api.tasks.util.PatternSet; - -import java.util.Set; - -/** - * The type Dex knife config. - * - * @author ceabie - */ -public class DexKnifeConfig { - PatternSet patternSet; - PatternSet suggestPatternSet; - boolean useSuggest = true; - boolean filterSuggest = false; - boolean logMainList = false; - boolean logFilterSuggest = false; - Set additionalParameters; -} diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java deleted file mode 100644 index 860d4af..0000000 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) 2016 ceabie (https://github.com/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. - */ -package com.ceabie.dexknife; - -import org.gradle.api.Project; -import org.gradle.api.file.FileTreeElement; -import org.gradle.api.specs.NotSpec; -import org.gradle.api.specs.OrSpec; -import org.gradle.api.specs.Spec; -import org.gradle.api.specs.Specs; -import org.gradle.api.tasks.util.PatternSet; - -import java.io.*; -import java.util.*; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * the base of spilt tools. - * - * @author ceabie - */ -public class DexSplitTools { - - public static final String DEX_KNIFE_CFG_TXT = "dexknife.txt"; - - private static final String DEX_MINIMAL_MAIN_DEX = "--minimal-main-dex"; - - private static final String DEX_KNIFE_CFG_DEX_PARAM = "-dex-param"; - private static final String DEX_KNIFE_CFG_SPLIT = "-split"; - private static final String DEX_KNIFE_CFG_KEEP = "-keep"; - private static final String DEX_KNIFE_CFG_AUTO_MAINDEX = "-auto-maindex"; - private static final String DEX_KNIFE_CFG_DONOT_USE_SUGGEST = "-donot-use-suggest"; - private static final String DEX_KNIFE_CFG_LOG_MAIN_DEX = "-log-mainlist"; - private static final String DEX_KNIFE_CFG_FILTER_SUGGEST = "-filter-suggest"; - private static final String DEX_KNIFE_CFG_SUGGEST_SPLIT = "-suggest-split"; - private static final String DEX_KNIFE_CFG_SUGGEST_KEEP = "-suggest-keep"; - private static final String DEX_KNIFE_CFG_LOG_FILTER_SUGGEST = "-log-filter-suggest"; - - private static final String MAINDEXLIST_TXT = "maindexlist.txt"; - private static final String MAPPING_FLAG = " -> "; - private static final int MAPPING_FLAG_LEN = MAPPING_FLAG.length(); - private static final String CLASS_SUFFIX = ".class"; - - private static long StartTime = 0; - - protected static void startDexKnife() { - System.out.println("DexKnife Processing ..."); - StartTime = System.currentTimeMillis(); - } - - protected static void endDexKnife() { - String time; - long internal = System.currentTimeMillis() - StartTime; - if (internal > 1000) { - float i = internal / 1000; - if (i >= 60) { - i = i / 60; - int min = (int) i; - time = min + " min " + (i - min) + " s"; - } else { - time = i + "s"; - } - } else { - time = internal + "ms"; - } - - System.out.println("DexKnife Finished: " + time); - } - - public static boolean processMainDexList(Project project, boolean minifyEnabled, File mappingFile, - File jarMergingOutputFile, File andMainDexList, - DexKnifeConfig dexKnifeConfig) throws Exception { - - if (!minifyEnabled && jarMergingOutputFile == null) { - System.out.println("DexKnife Error: jarMerging is Null! Skip DexKnife. Please report All Gradle Log."); - return false; - } - - try { - return genMainDexList(project, minifyEnabled, mappingFile, jarMergingOutputFile, - andMainDexList, dexKnifeConfig); - } catch (Exception e) { - e.printStackTrace(); - } - - return false; - } - - /** - * get the config of dex knife - */ - protected static DexKnifeConfig getDexKnifeConfig(Project project) throws Exception { - BufferedReader reader = new BufferedReader(new FileReader(project.file(DEX_KNIFE_CFG_TXT))); - DexKnifeConfig dexKnifeConfig = new DexKnifeConfig(); - - String line; - boolean matchCmd; - boolean minimalMainDex = true; - Set addParams = new HashSet<>(); - - Set splitToSecond = new HashSet<>(); - Set keepMain = new HashSet<>(); - Set splitSuggest = new HashSet<>(); - Set keepSuggest = new HashSet<>(); - - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (line.length() == 0) { - continue; - } - - int rem = line.indexOf('#'); - if (rem != -1) { - if (rem == 0) { - continue; - } else { - line = line.substring(0, rem).trim(); - } - } - - String cmd = line.toLowerCase(); - matchCmd = true; - - if (DEX_KNIFE_CFG_AUTO_MAINDEX.equals(cmd)) { - minimalMainDex = false; - } else if (matchCommand(cmd, DEX_KNIFE_CFG_DEX_PARAM)) { - String param = line.substring(DEX_KNIFE_CFG_DEX_PARAM.length()).trim(); - if (!param.toLowerCase().startsWith("--main-dex-list")) { - addParams.add(param); - } - - } else if (matchCommand(cmd, DEX_KNIFE_CFG_SPLIT)) { - String sPattern = line.substring(DEX_KNIFE_CFG_SPLIT.length()).trim(); - addClassFilePath(sPattern, splitToSecond); - - } else if (matchCommand(cmd, DEX_KNIFE_CFG_KEEP)) { - String sPattern = line.substring(DEX_KNIFE_CFG_KEEP.length()).trim(); - addClassFilePath(sPattern, keepMain); - - } else if (DEX_KNIFE_CFG_DONOT_USE_SUGGEST.equals(cmd)) { - dexKnifeConfig.useSuggest = false; - - } else if (DEX_KNIFE_CFG_FILTER_SUGGEST.equals(cmd)) { - dexKnifeConfig.filterSuggest = true; - - } else if (DEX_KNIFE_CFG_LOG_MAIN_DEX.equals(cmd)) { - dexKnifeConfig.logMainList = true; - - } else if (DEX_KNIFE_CFG_LOG_FILTER_SUGGEST.equals(cmd)) { - dexKnifeConfig.logFilterSuggest = true; - - } else if (matchCommand(cmd, DEX_KNIFE_CFG_SUGGEST_SPLIT)) { - String sPattern = line.substring(DEX_KNIFE_CFG_SUGGEST_SPLIT.length()).trim(); - addClassFilePath(sPattern, splitSuggest); - - } else if (matchCommand(cmd, DEX_KNIFE_CFG_SUGGEST_KEEP)) { - String sPattern = line.substring(DEX_KNIFE_CFG_SUGGEST_KEEP.length()).trim(); - addClassFilePath(sPattern, keepSuggest); - - } else if (!cmd.startsWith("-")) { - addClassFilePath(line, splitToSecond); - } else { - matchCmd = false; - } - - if (matchCmd) { - System.out.println("DexKnife Config: " + line); - } - } - - reader.close(); - - if (minimalMainDex) { - addParams.add(DEX_MINIMAL_MAIN_DEX); - } - - // 使用ADT建议的mainlist - if (dexKnifeConfig.useSuggest) { - - // 将全局过滤应用到建议的mainlist - if (dexKnifeConfig.filterSuggest) { - splitSuggest.addAll(splitToSecond); - keepSuggest.addAll(keepMain); - } - - if (!splitSuggest.isEmpty() || !keepSuggest.isEmpty()) { - dexKnifeConfig.suggestPatternSet = new PatternSet() - .exclude(splitSuggest) - .include(keepSuggest); - } - } - - if (!splitToSecond.isEmpty() || !keepMain.isEmpty()) { - dexKnifeConfig.patternSet = new PatternSet() - .exclude(splitToSecond) - .include(keepMain); - } else { - dexKnifeConfig.useSuggest = true; - System.err.println("DexKnife Warning: NO SET split Or keep path, it will use Suggest!"); - } - - dexKnifeConfig.additionalParameters = addParams; - - return dexKnifeConfig; - } - - private static boolean matchCommand(String text, String cmd) { - Pattern pattern = Pattern.compile("^" + cmd + "\\s+"); - return pattern.matcher(text).find(); - } - - /** - * add the class path to pattern list, and the single class pattern can work. - */ - private static void addClassFilePath(String classPath, Set patternList) { - if (classPath != null && classPath.length() > 0) { - if (classPath.endsWith(CLASS_SUFFIX)) { - classPath = classPath.substring(0, classPath.length() - CLASS_SUFFIX.length()) - .replace('.', '/') + CLASS_SUFFIX; - } else { - classPath = classPath.replace('.', '/'); - } - - patternList.add(classPath); - } - } - - private static Spec getMaindexSpec(PatternSet patternSet) { - Spec maindexSpec = null; - - if (patternSet != null) { - Spec includeSpec = null; - Spec excludeSpec = null; - - if (!patternSet.getIncludes().isEmpty()) { - includeSpec = patternSet.getAsIncludeSpec(); - } - - if (!patternSet.getExcludes().isEmpty()) { - excludeSpec = patternSet.getAsExcludeSpec(); - } - - if (includeSpec != null && excludeSpec != null) { - maindexSpec = new OrSpec<>(includeSpec, new NotSpec<>(excludeSpec)); - } else { - if (excludeSpec == null) { - maindexSpec = Specs.satisfyAll(); - } else { - maindexSpec = new NotSpec<>(excludeSpec); - } - } - } - - if (maindexSpec == null) { - maindexSpec = Specs.satisfyAll(); - } - - return maindexSpec; - } - - - private static boolean isPatternSetEmpty(PatternSet patternSet) { - return patternSet.getExcludes().isEmpty() && patternSet.getIncludes().isEmpty() - && patternSet.getExcludeSpecs().isEmpty() && patternSet.getIncludeSpecs().isEmpty(); - } - - /** - * generate the main dex list - */ - private static boolean genMainDexList(Project project, boolean minifyEnabled, - File mappingFile, File jarMergingOutputFile, - File andMainDexList, DexKnifeConfig dexKnifeConfig) throws Exception { - - System.out.println(":" + project.getName() + ":genMainDexList"); - - // 1.get the adt's maindexlist - Map adtMainClasses = null; - if (dexKnifeConfig.useSuggest) { - - PatternSet patternSet = dexKnifeConfig.suggestPatternSet; - if (dexKnifeConfig.filterSuggest && patternSet == null) { - patternSet = dexKnifeConfig.patternSet; - } - - System.out.println("DexKnife: use suggest"); - adtMainClasses = getAdtMainDexClasses(andMainDexList, patternSet, dexKnifeConfig.logFilterSuggest); - } - - File keepFile = project.file(MAINDEXLIST_TXT); - keepFile.delete(); - - // 2.process the global filter - List mainClasses = null; - if (dexKnifeConfig.patternSet == null || isPatternSetEmpty(dexKnifeConfig.patternSet)) { - // only filter the suggest list - if (adtMainClasses != null && adtMainClasses.size() > 0) { - mainClasses = new ArrayList<>(); - Set> entries = adtMainClasses.entrySet(); - for (Map.Entry entry : entries) { - if (entry.getValue()) { - mainClasses.add(entry.getKey()); - } - } - } - } else { - if (minifyEnabled) { - System.err.println("DexKnife: From Mapping"); - // get classes from mapping - mainClasses = getMainClassesFromMapping(mappingFile, dexKnifeConfig.patternSet, adtMainClasses); - } else { - System.out.println("DexKnife: From MergedJar: " + jarMergingOutputFile); - if (jarMergingOutputFile != null) { - // get classes from merged jar - mainClasses = getMainClassesFromJar(jarMergingOutputFile, dexKnifeConfig.patternSet, adtMainClasses); - } else { - System.err.println("DexKnife: The Merged Jar is not exist! Can't be processed!"); - } - } - } - - // 3.create the miandexlist - if (mainClasses != null && mainClasses.size() > 0) { - BufferedWriter writer = new BufferedWriter(new FileWriter(keepFile)); - - for (String mainClass : mainClasses) { - writer.write(mainClass); - writer.newLine(); - - if (dexKnifeConfig.logMainList) { - System.out.println(mainClass); - } - } - - writer.close(); - - return true; - } - - throw new Exception("DexKnife Warning: Main dex is EMPTY ! Check your config and project!"); - } - - /** - * Gets main classes from jar. - * - * @param jarMergingOutputFile the jar merging output file - * @param mainDexPattern the main dex pattern - * @param adtMainCls the filter mapping of suggest classes - * @return the main classes from jar - * @throws Exception the exception - * @author ceabie - */ - private static ArrayList getMainClassesFromJar( - File jarMergingOutputFile, PatternSet mainDexPattern, Map adtMainCls) - throws Exception { - ZipFile clsFile = new ZipFile(jarMergingOutputFile); - Spec asSpec = getMaindexSpec(mainDexPattern); - ClassFileTreeElement treeElement = new ClassFileTreeElement(); - - // lists classes from jar. - ArrayList mainDexList = new ArrayList<>(); - Enumeration entries = clsFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - String entryName = entry.getName(); - - if (entryName.endsWith(CLASS_SUFFIX)) { - treeElement.setClassPath(entryName); - - if (isAtMainDex(adtMainCls, entryName, treeElement, asSpec)) { - mainDexList.add(entryName); - } - } - } - - clsFile.close(); - - return mainDexList; - } - - /** - * Gets main classes from mapping. - * - * @param mapping the mapping file - * @param mainDexPattern the main dex pattern - * @param adtMainCls the filter mapping of suggest classes - * @return the main classes from mapping - * @throws Exception the exception - * @author ceabie - */ - private static List getMainClassesFromMapping( - File mapping, - PatternSet mainDexPattern, - Map adtMainCls) throws Exception { - - String line; - List mainDexList = new ArrayList<>(); - BufferedReader reader = new BufferedReader(new FileReader(mapping)); // all classes - - ClassFileTreeElement filterElement = new ClassFileTreeElement(); - Spec asSpec = getMaindexSpec(mainDexPattern); - - while ((line = reader.readLine()) != null) { - line = line.trim(); - - if (line.endsWith(":")) { - int flagPos = line.indexOf(MAPPING_FLAG); - if (flagPos != -1) { - String sOrgCls = line.substring(0, flagPos).replace('.', '/') + CLASS_SUFFIX; - String sMapCls = line.substring(flagPos + MAPPING_FLAG_LEN, line.length() - 1) - .replace('.', '/') + CLASS_SUFFIX; - - filterElement.setClassPath(sOrgCls); - - boolean isAtMainDex = isAtMainDex(adtMainCls, sMapCls, filterElement, asSpec); - System.out.println("Filter: " + sOrgCls + " [" + isAtMainDex + "]"); - if (isAtMainDex) { - mainDexList.add(sMapCls); - } - } - } - } - - reader.close(); - - return mainDexList; - } - - private static boolean isAtMainDex( - Map mainCls, String sMapCls, - ClassFileTreeElement treeElement, Spec asSpec) { - - if (mainCls != null) { - Boolean inAdtList = mainCls.get(sMapCls); - if (inAdtList != null) { - return inAdtList; - } - } - - return asSpec.isSatisfiedBy(treeElement); - } - - /** - * get the maindexlist of android gradle plugin. - * if enable ProGuard, return the mapped class. - */ - private static Map getAdtMainDexClasses( - File outputDir, - PatternSet mainDexPattern, - boolean logFilter) throws Exception { - - if (outputDir == null || !outputDir.exists()) { - System.err.println("DexKnife Warning: Android recommand Main dex is no exist, try run again!"); - return null; - } - - HashMap mainCls = new HashMap<>(); - BufferedReader reader = new BufferedReader(new FileReader(outputDir)); - - ClassFileTreeElement treeElement = new ClassFileTreeElement(); - Spec asSpec = mainDexPattern != null ? getMaindexSpec(mainDexPattern) : null; - - String line, clsPath; - while ((line = reader.readLine()) != null) { - line = line.trim(); - int clsPos = line.lastIndexOf(CLASS_SUFFIX); - if (clsPos != -1) { - boolean satisfiedBy = true; - - if (asSpec != null) { - clsPath = line.substring(0, clsPos).replace('.', '/') + CLASS_SUFFIX; - treeElement.setClassPath(clsPath); - - satisfiedBy = asSpec.isSatisfiedBy(treeElement); - if (logFilter) { - System.out.println("DexKnife-Suggest: [" + - (satisfiedBy ? "Keep" : "Split") + "] " + clsPath); - } - } - - mainCls.put(line, satisfiedBy); - } - } - - reader.close(); - - if (mainCls.size() == 0) { - mainCls = null; - } - - return mainCls; - } - - static int getAndroidPluginVersion(String version) { - int size = version.length(); - int ver = 0; - for (int i = 0; i < size; i++) { - char c = version.charAt(i); - if (Character.isDigit(c) || c == '.') { - if (c != '.') { - ver = ver * 10 + c - '0'; - } - } else { - break; - } - } - - return ver; - } -} \ No newline at end of file diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/InjectAndroidBuilder.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/InjectAndroidBuilder.groovy deleted file mode 100644 index 5651173..0000000 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/InjectAndroidBuilder.groovy +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2016 ceabie (https://github.com/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. - */ -package com.ceabie.dexknife - -import com.android.build.gradle.internal.transforms.DexTransform -import com.android.builder.core.AndroidBuilder -import com.android.builder.core.DexOptions -import com.android.builder.core.ErrorReporter -import com.android.builder.sdk.TargetInfo -import com.android.ide.common.process.JavaProcessExecutor -import com.android.ide.common.process.ProcessException -import com.android.ide.common.process.ProcessExecutor -import com.android.ide.common.process.ProcessOutputHandler -import com.android.utils.ILogger -import groovy.transform.CompileStatic - -import java.lang.reflect.Field - -/** - * proxy the androidBuilder that plugin 1.5.0 to add '--minimal-main-dex' options. - * - * @author ceabie - */ -public class InjectAndroidBuilder extends AndroidBuilder { - - Collection mAddParams; - AndroidBuilder mAndroidBuilder; - - public InjectAndroidBuilder(String projectId, - String createdBy, - ProcessExecutor processExecutor, - JavaProcessExecutor javaProcessExecutor, - ErrorReporter errorReporter, - ILogger logger, - boolean verboseExec) { - super(projectId, createdBy, processExecutor, javaProcessExecutor, errorReporter, logger, verboseExec) - } - -// @Override // for < 2.2.0 - public void convertByteCode(Collection inputs, - File outDexFolder, - boolean multidex, - File mainDexList, - DexOptions dexOptions, - List additionalParameters, - boolean incremental, - boolean optimize, - ProcessOutputHandler processOutputHandler) - throws IOException, InterruptedException, ProcessException { - - println("DexKnife: convertByteCode before 2.2.0") - if (mAddParams != null) { - if (additionalParameters == null) { - additionalParameters = new ArrayList<>() - } - - mergeParams(additionalParameters, mAddParams) - } - - // groovy call super has bug - mAndroidBuilder.convertByteCode(inputs, outDexFolder, multidex, mainDexList, dexOptions, - additionalParameters, incremental, optimize, processOutputHandler); - } - -// @Override for >= 2.2.0 - public void convertByteCode(Collection inputs, - File outDexFolder, - boolean multidex, - File mainDexList, - final DexOptions dexOptions, - boolean optimize, - ProcessOutputHandler processOutputHandler) - throws IOException, InterruptedException, ProcessException { - - println("DexKnife:convertByteCode after 2.2.0") - - DexOptions dexOptionsProxy = dexOptions - - if (mAddParams != null) { - List additionalParameters = dexOptions.getAdditionalParameters() - if (additionalParameters == null) { - additionalParameters = new ArrayList<>() - } - - mergeParams(additionalParameters, mAddParams) - } - - mAndroidBuilder.convertByteCode(inputs, outDexFolder, multidex, mainDexList, dexOptionsProxy, - optimize, processOutputHandler); - } - - @CompileStatic - @Override - List getBootClasspath(boolean includeOptionalLibraries) { - return mAndroidBuilder.getBootClasspath(includeOptionalLibraries) - } - - @CompileStatic - @Override - List getBootClasspathAsStrings(boolean includeOptionalLibraries) { - return mAndroidBuilder.getBootClasspathAsStrings(includeOptionalLibraries) - } - - - @CompileStatic - static void mergeParams(List additionalParameters, Collection addParams) { - List mergeParam = new ArrayList<>() - for (String param : addParams) { - if (!additionalParameters.contains(param)) { - mergeParam.add(param) - } - } - - if (mergeParam.size() > 0) { - additionalParameters.addAll(mergeParam) - } - } - - - public static void proxyAndroidBuilder(DexTransform transform, Collection addParams) { - if (addParams != null && addParams.size() > 0) { - accessibleField(DexTransform.class, "androidBuilder") - .set(transform, getProxyAndroidBuilder(transform.androidBuilder, addParams)) - } - } - - private static AndroidBuilder getProxyAndroidBuilder(AndroidBuilder orgAndroidBuilder, - Collection addParams) { - InjectAndroidBuilder myAndroidBuilder = new InjectAndroidBuilder( - orgAndroidBuilder.mProjectId, - orgAndroidBuilder.mCreatedBy, - orgAndroidBuilder.getProcessExecutor(), - orgAndroidBuilder.mJavaProcessExecutor, - orgAndroidBuilder.getErrorReporter(), - orgAndroidBuilder.getLogger(), - orgAndroidBuilder.mVerboseExec) - - // if >= 2.2.0 - def to = myAndroidBuilder.respondsTo("setTargetInfo", TargetInfo.class) - if (to.size() > 0) { - myAndroidBuilder.setTargetInfo(orgAndroidBuilder.getTargetInfo()) - myAndroidBuilder.setSdkInfo(orgAndroidBuilder.getSdkInfo()) - myAndroidBuilder.setLibraryRequests(orgAndroidBuilder.mLibraryRequests) - } else { - myAndroidBuilder.setTargetInfo( - orgAndroidBuilder.getSdkInfo(), - orgAndroidBuilder.getTargetInfo(), - orgAndroidBuilder.mLibraryRequests) - } - - myAndroidBuilder.mAddParams = addParams - myAndroidBuilder.mAndroidBuilder = orgAndroidBuilder -// myAndroidBuilder.mBootClasspathFiltered = orgAndroidBuilder.mBootClasspathFiltered -// myAndroidBuilder.mBootClasspathAll = orgAndroidBuilder.mBootClasspathAll - - return myAndroidBuilder - } - - @CompileStatic - private static Field accessibleField(Class cls, String field) { - Field f = cls.getDeclaredField(field) - f.setAccessible(true) - return f - } -} diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor130.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor130.groovy deleted file mode 100644 index 58fdba5..0000000 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor130.groovy +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2016 ceabie (https://github.com/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. - */ -package com.ceabie.dexknife - -import org.gradle.api.Project - -/** - * the spilt tools for plugin 1.3.0. - * - * @author ceabie - */ -public class SplitToolsFor130 extends DexSplitTools { - - public static boolean isCompat(Object variant) { - try { - if (variant != null) { - variant.dex - - return true - } - } catch (RuntimeException e) { -// e.printStackTrace() - } - - return false - } - - public static void processSplitDex(Project project, Object variant) { - def dex = variant.dex - if (dex.multiDexEnabled) { - dex.inputs.file DEX_KNIFE_CFG_TXT - - dex.doFirst { - startDexKnife() - - DexKnifeConfig dexKnifeConfig = getDexKnifeConfig(project) - - def scope = variant.getVariantData().getScope() - File mergedJar = scope.jarMergingOutputFile - File mappingFile = variant.mappingFile - File andMainDexList = scope.mainDexListFile - boolean minifyEnabled = variant.buildType.minifyEnabled - - if (processMainDexList(project, minifyEnabled, mappingFile, mergedJar, - andMainDexList, dexKnifeConfig)) { - if (dex.additionalParameters == null) { - dex.additionalParameters = [] - } - - dex.additionalParameters += '--main-dex-list=maindexlist.txt' - dex.additionalParameters += dexKnifeConfig.additionalParameters - } - - endDexKnife() - } - } - } -} \ No newline at end of file diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy deleted file mode 100644 index 84932d3..0000000 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2016 ceabie (https://github.com/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. - */ -package com.ceabie.dexknife - -import com.android.build.api.transform.Format -import com.android.build.api.transform.Transform -import com.android.build.gradle.api.ApplicationVariant -import com.android.build.gradle.internal.pipeline.TransformTask -import com.android.build.gradle.internal.transforms.DexTransform -import org.gradle.api.Project - -/** - * the spilt tools for plugin 1.5.0. - * - * @author ceabie - */ -public class SplitToolsFor150 extends DexSplitTools { - - public static boolean isCompat() { -// if (getAndroidPluginVersion() < 200) { -// return true; -// } - - return true; - } - - public static void processSplitDex(Project project, ApplicationVariant variant) { - if (isInInstantRunMode(variant)) { - System.err.println("DexKnife: Instant Run mode, DexKnife is auto disabled!") - return - } - - TransformTask dexTask -// TransformTask proGuardTask - TransformTask jarMergingTask - - String name = variant.name.capitalize() - boolean minifyEnabled = variant.buildType.minifyEnabled - - // find the task we want to process - project.tasks.matching { - ((it instanceof TransformTask) && it.name.endsWith(name)) // TransformTask - }.each { TransformTask theTask -> - Transform transform = theTask.transform - String transformName = transform.name - -// if (minifyEnabled && "proguard".equals(transformName)) { // ProGuardTransform -// proGuardTask = theTask -// } else - if ("jarMerging".equalsIgnoreCase(transformName)) { - jarMergingTask = theTask - } else if ("dex".equalsIgnoreCase(transformName)) { // DexTransform - dexTask = theTask - } - } - - if (dexTask != null && ((DexTransform) dexTask.transform).multiDex) { - dexTask.inputs.file DEX_KNIFE_CFG_TXT - - dexTask.doFirst { - startDexKnife() - - File mergedJar = null - File mappingFile = variant.mappingFile - DexTransform dexTransform = it.transform - File fileAdtMainList = dexTransform.mainDexListFile - - println("DexKnife Adt Main: " + fileAdtMainList) - - DexKnifeConfig dexKnifeConfig = getDexKnifeConfig(project) - - // 非混淆的,从合并后的jar文件中提起mainlist; - // 混淆的,直接从mapping文件中提取 - if (minifyEnabled) { - println("DexKnife-From Mapping: " + mappingFile) - } else { - if (jarMergingTask != null) { - Transform transform = jarMergingTask.transform - def outputProvider = jarMergingTask.outputStream.asOutput() - mergedJar = outputProvider.getContentLocation("combined", - transform.getOutputTypes(), - transform.getScopes(), Format.JAR) - } - - println("DexKnife-From MergedJar: " + mergedJar) - } - - if (processMainDexList(project, minifyEnabled, mappingFile, mergedJar, - fileAdtMainList, dexKnifeConfig)) { - - int version = getAndroidPluginVersion(getAndroidGradlePluginVersion()) - println("DexKnife: AndroidPluginVersion: " + version) - - // after 2.2.0, it can additionalParameters, but it is a copy in task - - // 替换 AndroidBuilder - InjectAndroidBuilder.proxyAndroidBuilder(dexTransform, - dexKnifeConfig.additionalParameters) - - // 替换这个文件 - fileAdtMainList.delete() - project.copy { - from 'maindexlist.txt' - into fileAdtMainList.parentFile - } - } - - endDexKnife() - } - } - } - - private static boolean isInInstantRunMode(Object variant) { - try { - def scope = variant.getVariantData().getScope() - def instantRunBuildContext = scope.getInstantRunBuildContext() - return instantRunBuildContext.isInInstantRunMode() - } catch (Throwable e) { - } - - return false - } -} \ No newline at end of file diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifeExtension.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifeExtension.groovy similarity index 77% rename from DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifeExtension.groovy rename to DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifeExtension.groovy index dffcbf0..31795a9 100644 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifeExtension.groovy +++ b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifeExtension.groovy @@ -1,4 +1,4 @@ -package com.ceabie.dexknife +package com.tangxiaolv.dexknife class DexKnifeExtension { boolean enabled = false diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifePlugin.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifePlusPlugin.groovy similarity index 75% rename from DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifePlugin.groovy rename to DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifePlusPlugin.groovy index c7086b6..c19971b 100644 --- a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/ceabie/dexknife/DexKnifePlugin.groovy +++ b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifePlusPlugin.groovy @@ -13,15 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ceabie.dexknife +package com.tangxiaolv.dexknife +import com.ceabie.dexknife.DexKnifePlugin +import com.ceabie.dexknife.DexSplitTools import org.gradle.api.Plugin import org.gradle.api.Project /** * the spilt tools plugin. */ -public class DexKnifePlugin implements Plugin { +public class DexKnifePlusPlugin implements Plugin { @Override void apply(Project project) { @@ -48,21 +50,11 @@ public class DexKnifePlugin implements Plugin { filterActivity(project); - if (isMultiDexEnabled(variant)) { - if (SplitToolsFor130.isCompat(variant)) { - System.err.println("DexKnife: Compat 1.3.0."); - SplitToolsFor130.processSplitDex(project, variant) - } else if (SplitToolsFor150.isCompat()) { - SplitToolsFor150.processSplitDex(project, variant) - } else { - System.err.println("DexKnife Error: DexKnife is not compatible your Android gradle plugin."); - } - } else { - System.err.println("DexKnife : MultiDexEnabled is false, it's not work."); - } + DexKnifePlugin.dexKnifeProcessVariant(project, variant) } + } else { + printf "-DexKnifePlugin Enable = false\n"; } - printf "-DexKnifePlugin Enable = false\n"; } } } @@ -103,19 +95,4 @@ public class DexKnifePlugin implements Plugin { } } } - - private static boolean isMultiDexEnabled(variant) { - def is = variant.buildType.multiDexEnabled - if (is != null) { - return is; - } - - is = variant.mergedFlavor.multiDexEnabled - if (is != null) { - return is; - } - - return false - } - } \ No newline at end of file diff --git a/DexKnifePlugin/dexknife-plus/src/main/resources/META-INF/gradle-plugins/dexknifePlus.properties b/DexKnifePlugin/dexknife-plus/src/main/resources/META-INF/gradle-plugins/dexknifePlus.properties index 24abf7f..c2ec48d 100644 --- a/DexKnifePlugin/dexknife-plus/src/main/resources/META-INF/gradle-plugins/dexknifePlus.properties +++ b/DexKnifePlugin/dexknife-plus/src/main/resources/META-INF/gradle-plugins/dexknifePlus.properties @@ -1 +1 @@ -implementation-class=com.ceabie.dexknife.DexKnifePlugin +implementation-class=com.tangxiaolv.dexknife.DexKnifePlusPlugin From bfe34c47676e9b5cb98f926dc166285e784967ed Mon Sep 17 00:00:00 2001 From: ceabie Date: Mon, 10 Apr 2017 00:15:07 +0800 Subject: [PATCH 09/14] update readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e5d2f30..745e0d4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Android傻瓜式分包插件 注1:不想看前半部分的话可以直接跳过到最下面配置部分。 -注2:本插件是基于[DexKnifePlugin 1.6.0](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 +注2:本插件是基于[DexKnifePlugin 1.6.2](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 ## 填坑之路 ### 坑1:65536 ,So easy! @@ -201,6 +201,8 @@ dexKnife{ **第六步:在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用** +**使用前先参阅 DexKnife 的[特性部分](https://github.com/ceabie/DexKnifePlugin#特性重要)** + ## 已知错误 注:分包的时候如果发现一些莫名的错误,可以关掉instant run,一般都能解决 From 79a7b0ea6da3cc0fa234abdf9dcfc6dab0a3be4c Mon Sep 17 00:00:00 2001 From: tangxiaolv Date: Mon, 10 Apr 2017 09:42:32 +0800 Subject: [PATCH 10/14] sync update from dexknife --- .gitignore | 1 + DexKnifePlugin/dexknife-plus/gradle.properties | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 20c8c87..fa5f81f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /DexKnifePlugin/.idea/qaplug_profiles.xml /DexKnifePlugin/.idea/runConfigurations.xml /DexKnifePlugin/.idea/vcs.xml +.idea/ diff --git a/DexKnifePlugin/dexknife-plus/gradle.properties b/DexKnifePlugin/dexknife-plus/gradle.properties index e492aa4..2f24490 100644 --- a/DexKnifePlugin/dexknife-plus/gradle.properties +++ b/DexKnifePlugin/dexknife-plus/gradle.properties @@ -1,6 +1,6 @@ #Gradle:groupId:libraryName:publicVersion LOCAL_VERSION=0.0.5 -PUBLIC_VERSION=1.0.3 +PUBLIC_VERSION=1.0.4 GROUP_ID=com.library.tangxiaolv #Modelһ LIBRARY_NAME=dexknife-plus diff --git a/README.md b/README.md index 745e0d4..aae8520 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ protected void attachBaseContext(Context base) { ``` buildscript { dependencies { - classpath 'com.library.tangxiaolv:dexknife-plus:1.0.3' + classpath 'com.library.tangxiaolv:dexknife-plus:1.0.4' } } ``` From 09f786eb448e553251d0ba791605d1ce6d2f4d28 Mon Sep 17 00:00:00 2001 From: tangxiaolv Date: Mon, 10 Apr 2017 09:51:56 +0800 Subject: [PATCH 11/14] update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index aae8520..c64d957 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # Android傻瓜式分包插件 +[ ![Download](https://api.bintray.com/packages/tangxiaolv/maven/dexknife-plus/images/download.svg?version=1.0.4) ](https://bintray.com/tangxiaolv/maven/dexknife-plus/1.0.4/link) + 注1:不想看前半部分的话可以直接跳过到最下面配置部分。 注2:本插件是基于[DexKnifePlugin 1.6.2](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 From d7b22bbd038b434082a51f4911d09b7653ee6389 Mon Sep 17 00:00:00 2001 From: tangxiaolv Date: Mon, 10 Apr 2017 10:25:28 +0800 Subject: [PATCH 12/14] update readme --- DexKnifePlugin/app/dexknife.txt | 6 +++--- README.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DexKnifePlugin/app/dexknife.txt b/DexKnifePlugin/app/dexknife.txt index 33e281b..c6e76f4 100644 --- a/DexKnifePlugin/app/dexknife.txt +++ b/DexKnifePlugin/app/dexknife.txt @@ -1,10 +1,10 @@ #为注释符 -#-----------主Dex中必要依赖的脚本配置----------- -#默认保留四大组件中其他三大组件(并计算其依赖树),Activity组件选择性保留(使用-just activity 选项),若为空不保留任何Activity +#-----------主Dex中必要依赖的脚本配置-----------(支持依赖检测) +#默认保留四大组件中Service,ContentProvider,BroadcastReceiver三大组件,Activity组件选择性保留,若为空不保留任何Activity -just activity com.ceabie.demo.MainActivity -#-----------附加类----------- +#-----------附加类-----------(不支持依赖检测) # 如果你想要某个包路径在maindex中,则使用 -keep 选项,即使他已经在分包的路径中.若为空,不保留任意类 #-keep com.ceabie.demo.** diff --git a/README.md b/README.md index c64d957..4d98b13 100644 --- a/README.md +++ b/README.md @@ -170,11 +170,11 @@ dexKnife{ ``` #为注释符 -#-----------主Dex中必要依赖的脚本配置----------- -#默认保留四大组件中其他三大组件(并计算其依赖树),Activity组件选择性保留(使用-just activity 选项),若为空不保留任何Activity +#-----------主Dex中必要依赖的脚本配置-----------(支持依赖检测) +#默认保留四大组件中Service,ContentProvider,BroadcastReceiver三大组件,Activity组件选择性保留,若为空不保留任何Activity -just activity com.ceabie.demo.MainActivity -#-----------附加类----------- +#-----------附加类-----------(不支持依赖检测) # 如果你想要某个包路径在maindex中,则使用 -keep 选项,即使他已经在分包的路径中.若为空,不保留任意类 #-keep com.ceabie.demo.** From c90d78fdde307bf878a9805c38d8502dcaa0979e Mon Sep 17 00:00:00 2001 From: Artist Date: Sun, 20 Jan 2019 16:02:35 +0800 Subject: [PATCH 13/14] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4d98b13..b67d2d2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# Deprecated +plz use [multiDexKeepProguard](https://developer.android.com/studio/build/multidex?hl=zh-cn) to splite main dex classes. + # Android傻瓜式分包插件 [ ![Download](https://api.bintray.com/packages/tangxiaolv/maven/dexknife-plus/images/download.svg?version=1.0.4) ](https://bintray.com/tangxiaolv/maven/dexknife-plus/1.0.4/link) From 19abd3325654666e82f4f868d1c1396781c113f4 Mon Sep 17 00:00:00 2001 From: Artist Date: Sun, 20 Jan 2019 16:03:56 +0800 Subject: [PATCH 14/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b67d2d2..28cdf90 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Deprecated -plz use [multiDexKeepProguard](https://developer.android.com/studio/build/multidex?hl=zh-cn) to splite main dex classes. +Please use [multiDexKeepProguard](https://developer.android.com/studio/build/multidex?hl=zh-cn) to splite main dex classes. # Android傻瓜式分包插件 [ ![Download](https://api.bintray.com/packages/tangxiaolv/maven/dexknife-plus/images/download.svg?version=1.0.4) ](https://bintray.com/tangxiaolv/maven/dexknife-plus/1.0.4/link) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy