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/.gitignore b/DexKnifePlugin/.gitignore index e86cb99..7cb5c9c 100644 --- a/DexKnifePlugin/.gitignore +++ b/DexKnifePlugin/.gitignore @@ -5,4 +5,16 @@ /.idea/libraries .DS_Store /build -/captures \ No newline at end of file +/captures +local.properties +.idea/compiler.xml +.idea/copyright/ +.idea/encodings.xml +.idea/gradle.xml +.idea/misc.xml +.idea/qaplug_profiles.xml +gradle/ +gradlew +gradlew.bat +repo/com/ceabie/ +repo/com/library/ diff --git a/DexKnifePlugin/LICENSE.txt b/DexKnifePlugin/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/DexKnifePlugin/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/DexKnifePlugin/app/build.gradle b/DexKnifePlugin/app/build.gradle index 0da9a3f..aa8d0ba 100644 --- a/DexKnifePlugin/app/build.gradle +++ b/DexKnifePlugin/app/build.gradle @@ -1,27 +1,48 @@ apply plugin: 'com.android.application' -apply plugin: 'com.ceabie.dexnkife' +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{ + + } + + mock{ + + } + } + 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' } } @@ -31,6 +52,24 @@ android { } } +dexKnife{ + //必选参数 + enabled true //if false,禁用分包插件 + //可选参数 + //1.如果没有可选参数,将根据enabled决定是否分包。 + //2.如果有可选参数,需满足必选参数和可选参数的条件才允许分包 + productFlavor 'mock' + //buildType 'debug' + + /* + *eg:当前productFlavors = dev,buildType = debug, + *参数组合1:enabled = true,productFlavor = dev,buildType = debug 分包 + *参数组合2:enabled = true,productFlavor = mock,buildType = debug 不分包 + *参数组合1:enabled = true,buildType = debug 所有buildType = debug分包 + *参数组合1:enabled = true,productFlavor = dev 所有productFlavor = dev分包 + * */ +} + dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile "com.android.support:appcompat-v7:${SUPPORT_VERSION}" diff --git a/DexKnifePlugin/app/dexknife.txt b/DexKnifePlugin/app/dexknife.txt index e0fbd8b..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.** @@ -16,10 +16,15 @@ #将全部类移出主Dex -split **.** -# 不包含Android gradle 插件自动生成的miandex列表.(不用系统自带分包策略) +# 不包含Android gradle 插件自动生成的miandex列表.(不使用建议的依赖树,注释掉表示使用,否则-just activity无效) #-donot-use-suggest -# 不进行dex分包, 直到 dex 的id数量超过 65536.(设置自动执行分包策略) +# (分割每个dex的方法数上限) 扩展参数:例如 --set-max-idx-number=50000 +# 如果出现 DexException: Too many classes in --main-dex-list, main dex capacity exceeded: +# 表明限制的方法数小于main dex的必要方法数,调大到合适数值即可 +-dex-param --set-max-idx-number=4000 + +# 注释掉将执行自定义dex分包,否则执行默认分包. #-auto-maindex # 显示miandex的日志. diff --git a/DexKnifePlugin/app/maindexlist.txt b/DexKnifePlugin/app/maindexlist.txt index 53a33c4..72c71a2 100644 --- a/DexKnifePlugin/app/maindexlist.txt +++ b/DexKnifePlugin/app/maindexlist.txt @@ -1,67 +1,5 @@ rx/android/concurrency/AndroidSchedulers.class rx/android/concurrency/HandlerThreadScheduler.class -rx/annotations/Beta.class -rx/annotations/Experimental.class -android/support/annotation/StyleableRes.class -android/support/annotation/IntDef.class -android/support/annotation/AnyRes.class -android/support/annotation/AnimRes.class -android/support/annotation/AttrRes.class -android/support/annotation/Nullable.class -android/support/annotation/StyleRes.class -android/support/annotation/StringRes.class -android/support/annotation/MenuRes.class -android/support/annotation/NonNull.class -android/support/annotation/XmlRes.class -android/support/annotation/ArrayRes.class -android/support/annotation/InterpolatorRes.class -android/support/annotation/IntegerRes.class -android/support/annotation/FractionRes.class -android/support/annotation/AnimatorRes.class -android/support/annotation/DimenRes.class -android/support/annotation/RawRes.class -android/support/annotation/PluralsRes.class -android/support/annotation/BoolRes.class -android/support/annotation/DrawableRes.class -android/support/annotation/LayoutRes.class -android/support/annotation/IdRes.class -android/support/annotation/StringDef.class -android/support/annotation/ColorRes.class -android/support/multidex/MultiDex$V14.class -android/support/multidex/MultiDex$V19.class -android/support/multidex/MultiDex$V4.class -android/support/multidex/MultiDex.class -android/support/multidex/MultiDexExtractor$1.class -android/support/multidex/MultiDexExtractor.class -android/support/multidex/ZipUtil$CentralDirectory.class -android/support/multidex/ZipUtil.class -android/support/v7/view/ActionMode.class -android/support/v7/view/ActionMode$Callback.class -android/support/v7/app/ActionBar$TabListener.class -android/support/v7/app/ActionBarDrawerToggle$DelegateProvider.class -android/support/v7/app/ActionBar$OnMenuVisibilityListener.class -android/support/v7/app/ActionBarDrawerToggle$Delegate.class -android/support/v7/app/ActionBarActivity.class -android/support/v7/app/ActionBar.class -android/support/v7/app/ActionBar$Tab.class -android/support/v7/app/ActionBar$LayoutParams.class -android/support/v7/app/AppCompatActivity.class -android/support/v7/app/AppCompatCallback.class -android/support/v7/app/ActionBarDrawerToggle.class -android/support/v7/app/ActionBar$OnNavigationListener.class -android/support/v7/app/ActionBar$NavigationMode.class -android/support/v7/app/ActionBar$DisplayOptions.class -android/support/v7/app/AppCompatDelegate.class -android/support/v7/internal/view/menu/MenuItemImpl.class -android/support/v7/internal/widget/AdapterViewCompat.class -android/support/v7/internal/widget/ViewUtils.class -android/support/v7/internal/widget/TintTypedArray.class -android/support/v7/widget/Toolbar.class -android/support/v7/widget/LinearLayoutCompat$OrientationMode.class -android/support/v7/widget/LinearLayoutCompat.class -android/support/v7/widget/LinearLayoutCompat$DividerMode.class -android/support/v7/widget/LinearLayoutCompat$LayoutParams.class -android/support/v7/widget/ActionMenuView$LayoutParams.class android/support/v4/view/GravityCompat.class android/support/v4/view/ViewCompat$AccessibilityLiveRegion.class android/support/v4/view/MenuCompat.class @@ -129,12 +67,74 @@ android/support/v4/widget/SlidingPaneLayout.class android/support/v4/widget/DrawerLayout$DrawerListener.class android/support/v4/widget/MaterialProgressDrawable$StartCurveInterpolator.class android/support/v4/widget/ResourceCursorAdapter.class +android/support/v7/view/ActionMode.class +android/support/v7/view/ActionMode$Callback.class +android/support/v7/app/ActionBar$TabListener.class +android/support/v7/app/ActionBarDrawerToggle$DelegateProvider.class +android/support/v7/app/ActionBar$OnMenuVisibilityListener.class +android/support/v7/app/ActionBarDrawerToggle$Delegate.class +android/support/v7/app/ActionBarActivity.class +android/support/v7/app/ActionBar.class +android/support/v7/app/ActionBar$Tab.class +android/support/v7/app/ActionBar$LayoutParams.class +android/support/v7/app/AppCompatActivity.class +android/support/v7/app/AppCompatCallback.class +android/support/v7/app/ActionBarDrawerToggle.class +android/support/v7/app/ActionBar$OnNavigationListener.class +android/support/v7/app/ActionBar$NavigationMode.class +android/support/v7/app/ActionBar$DisplayOptions.class +android/support/v7/app/AppCompatDelegate.class +android/support/v7/internal/view/menu/MenuItemImpl.class +android/support/v7/internal/widget/AdapterViewCompat.class +android/support/v7/internal/widget/ViewUtils.class +android/support/v7/internal/widget/TintTypedArray.class +android/support/v7/widget/Toolbar.class +android/support/v7/widget/LinearLayoutCompat$OrientationMode.class +android/support/v7/widget/LinearLayoutCompat.class +android/support/v7/widget/LinearLayoutCompat$DividerMode.class +android/support/v7/widget/LinearLayoutCompat$LayoutParams.class +android/support/v7/widget/ActionMenuView$LayoutParams.class +android/support/annotation/StyleableRes.class +android/support/annotation/IntDef.class +android/support/annotation/AnyRes.class +android/support/annotation/AnimRes.class +android/support/annotation/AttrRes.class +android/support/annotation/Nullable.class +android/support/annotation/StyleRes.class +android/support/annotation/StringRes.class +android/support/annotation/MenuRes.class +android/support/annotation/NonNull.class +android/support/annotation/XmlRes.class +android/support/annotation/ArrayRes.class +android/support/annotation/InterpolatorRes.class +android/support/annotation/IntegerRes.class +android/support/annotation/FractionRes.class +android/support/annotation/AnimatorRes.class +android/support/annotation/DimenRes.class +android/support/annotation/RawRes.class +android/support/annotation/PluralsRes.class +android/support/annotation/BoolRes.class +android/support/annotation/DrawableRes.class +android/support/annotation/LayoutRes.class +android/support/annotation/IdRes.class +android/support/annotation/StringDef.class +android/support/annotation/ColorRes.class +rx/annotations/Beta.class +rx/annotations/Experimental.class +android/support/multidex/MultiDex$V14.class +android/support/multidex/MultiDex$V19.class +android/support/multidex/MultiDex$V4.class +android/support/multidex/MultiDex.class +android/support/multidex/MultiDexApplication.class +android/support/multidex/MultiDexExtractor$1.class +android/support/multidex/MultiDexExtractor.class +android/support/multidex/ZipUtil$CentralDirectory.class +android/support/multidex/ZipUtil.class android/support/v4/view/LayoutInflaterFactory.class android/support/v4/app/ActivityCompatHoneycomb.class android/support/v7/appcompat/R$styleable.class android/support/v7/appcompat/R.class com/ceabie/demo/AppApplication.class -com/ceabie/demo/FirstActivity.class com/ceabie/demo/MainActivity$1.class com/ceabie/demo/MainActivity.class demo/ceabie/com/demo/R$id.class diff --git a/DexKnifePlugin/app/mutidex.jks b/DexKnifePlugin/app/mutidex.jks new file mode 100644 index 0000000..ed54544 Binary files /dev/null and b/DexKnifePlugin/app/mutidex.jks differ diff --git a/DexKnifePlugin/app/src/main/java/com/ceabie/demo/MainActivity2.java b/DexKnifePlugin/app/src/main/java/com/ceabie/demo/MainActivity2.java new file mode 100644 index 0000000..b5984a5 --- /dev/null +++ b/DexKnifePlugin/app/src/main/java/com/ceabie/demo/MainActivity2.java @@ -0,0 +1,59 @@ +package com.ceabie.demo; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.TextView; + +import demo.ceabie.com.demo.R; +import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.functions.Func1; +import rx.schedulers.Schedulers; + +public class MainActivity2 extends AppCompatActivity { + + private TextView mViewById; + private long mMillis; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + mViewById = (TextView) findViewById(R.id.text); + + findViewById(R.id.btn_save_photo).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int dfg = 12111111; + Observable.just(1, 2, dfg) + .map(new Func1() { + @Override + public Integer call(Integer integer) { + return integer + 10; + } + }) +// .flatMap(new Func1>() { +// @Override +// public Observable call(Integer integer) { +// return Observable.just(integer + 10); +// } +// }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe(new Action1() { + @Override + public void call(Integer integer) { + log(String.valueOf(integer)); + } + }); + } + }); + } + + + private void log(final String stext) { + mViewById.setText(mViewById.getText().toString() + "\n" + stext); + } +} diff --git a/DexKnifePlugin/app/src/main/res/values/strings.xml b/DexKnifePlugin/app/src/main/res/values/strings.xml index 8d40eb8..0a5576f 100644 --- a/DexKnifePlugin/app/src/main/res/values/strings.xml +++ b/DexKnifePlugin/app/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - demo + MultiDexPluginApp Hello world! Settings diff --git a/DexKnifePlugin/build.gradle b/DexKnifePlugin/build.gradle index 37499a0..0e9a366 100644 --- a/DexKnifePlugin/build.gradle +++ b/DexKnifePlugin/build.gradle @@ -1,13 +1,13 @@ buildscript { repositories { - maven { url uri('repo') } + //maven { url uri('./repo') } jcenter() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' - classpath 'com.ceabie.dextools:gradle-dexknife-plugin:2.0.1' + classpath 'com.android.tools.build:gradle:2.2.3' + classpath 'com.library.tangxiaolv:dexknife-plus:1.0.3' } } diff --git a/DexKnifePlugin/gradle-dexknife-plugin/.gitignore b/DexKnifePlugin/dexknife-plus/.gitignore similarity index 100% rename from DexKnifePlugin/gradle-dexknife-plugin/.gitignore rename to DexKnifePlugin/dexknife-plus/.gitignore diff --git a/DexKnifePlugin/dexknife-plus/build.gradle b/DexKnifePlugin/dexknife-plus/build.gradle new file mode 100644 index 0000000..02e3c83 --- /dev/null +++ b/DexKnifePlugin/dexknife-plus/build.gradle @@ -0,0 +1,75 @@ +buildscript { + repositories { + mavenLocal() + jcenter() + } + + dependencies { + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' + } +} + +apply plugin: 'groovy' +apply plugin: 'com.jfrog.bintray' + +configurations { + provided { + dependencies.all { dep -> + configurations.default.exclude group: dep.group, module: dep.name + } + } + compile.extendsFrom provided +} + +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' +} + +tasks.withType(Javadoc) { +// enabled = false //禁用生成javadoc的任务 + options.encoding = "UTF-8" +} + +ext { + bintrayRepo = 'maven' + bintrayName = "$LIBRARY_NAME" //maven 仓库中的包名 + + publishedGroupId = "$GROUP_ID" + libraryName = "$LIBRARY_NAME" + artifact = "$LIBRARY_NAME"//必须跟Model名一样 + + libraryDescription = 'android multidex plugin' + + siteUrl = 'https://github.com/TangXiaoLv/Android-Easy-MultiDex' + gitUrl = 'https://github.com/TangXiaoLv/Android-Easy-MultiDex.git' + + libraryVersion = "$PUBLIC_VERSION" + + developerId = 'tangxiaolv' + developerName = 'XiaoLv Tang' + developerEmail = 'imbatang@gmail.com' + + licenseName = 'The Apache Software License, Version 2.0' + licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + allLicenses = ["Apache-2.0"] +} + +// Place it at the end of the file +apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' +apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle' + +uploadArchives { + repositories { + mavenDeployer { + repository(url: uri('../repo')) + pom.groupId = "$GROUP_ID" + pom.artifactId = "$LIBRARY_NAME" + pom.version = "$LOCAL_VERSION" + } + } +} diff --git a/DexKnifePlugin/dexknife-plus/gradle.properties b/DexKnifePlugin/dexknife-plus/gradle.properties new file mode 100644 index 0000000..2f24490 --- /dev/null +++ b/DexKnifePlugin/dexknife-plus/gradle.properties @@ -0,0 +1,6 @@ +#Gradle:groupId:libraryName:publicVersion +LOCAL_VERSION=0.0.5 +PUBLIC_VERSION=1.0.4 +GROUP_ID=com.library.tangxiaolv +#Modelһ +LIBRARY_NAME=dexknife-plus diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifeExtension.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifeExtension.groovy new file mode 100644 index 0000000..31795a9 --- /dev/null +++ b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifeExtension.groovy @@ -0,0 +1,7 @@ +package com.tangxiaolv.dexknife + +class DexKnifeExtension { + boolean enabled = false + String productFlavor = "" + String buildType = "" +} diff --git a/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifePlusPlugin.groovy b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifePlusPlugin.groovy new file mode 100644 index 0000000..c19971b --- /dev/null +++ b/DexKnifePlugin/dexknife-plus/src/main/groovy/com/tangxiaolv/dexknife/DexKnifePlusPlugin.groovy @@ -0,0 +1,98 @@ +/* + * 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.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 DexKnifePlusPlugin implements Plugin { + + @Override + void apply(Project project) { + + DexKnifeExtension dexKnifeExtension = project.extensions.create('dexKnife', DexKnifeExtension) + project.afterEvaluate { + boolean hasApp = project.plugins.hasPlugin("com.android.application") + print("-hasApp = ${hasApp}\n") + if (!hasApp) { + throw new IllegalStateException("'android' plugin required.") + } + + final def variants = project.android.applicationVariants + variants.each{variant -> + if (dexKnifeExtension.enabled) { + boolean checkProductFlavor = dexKnifeExtension.productFlavor == "" || dexKnifeExtension.productFlavor.equalsIgnoreCase(variant.flavorName) + boolean checkBuildType = dexKnifeExtension.buildType == "" || dexKnifeExtension.buildType.equalsIgnoreCase(variant.buildType.name) + if (checkProductFlavor && checkBuildType) { + printf "-DexKnifePlugin Enable = true\n"; + printf "-DexKnifePlugin checkProductFlavor = ${checkProductFlavor}\n"; + printf "-DexKnifePlugin checkBuildType = ${checkBuildType}\n"; + printf "-DexKnifePlugin buildType.name = ${variant.buildType.name}\n"; + printf "-DexKnifePlugin flavorName = ${variant.flavorName}\n"; + + filterActivity(project); + + DexKnifePlugin.dexKnifeProcessVariant(project, variant) + } + } else { + printf "-DexKnifePlugin Enable = false\n"; + } + } + } + } + + //filter Activity + private static void filterActivity(Project project) { + File file = project.file(DexSplitTools.DEX_KNIFE_CFG_TXT) + if (file != null) { + def justActivitys = []; + file.eachLine { line -> + //printf "read line ${line}\n"; + if (line.startsWith('-just activity')) { + line = line.replaceAll('-just activity', '').trim(); + justActivitys.add(line) + } + } + printf "-just activity size = ${justActivitys.size()}\n"; + if (justActivitys.size() != 0) { + project.tasks.each { task -> + if (task.name.startsWith('collect') && task.name.endsWith('MultiDexComponents')) { + println "main-dex-filter: found task $task.name" + task.filter { name, attrs -> + String componentName = attrs.get('android:name') + if ('activity'.equals(name)) { + def result = justActivitys.find { + componentName.endsWith("${it}") + } + def bool = result != null; + if (bool) { + printf "main-dex-filter: keep ${componentName}\n" + } + return bool + } + return true + } + } + } + } + } + } +} \ 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 new file mode 100644 index 0000000..c2ec48d --- /dev/null +++ b/DexKnifePlugin/dexknife-plus/src/main/resources/META-INF/gradle-plugins/dexknifePlus.properties @@ -0,0 +1 @@ +implementation-class=com.tangxiaolv.dexknife.DexKnifePlusPlugin diff --git a/DexKnifePlugin/gradle-dexknife-plugin/build.gradle b/DexKnifePlugin/gradle-dexknife-plugin/build.gradle deleted file mode 100644 index eb1f4fa..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/build.gradle +++ /dev/null @@ -1,48 +0,0 @@ -buildscript { - repositories { - mavenLocal() - jcenter() - } - dependencies { - classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.1.1" - classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.3" - } -} - -apply plugin: 'groovy' -apply plugin: 'maven' -apply plugin: 'maven-publish' -apply plugin: 'idea' -apply plugin: 'com.jfrog.artifactory' -apply plugin: 'com.jfrog.bintray' - -repositories { - jcenter() -} - -configurations { - provided { - dependencies.all { dep -> - configurations.default.exclude group: dep.group, module: dep.name - } - } - compile.extendsFrom provided -} - -dependencies { - compile gradleApi() - compile localGroovy() - provided 'com.android.tools.build:builder:1.5.0' - provided 'com.android.tools.build:gradle-core:1.5.0' -} - -uploadArchives { - repositories { - mavenDeployer { - repository(url: uri('../repo')) - pom.version = "2.0.1" - pom.artifactId = "gradle-dexknife-plugin" - pom.groupId = "com.ceabie.dextools" - } - } -} \ No newline at end of file diff --git a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/ClassFileTreeElement.java b/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/ClassFileTreeElement.java deleted file mode 100644 index f08b325..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/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/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexKnifeConfig.java b/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexKnifeConfig.java deleted file mode 100644 index cc217e2..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexKnifeConfig.java +++ /dev/null @@ -1,32 +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 { - public PatternSet patternSet; - public boolean useSuggest = true; - public boolean logMainList = false; - public Set additionalParameters; -} diff --git a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexKnifePlugin.groovy b/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexKnifePlugin.groovy deleted file mode 100644 index 9752664..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexKnifePlugin.groovy +++ /dev/null @@ -1,99 +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.Plugin -import org.gradle.api.Project - -/** - * the spilt tools plugin. - * - * @author ceabie - */ -public class DexKnifePlugin implements Plugin { - - @Override - void apply(Project project) { - //过滤Activity组件 - project.afterEvaluate { - File file = project.file(DexSplitTools.DEX_KNIFE_CFG_TXT) - if (file != null) { - def justActivitys = []; - file.eachLine { line -> - //printf "read line ${line}\n"; - if (line.startsWith('-just activity')) { - line = line.replaceAll('-just activity', '').trim(); - justActivitys.add(line) - } - } - printf "-just activity size = ${justActivitys.size()}\n"; - if (justActivitys.size() != 0) { - project.tasks.each { task -> - if (task.name.startsWith('collect') && task.name.endsWith('MultiDexComponents')) { - println "main-dex-filter: found task $task.name" - task.filter { name, attrs -> - String componentName = attrs.get('android:name') - if ('activity'.equals(name)) { - def result = justActivitys.find { - componentName.endsWith("${it}") - } - def bool = result != null; - if (bool) { - printf "main-dex-filter: keep ${componentName}\n" - } - return bool - } - return true - } - } - } - } - } - } - - project.afterEvaluate { - for (variant in project.android.applicationVariants) { - 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."); - } - } - } - } - - 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/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java b/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java deleted file mode 100644 index 3981935..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexSplitTools.java +++ /dev/null @@ -1,374 +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.Spec; -import org.gradle.api.specs.Specs; -import org.gradle.api.tasks.util.PatternSet; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -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 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; - } - - return genMainDexList(project, minifyEnabled, mappingFile, jarMergingOutputFile, - andMainDexList, dexKnifeConfig); - } - - /** - * 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(); - - boolean minimalMainDex = true; - - Set addParams = new HashSet<>(); - - String line; - ArrayList splitToSecond = new ArrayList<>(); - ArrayList keepMain = new ArrayList<>(); - - 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(); - - System.out.println("DexKnife Config: " + cmd); - - if (DEX_KNIFE_CFG_AUTO_MAINDEX.equals(cmd)) { - minimalMainDex = false; - } else if (cmd.startsWith(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 (cmd.startsWith(DEX_KNIFE_CFG_SPLIT)) { - String sPattern = line.substring(DEX_KNIFE_CFG_SPLIT.length()).trim(); - addClassFilePath(sPattern, splitToSecond); - - } else if (cmd.startsWith(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_LOG_MAIN_DEX.equals(cmd)) { - dexKnifeConfig.logMainList = true; - - } else if (!cmd.startsWith("-")) { - addClassFilePath(line, splitToSecond); - } - } - - reader.close(); - - if (minimalMainDex) { - addParams.add(DEX_MINIMAL_MAIN_DEX); - } - - if (!splitToSecond.isEmpty() || !keepMain.isEmpty()) { - dexKnifeConfig.patternSet = new PatternSet() - .exclude(splitToSecond) - .include(keepMain); - getMaindexSpec(dexKnifeConfig.patternSet); - } else { - dexKnifeConfig.useSuggest = true; - System.err.println("DexKnife Warning: NO SET split Or keep path, it will use Suggest!"); - } - - dexKnifeConfig.additionalParameters = addParams; - - return dexKnifeConfig; - } - - /** - * add the class path to pattern list, and the single class pattern can work. - */ - private static void addClassFilePath(String classPath, List 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 = Specs.or(includeSpec, Specs.not(excludeSpec)); - } else { - maindexSpec = excludeSpec != null? Specs.not(excludeSpec): includeSpec; - } - } - - if (maindexSpec == null) { - maindexSpec = Specs.satisfyNone(); - } - - return maindexSpec; - } - - /** - * 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"); - - // get the adt's maindexlist - HashSet mainCls = null; - if (dexKnifeConfig.useSuggest) { - mainCls = getAdtMainDexClasses(andMainDexList); - System.out.println("DexKnife: use suggest"); - } - - 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); - } else { - System.err.println("DexKnife: From Merged Jar: " + jarMergingOutputFile); - if (jarMergingOutputFile != null) { - // get classes from merged jar - mainClasses = getMainClassesFromJar(jarMergingOutputFile, dexKnifeConfig.patternSet, mainCls); - } else { - System.err.println("DexKnife: The Merged Jar is not exist! Can't be processed!"); - } - } - - 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!"); - } - - private static ArrayList getMainClassesFromJar( - File jarMergingOutputFile, PatternSet mainDexPattern, HashSet mainCls) throws Exception { - ZipFile clsFile = new ZipFile(jarMergingOutputFile); - Spec asSpec = getMaindexSpec(mainDexPattern); - ClassFileTreeElement treeElement = new ClassFileTreeElement(); - - 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 (asSpec.isSatisfiedBy(treeElement) - || (mainCls != null && mainCls.contains(entryName))) { - mainDexList.add(entryName); - } - } - } - - clsFile.close(); - - return mainDexList; - } - - private static ArrayList getMainClassesFromMapping( - File mapping, - PatternSet mainDexPattern, - HashSet mainCls) throws Exception { - - String line; - ArrayList mainDexList = new ArrayList<>(); - BufferedReader reader = new BufferedReader(new FileReader(mapping)); - - ClassFileTreeElement treeElement = 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 sOrg = line.substring(0, flagPos).replace('.', '/') + CLASS_SUFFIX; - treeElement.setClassPath(sOrg); - - 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); - } - } - } - } - - reader.close(); - - return mainDexList; - } - - /** - * get the maindexlist of android gradle plugin - */ - private static HashSet getAdtMainDexClasses(File outputDir) throws Exception { - if (outputDir == null || !outputDir.exists()) { - System.err.println("DexKnife Warning: Android recommand Main dex is no exist, try run again!"); - return null; - } - - HashSet mainCls = new HashSet<>(); - BufferedReader reader = new BufferedReader(new FileReader(outputDir)); - - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (line.endsWith(CLASS_SUFFIX)) { - mainCls.add(line); - } - } - - reader.close(); - - if (mainCls.size() == 0) { - mainCls = null; - } - - return mainCls; - } -} \ No newline at end of file diff --git a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/MultiDexAndroidBuilder.groovy b/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/MultiDexAndroidBuilder.groovy deleted file mode 100644 index 2c41694..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/MultiDexAndroidBuilder.groovy +++ /dev/null @@ -1,112 +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.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 java.lang.reflect.Field - -/** - * proxy the androidBuilder that plugin 1.5.0 to add '--minimal-main-dex' options. - * - * @author ceabie - */ -public class MultiDexAndroidBuilder extends AndroidBuilder { - - Collection mAddParams; - - public MultiDexAndroidBuilder(String projectId, - String createdBy, - ProcessExecutor processExecutor, - JavaProcessExecutor javaProcessExecutor, - ErrorReporter errorReporter, - ILogger logger, - boolean verboseExec) { - super(projectId, createdBy, processExecutor, javaProcessExecutor, errorReporter, logger, verboseExec) - } - - @Override - 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 { - - if (mAddParams != null) { - if (additionalParameters == null) { - additionalParameters = [] - } - - additionalParameters += mAddParams //'--minimal-main-dex' - } - - super.convertByteCode(inputs, outDexFolder, multidex, mainDexList, dexOptions, - additionalParameters, incremental, optimize, processOutputHandler) - } - -// public static void proxyAndroidBuilder(TransformTask task) { -// task.setAndroidBuilder(getProxyAndroidBuilder(task.getBuilder())) -// } - - 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) { - MultiDexAndroidBuilder myAndroidBuilder = new MultiDexAndroidBuilder( - orgAndroidBuilder.mProjectId, - orgAndroidBuilder.mCreatedBy, - orgAndroidBuilder.getProcessExecutor(), - orgAndroidBuilder.mJavaProcessExecutor, - orgAndroidBuilder.getErrorReporter(), - orgAndroidBuilder.getLogger(), - orgAndroidBuilder.mVerboseExec) - - myAndroidBuilder.setTargetInfo( - orgAndroidBuilder.getSdkInfo(), - orgAndroidBuilder.getTargetInfo(), - orgAndroidBuilder.mLibraryRequests) - - myAndroidBuilder.mAddParams = addParams -// myAndroidBuilder.mBootClasspathFiltered = orgAndroidBuilder.mBootClasspathFiltered -// myAndroidBuilder.mBootClasspathAll = orgAndroidBuilder.mBootClasspathAll - - myAndroidBuilder - } - - private static Field accessibleField(Class cls, String field) { - Field f = cls.getDeclaredField(field) - f.setAccessible(true) - f - } -} diff --git a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/SplitToolsFor130.groovy b/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/SplitToolsFor130.groovy deleted file mode 100644 index 58fdba5..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/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/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy b/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy deleted file mode 100644 index d4d503a..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/SplitToolsFor150.groovy +++ /dev/null @@ -1,113 +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.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, Object variant) { - 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 - - println("DexKnife: task: " + transformName) -// 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 - - 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)) { - - // 替换 AndroidBuilder - MultiDexAndroidBuilder.proxyAndroidBuilder(dexTransform, - dexKnifeConfig.additionalParameters) - - // 替换这个文件 - fileAdtMainList.delete() - project.copy { - from 'maindexlist.txt' - into fileAdtMainList.parentFile - } - } - - endDexKnife() - } - } - } -} \ No newline at end of file diff --git a/DexKnifePlugin/gradle-dexknife-plugin/src/main/resources/META-INF/gradle-plugins/com.ceabie.dexnkife.properties b/DexKnifePlugin/gradle-dexknife-plugin/src/main/resources/META-INF/gradle-plugins/com.ceabie.dexnkife.properties deleted file mode 100644 index 24abf7f..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/src/main/resources/META-INF/gradle-plugins/com.ceabie.dexnkife.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=com.ceabie.dexknife.DexKnifePlugin diff --git a/DexKnifePlugin/gradle-dexknife-plugin/temp/AbstractSplitTools.groovy b/DexKnifePlugin/gradle-dexknife-plugin/temp/AbstractSplitTools.groovy deleted file mode 100644 index d01d206..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/temp/AbstractSplitTools.groovy +++ /dev/null @@ -1,159 +0,0 @@ -package com.ceabie.dexknife - -import org.gradle.api.Project - - -/** - * the base of spilt tools. - * - * @author ceabie - */ -public abstract class AbstractSplitTools { - protected Project mProject; - - public AbstractSplitTools(Project project) { - mProject = project - } - - public abstract void processSplitDex(Object variant); - - public static void processMainDexList(Project project, Object variant, File mergedJar) { - genMainDexList(project, variant, getSecondPackages(project), mergedJar) - } - - protected void processMainDexList(Object variant, File mergedJar) { - genMainDexList(mProject, variant, getSecondPackages(mProject), mergedJar) - } - - /** - * 获得第二个分包的类过滤列表 - */ - private static ArrayList getSecondPackages(Project project) { - ArrayList secDexPackages = new ArrayList<>() - project.file("second_dex_package_list.txt").withReader { r -> - for (it in r.readLines()) { - String s = it.trim() - if (s.size() > 0) { - secDexPackages.add(s) - } - } - } - - return secDexPackages - } - - /** - * 生成主dex的类列表 - */ - private static void genMainDexList(Project project, Object variant, - List secDexPackages, File mergedJar) { - println ":genMainDexList" - - String[] secPackages = null - HashSet secPackageSet = null - def scope = variant.getVariantData().getScope() - - if (variant.buildType.minifyEnabled) { - // 从mapping文件中收集混淆后的 class - File mapping = variant.mappingFile; - secPackageSet = getClassesFromMapping(mapping, secDexPackages) - - if (mergedJar == null) { - mergedJar = scope.proguardOutputFile - } - } else { - def size = secDexPackages.size() - secPackages = new String[size] - for (int i = 0; i < size; i++) { - secPackages[i] = secDexPackages.get(i).replace('.', '/') - } - - if (mergedJar == null) { - // multi-dex/allclasses.jar - mergedJar = scope.jarMergingOutputFile - } - } - - File keepFile = project.file("maindexlist.txt") - keepFile.delete() - - // 获得 ADT 推荐的 maindexlist - File andMainDexList = scope.mainDexListFile - HashSet mainCls = getAdtMainDexClasses(andMainDexList); - - def clsfile = new java.util.zip.ZipFile(mergedJar) - - for (entry in clsfile.entries()) { - String entryName = entry.getName() - - if (entryName.endsWith(".class")) { - boolean isSecDex = false - if (secPackageSet != null) { - isSecDex = secPackageSet.contains(entryName) - } else if (secPackages != null) { - for (String pack : secPackages) { - if (entryName.startsWith(pack)) { - isSecDex = true - break - } - } - } - - // 如果ADT的类在主dex,则不放在第二个dex - if (isSecDex && mainCls != null && mainCls.contains(entryName)) { - isSecDex = false; - } - - if (!isSecDex) { - keepFile.withWriterAppend { w -> - w << entryName << '\n' - } - } else { - println entryName - } - } - - } - - clsfile.close() - } - - private static HashSet getClassesFromMapping(File mapping, List secDexPackages) { - HashSet secPackSet = new HashSet<>(); - mapping.withReader { r -> - for (line in r.readLines()) { - for (it in secDexPackages) { - if (line.startsWith(it)) { - int ip = line.indexOf("-> ") - if (ip != -1) { - def sMap = line.substring(ip + 3, line.length() - 1) - secPackSet.add(sMap.replace('.', '/') + ".class") - } - } - } - } - } - - return secPackSet; - } - - /** - * 获取系统推荐在主dex的列表 - */ - private static HashSet getAdtMainDexClasses(File outputDir) { - HashSet mainCls = new HashSet<>() - outputDir.withReader { r -> - for (it in r.readLines()) { - if (it.endsWith(".class")) { - mainCls.add(it) - } - } - } - - if (mainCls.size() == 0) { - mainCls = null - } - - return mainCls - } -} \ No newline at end of file diff --git a/DexKnifePlugin/gradle-dexknife-plugin/temp/MultiDexAndroidBuilder.java b/DexKnifePlugin/gradle-dexknife-plugin/temp/MultiDexAndroidBuilder.java deleted file mode 100644 index 387c2d7..0000000 --- a/DexKnifePlugin/gradle-dexknife-plugin/temp/MultiDexAndroidBuilder.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.ceabie.dexknife; - -import com.android.build.gradle.internal.transforms.DexTransform; -import com.android.builder.core.AndroidBuilder; -import com.android.builder.core.ErrorReporter; -import com.android.ide.common.process.JavaProcessExecutor; -import com.android.ide.common.process.ProcessExecutor; -import com.android.utils.ILogger; - -import java.lang.reflect.Field; - -/** - * proxy the androidBuilder that plugin 1.5.0 to add '--minimal-main-dex' options. - * - * @author ceabie - */ -public class MultiDexAndroidBuilder extends AndroidBuilder { - public MultiDexAndroidBuilder(String projectId, - String createdBy, - ProcessExecutor processExecutor, - JavaProcessExecutor javaProcessExecutor, - ErrorReporter errorReporter, - ILogger logger, - boolean verboseExec) { - - super(projectId, createdBy, processExecutor, - javaProcessExecutor, errorReporter, - logger, verboseExec); - } - - public static void proxyAndroidBuilder(DexTransform transform) throws Exception { - Field fieldAndroidBuilder = accessibleField(DexTransform.class, "androidBuilder"); - AndroidBuilder orgAndroidBuilder = (AndroidBuilder) fieldAndroidBuilder.get(transform); - fieldAndroidBuilder.set(transform, getProxyAndroidBuilder(orgAndroidBuilder)); - } - - private static AndroidBuilder getProxyAndroidBuilder(AndroidBuilder orgAndroidBuilder) throws Exception { - - Field fieldProjectId = accessibleField(AndroidBuilder.class, "mProjectId"); - Field fieldCreatedBy = accessibleField(AndroidBuilder.class, "mCreatedBy"); - Field fieldJavaProcessExecutor = accessibleField(AndroidBuilder.class, "mJavaProcessExecutor"); - Field fieldVerboseExec = accessibleField(AndroidBuilder.class, "mVerboseExec"); - Field fieldLibraryRequests = accessibleField(AndroidBuilder.class, "mLibraryRequests"); - - MultiDexAndroidBuilder myAndroidBuilder = new MultiDexAndroidBuilder( - (String) fieldProjectId.get(orgAndroidBuilder), - (String) fieldCreatedBy.get(orgAndroidBuilder), - orgAndroidBuilder.getProcessExecutor(), - (JavaProcessExecutor)fieldJavaProcessExecutor.get(orgAndroidBuilder), - orgAndroidBuilder.getErrorReporter(), - orgAndroidBuilder.getLogger(), - (boolean) fieldVerboseExec.get(orgAndroidBuilder)); - - myAndroidBuilder.setTargetInfo( - orgAndroidBuilder.getSdkInfo(), - orgAndroidBuilder.getTargetInfo(), - fieldLibraryRequests.get(orgAndroidBuilder)); - -// myAndroidBuilder.mBootClasspathFiltered = orgAndroidBuilder.mBootClasspathFiltered -// myAndroidBuilder.mBootClasspathAll = orgAndroidBuilder.mBootClasspathAll - - return myAndroidBuilder; - } - - private static Field accessibleField(Class cls, String field) throws NoSuchFieldException { - Field f = cls.getDeclaredField(field); - f.setAccessible(true); - return f; - } -} diff --git a/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties b/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties index 122a0dc..e17444a 100644 --- a/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties +++ b/DexKnifePlugin/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Dec 28 10:00:20 PST 2015 +#Mon Dec 26 17:59:14 CST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/DexKnifePlugin/lib1/.gitignore b/DexKnifePlugin/lib1/.gitignore new file mode 100644 index 0000000..e8fa30f --- /dev/null +++ b/DexKnifePlugin/lib1/.gitignore @@ -0,0 +1,2 @@ +/build +*.iml diff --git a/DexKnifePlugin/lib1/build.gradle b/DexKnifePlugin/lib1/build.gradle new file mode 100644 index 0000000..adaf966 --- /dev/null +++ b/DexKnifePlugin/lib1/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion Integer.parseInt(project.COMPILE_SDK_VER) + buildToolsVersion project.BUILD_TOOLS_VER + + defaultConfig { + minSdkVersion Integer.parseInt(project.MIN_SDK_VER) + targetSdkVersion Integer.parseInt(project.TARGET_SDK_VERSION) + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile "com.android.support:appcompat-v7:${SUPPORT_VERSION}" +} diff --git a/DexKnifePlugin/lib1/proguard-rules.pro b/DexKnifePlugin/lib1/proguard-rules.pro new file mode 100644 index 0000000..8010560 --- /dev/null +++ b/DexKnifePlugin/lib1/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in D:\sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/DexKnifePlugin/lib1/src/main/AndroidManifest.xml b/DexKnifePlugin/lib1/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6d527c3 --- /dev/null +++ b/DexKnifePlugin/lib1/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/DexKnifePlugin/lib1/src/main/res/values/strings.xml b/DexKnifePlugin/lib1/src/main/res/values/strings.xml new file mode 100644 index 0000000..e897d14 --- /dev/null +++ b/DexKnifePlugin/lib1/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Lib1 + diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar deleted file mode 100644 index 289ff04..0000000 Binary files a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar and /dev/null differ diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.md5 b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.md5 deleted file mode 100644 index 31f5310..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -19ba9da317955101b4505c530933fafc \ No newline at end of file diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.sha1 b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.sha1 deleted file mode 100644 index 5027f47..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -499d19de3b48b7e96a495748d808f6f93ecda2df \ No newline at end of file diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom deleted file mode 100644 index af99925..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom +++ /dev/null @@ -1,8 +0,0 @@ - - - 4.0.0 - com.ceabie.dextools - gradle-dexknife-plugin - 2.0.1 - diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.md5 b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.md5 deleted file mode 100644 index 4cb6837..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.md5 +++ /dev/null @@ -1 +0,0 @@ -bde96269e8d5e1098594fb20b7548545 \ No newline at end of file diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.sha1 b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.sha1 deleted file mode 100644 index d63d558..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.sha1 +++ /dev/null @@ -1 +0,0 @@ -15d752decef7fc19c516c16654ea4c7fad4b1ebc \ No newline at end of file diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml deleted file mode 100644 index cbeb5a3..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - com.ceabie.dextools - gradle-dexknife-plugin - - 2.0.1 - - 2.0.1 - - 20160821115305 - - diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.md5 b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.md5 deleted file mode 100644 index 68ccfab..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.md5 +++ /dev/null @@ -1 +0,0 @@ -b530b97185c6934c7e42bafb6a3e0bb0 \ No newline at end of file diff --git a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.sha1 b/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.sha1 deleted file mode 100644 index ddcf329..0000000 --- a/DexKnifePlugin/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.sha1 +++ /dev/null @@ -1 +0,0 @@ -cd50b635b3b3913c447da72f6d4db455d5a03bd8 \ No newline at end of file diff --git a/DexKnifePlugin/settings.gradle b/DexKnifePlugin/settings.gradle index 3319259..303963d 100644 --- a/DexKnifePlugin/settings.gradle +++ b/DexKnifePlugin/settings.gradle @@ -1,4 +1,3 @@ -include ':app' -include ':gradle-dexknife-plugin' - +include ':app', ':lib1' +include ':dexknife-plus' diff --git a/README.md b/README.md index aff9fd0..28cdf90 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,25 @@ -#Android傻瓜式分包插件 +# Deprecated +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) + 注1:不想看前半部分的话可以直接跳过到最下面配置部分。 -注2:本插件是基于[DexKnifePlugin 1.5.3](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。 +注2:本插件是基于[DexKnifePlugin 1.6.2](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/). **解决:** ``` +android{ + defaultConfig { + multiDexEnabled true + } +} + dependencies { compile 'com.android.support:MultiDex:1.0.1' } @@ -22,7 +33,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撑爆了。 **解决:** @@ -41,17 +52,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的所有子类。 @@ -95,49 +106,78 @@ 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左右,从此再也不用担心方法数问题了!!! -##配置部分 -**第一步:将repo目录复制到项目根目录** +## 配置部分 +**第一步:添加分包支持** +``` +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 { - repositories { - maven { - url uri('repo') - } - } - dependencies { - classpath 'com.ceabie.dextools:gradle-dexknife-plugin:2.0.1' + classpath 'com.library.tangxiaolv:dexknife-plus:1.0.4' } } - ``` **第三步:在你的App模块的build.gradle添加插件** ``` -apply plugin: 'com.ceabie.dexnkife' +apply plugin: 'dexknifePlus' +``` +**第四步:配置参数**   +``` +dexKnife{ + //必选参数 + enabled true //if false,禁用分包插件 + //可选参数 + //1.如果没有可选参数,将根据enabled决定是否分包。 + //2.如果有可选参数,需满足必选参数和可选参数的条件才允许分包 + productFlavor 'mock' + buildType 'debug' + + /* + *eg:当前productFlavors = dev,buildType = debug, + *参数组合1:enabled = true,productFlavor = dev,buildType = debug 分包 + *参数组合2:enabled = true,productFlavor = mock,buildType = debug 不分包 + *参数组合1:enabled = true,buildType = debug 所有buildType = debug分包 + *参数组合1:enabled = true,productFlavor = dev 所有productFlavor = dev分包 + * */ +} ``` - -**第四步:在你的App模块目录下新建dexknife.txt,并自定义配置** +**第五步:在你的App模块目录下新建dexknife.txt,并自定义配置** ``` #为注释符 -#-----------主Dex中必要依赖的脚本配置----------- -#默认保留四大组件中其他三大组件,Activity组件选择性保留(使用-just activity 选项),若为空不保留任何Activity +#-----------主Dex中必要依赖的脚本配置-----------(支持依赖检测) +#默认保留四大组件中Service,ContentProvider,BroadcastReceiver三大组件,Activity组件选择性保留,若为空不保留任何Activity -just activity com.ceabie.demo.MainActivity -#-----------附加类----------- +#-----------附加类-----------(不支持依赖检测) # 如果你想要某个包路径在maindex中,则使用 -keep 选项,即使他已经在分包的路径中.若为空,不保留任意类 #-keep com.ceabie.demo.** @@ -149,20 +189,26 @@ apply plugin: 'com.ceabie.dexnkife' #将全部类移出主Dex -split **.** -# 不包含Android gradle 插件自动生成的miandex列表.(不用系统自带分包策略) +# 不包含Android gradle 插件自动生成的miandex列表.(不使用建议的依赖树,注释掉表示使用,否则-just activity无效) #-donot-use-suggest -# 不进行dex分包, 直到 dex 的id数量超过 65536.(设置自动执行分包策略) +# (分割每个dex包的方法数上限) 扩展参数:例如 --set-max-idx-number=50000 +# 如果出现 DexException: Too many classes in --main-dex-list, main dex capacity exceeded: +# 表明限制的方法数小于main dex的必要方法数,调大到合适数值即可 +-dex-param --set-max-idx-number=4000 + +# 注释掉将执行自定义dex分包,否则执行默认分包. #-auto-maindex # 显示miandex的日志. #-log-mainlist - ``` -**第五步:在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用** +**第六步:在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用** + +**使用前先参阅 DexKnife 的[特性部分](https://github.com/ceabie/DexKnifePlugin#特性重要)** -##已知错误 +## 已知错误 注:分包的时候如果发现一些莫名的错误,可以关掉instant run,一般都能解决 @@ -172,7 +218,7 @@ Error:Execution failed for task ':Toon:transformClassesWithDexForDebug'.> java.l ``` 发生此错误只要切换一次Gradle版本就OK了,比如1.5.0 -**错误2:** +**错误2:**(已修复) ``` Unsupported major.minor version 52.0 ``` diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar b/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar deleted file mode 100644 index 289ff04..0000000 Binary files a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar and /dev/null differ diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.md5 b/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.md5 deleted file mode 100644 index 31f5310..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -19ba9da317955101b4505c530933fafc \ No newline at end of file diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.sha1 b/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.sha1 deleted file mode 100644 index 5027f47..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -499d19de3b48b7e96a495748d808f6f93ecda2df \ No newline at end of file diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom b/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom deleted file mode 100644 index af99925..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom +++ /dev/null @@ -1,8 +0,0 @@ - - - 4.0.0 - com.ceabie.dextools - gradle-dexknife-plugin - 2.0.1 - diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.md5 b/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.md5 deleted file mode 100644 index 4cb6837..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.md5 +++ /dev/null @@ -1 +0,0 @@ -bde96269e8d5e1098594fb20b7548545 \ No newline at end of file diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.sha1 b/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.sha1 deleted file mode 100644 index d63d558..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/2.0.1/gradle-dexknife-plugin-2.0.1.pom.sha1 +++ /dev/null @@ -1 +0,0 @@ -15d752decef7fc19c516c16654ea4c7fad4b1ebc \ No newline at end of file diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml b/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml deleted file mode 100644 index cbeb5a3..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - com.ceabie.dextools - gradle-dexknife-plugin - - 2.0.1 - - 2.0.1 - - 20160821115305 - - diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.md5 b/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.md5 deleted file mode 100644 index 68ccfab..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.md5 +++ /dev/null @@ -1 +0,0 @@ -b530b97185c6934c7e42bafb6a3e0bb0 \ No newline at end of file diff --git a/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.sha1 b/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.sha1 deleted file mode 100644 index ddcf329..0000000 --- a/repo/com/ceabie/dextools/gradle-dexknife-plugin/maven-metadata.xml.sha1 +++ /dev/null @@ -1 +0,0 @@ -cd50b635b3b3913c447da72f6d4db455d5a03bd8 \ No newline at end of file