├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── compressed_pictures ├── exclude_pictures.txt ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── wanjian │ │ │ └── tinypngplugin │ │ │ └── demo │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher2.9.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── pad │ └── res │ ├── drawable │ ├── ic_launcher_background_xx.xml │ ├── ic_launcher_round_xxx.png │ ├── img1.png │ ├── img2.png │ ├── img3.png │ └── img4.jpg │ └── layout │ └── activity_main_x.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── module2 ├── .gitignore ├── build.gradle ├── compressed_pictures ├── exclude_pictures.txt ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── res │ ├── drawable │ ├── module2_img1.png │ └── module2_img2.png │ └── values │ └── strings.xml ├── settings.gradle └── tinypng ├── .gitignore ├── build.gradle └── src └── main ├── groovy └── com │ └── wanjian │ └── plugin │ ├── TinyPngPlugin.groovy │ ├── config │ └── TinyPng.groovy │ ├── tasks │ └── TinyPngProcessTask.groovy │ └── utils │ └── MD5.groovy └── resources └── META-INF └── gradle-plugins └── com.wanjian.tinypng.properties /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | ### JetBrains template 12 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 13 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 14 | 15 | # User-specific stuff 16 | .idea/**/workspace.xml 17 | .idea/**/tasks.xml 18 | .idea/**/usage.statistics.xml 19 | .idea/**/dictionaries 20 | .idea/**/shelf 21 | 22 | # Sensitive or high-churn files 23 | .idea/**/dataSources/ 24 | .idea/**/dataSources.ids 25 | .idea/**/dataSources.local.xml 26 | .idea/**/sqlDataSources.xml 27 | .idea/**/dynamic.xml 28 | .idea/**/uiDesigner.xml 29 | .idea/**/dbnavigator.xml 30 | 31 | # Gradle 32 | .idea/**/gradle.xml 33 | .idea/**/libraries 34 | 35 | # Gradle and Maven with auto-import 36 | # When using Gradle or Maven with auto-import, you should exclude module files, 37 | # since they will be recreated, and may cause churn. Uncomment if using 38 | # auto-import. 39 | # .idea/modules.xml 40 | # .idea/*.iml 41 | # .idea/modules 42 | 43 | # CMake 44 | cmake-build-*/ 45 | 46 | # Mongo Explorer plugin 47 | .idea/**/mongoSettings.xml 48 | 49 | # File-based project format 50 | *.iws 51 | 52 | # IntelliJ 53 | out/ 54 | 55 | # mpeltonen/sbt-idea plugin 56 | .idea_modules/ 57 | 58 | # JIRA plugin 59 | atlassian-ide-plugin.xml 60 | 61 | # Cursive Clojure plugin 62 | .idea/replstate.xml 63 | 64 | # Crashlytics plugin (for Android Studio and IntelliJ) 65 | com_crashlytics_export_strings.xml 66 | crashlytics.properties 67 | crashlytics-build.properties 68 | fabric.properties 69 | 70 | # Editor-based Rest Client 71 | .idea/httpRequests 72 | ### Android template 73 | # Built application files 74 | *.apk 75 | *.ap_ 76 | 77 | # Files for the ART/Dalvik VM 78 | *.dex 79 | 80 | # Java class files 81 | *.class 82 | 83 | # Generated files 84 | bin/ 85 | gen/ 86 | out/ 87 | 88 | # Gradle files 89 | .gradle/ 90 | build/ 91 | 92 | # Local configuration file (sdk path, etc) 93 | local.properties 94 | 95 | # Proguard folder generated by Eclipse 96 | proguard/ 97 | 98 | # Log Files 99 | *.log 100 | 101 | # Android Studio Navigation editor temp files 102 | .navigation/ 103 | 104 | # Android Studio captures folder 105 | captures/ 106 | 107 | # IntelliJ 108 | *.iml 109 | .idea/workspace.xml 110 | .idea/tasks.xml 111 | .idea/gradle.xml 112 | .idea/assetWizardSettings.xml 113 | .idea/dictionaries 114 | .idea/libraries 115 | .idea/caches 116 | 117 | # Keystore files 118 | # Uncomment the following line if you do not want to check your keystore files in. 119 | #*.jks 120 | 121 | # External native build folder generated in Android Studio 2.2 and later 122 | .externalNativeBuild 123 | 124 | # Google Services (e.g. APIs or Firebase) 125 | google-services.json 126 | 127 | # Freeline 128 | freeline.py 129 | freeline/ 130 | freeline_project_description.json 131 | 132 | # fastlane 133 | fastlane/report.xml 134 | fastlane/Preview.html 135 | fastlane/screenshots 136 | fastlane/test_output 137 | fastlane/readme.md 138 | ### Java template 139 | # Compiled class file 140 | *.class 141 | 142 | # Log file 143 | *.log 144 | 145 | # BlueJ files 146 | *.ctxt 147 | 148 | # Mobile Tools for Java (J2ME) 149 | .mtj.tmp/ 150 | 151 | # Package Files # 152 | *.jar 153 | *.war 154 | *.nar 155 | *.ear 156 | *.zip 157 | *.tar.gz 158 | *.rar 159 | 160 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 161 | hs_err_pid* 162 | ### macOS template 163 | # General 164 | .DS_Store 165 | .AppleDouble 166 | .LSOverride 167 | 168 | # Icon must end with two \r 169 | Icon 170 | 171 | # Thumbnails 172 | ._* 173 | 174 | # Files that might appear in the root of a volume 175 | .DocumentRevisions-V100 176 | .fseventsd 177 | .Spotlight-V100 178 | .TemporaryItems 179 | .Trashes 180 | .VolumeIcon.icns 181 | .com.apple.timemachine.donotpresent 182 | 183 | # Directories potentially created on remote AFP share 184 | .AppleDB 185 | .AppleDesktop 186 | Network Trash Folder 187 | Temporary Items 188 | .apdisk 189 | 190 | tinypng/repo -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## TinyPng Plugin 2 | `TinyPngPlugin`是一个Android Gradle插件,可以批量压缩项目中的图片 3 | 4 | * 兼容Android Gradle Plugin 2.x-3.x 5 | * 自动识别sourceSets,无需为tinypng plugin配置资源路径 6 | * 可配置若干api key,压缩失败自动更换api key,避免每月500上限 7 | * 可配置图片白名单 8 | * 可配置压缩失败时是否终止Task 9 | * 默认不压缩9.png图片 10 | * 同名替换文件,新增文件都会压缩 11 | 12 | 13 | ### 使用方式 14 | * 在工程根目录中的`build.gradle`文件中的 `buildscript.dependencies`中添加`classpath "com.wanjian.plugin:tinypng:0.0.6"` 例如: 15 | 16 | ``` 17 | buildscript { 18 | repositories { 19 | google() 20 | jcenter() 21 | } 22 | dependencies { 23 | classpath 'com.android.tools.build:gradle:3.0.0' 24 | classpath "com.wanjian.plugin:tinypng:0.0.6" 25 | } 26 | } 27 | 28 | ``` 29 | 30 | * 在各module的`build.gradle`文件添加`apply plugin: "com.wanjian.tinypng"`,同时在该文件中配置如下。 31 | 32 | `enable`控制该module是否开启图片压缩。 33 | 34 | `abortOnError`控制压缩失败时是否终止Task。 35 | 36 | `skip9Png`是否不压缩 9.png图片,默认不压缩。tinypng压缩的9.png图片可能导致打包失败 37 | 38 | `appendCompressRecord`是否在compressed_pictures文件中追加压缩后的图片的MD5值。默认false。false:当productFlavors中配置的资源路径不同时,编译不同的flavor时,压缩的图片的md5值会相互覆盖。true:只追加记录,不删除 39 | 40 | `keys`配置压缩图片需要的tiny png api key,每个key每月最多可以压缩500张图片。 41 | 可以去这[Tiny Developers Page](https://tinypng.com/developers) 申请key,每个key需要一个邮箱,可是使用[临时邮箱](http://www.bccto.me) 42 | ``` 43 | tinyPng { 44 | //http://www.bccto.me/ 临时邮箱申请key 45 | //把下面的keys换成你申请的key,建议多配置几个 46 | enable true 47 | abortOnError false 48 | skip9Png true 49 | appendCompressRecord false 50 | keys = ["FBYz4WZR5tj9S4Jv4tCL5m3KgrQnXBgP", 51 | "1sQXBgXvvhfx5j1l10DKRvVvrlD3rcS4", 52 | "DdMZxbJ7W9K15hSZ6G5QVNbqh7PKGxjX", 53 | "xS2CNP0w7Sp4Xz7P1DvcCZNsQ9QJNsyb", 54 | "X7z8kgM3zw1Fr3R8RQTkhN3Kynx8xpdX", 55 | "mT1td5Qt6JW7yy0n2pkJd6ZwBxmHsjBy", 56 | "ctW1PG2wJhpJYxDhcj4NSgQ14WFxC7gb", 57 | "SWxfXRhZ6H1wnXnd3j5HmbK8wCpvdH0X", 58 | ] 59 | } 60 | 61 | ``` 62 | 63 | * 可以在各module下添`exclude_pictures.txt`文件,资源根目录下的drawable-xx文件夹及mipmap文件夹中的图片路径(以该module作为根路径)包含该文件配置的路径的图片不会压缩 64 | * 也可以手动调用 `./grawablew tinyPngxxx` 压缩图片 65 | * 各module下的`compressed_pictures`文件是tinypng plugin自动生成的,不要手动修改里面的内容,该module中压缩后的图片的md5值都记录在这里面 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: "com.wanjian.tinypng" 3 | android { 4 | compileSdkVersion 28 5 | buildToolsVersion "28.0.3" 6 | defaultConfig { 7 | applicationId "com.wanjian.tinypngplugin.demo" 8 | minSdkVersion 19 9 | targetSdkVersion 28 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | flavorDimensions "api" 20 | 21 | productFlavors { 22 | demo { 23 | // Assigns this product flavor to the "mode" flavor dimension. 24 | dimension "api" 25 | } 26 | 27 | full { 28 | dimension "api" 29 | } 30 | 31 | // Configurations in the "api" product flavors override those in "mode" 32 | // flavors and the defaultConfig {} block. Gradle determines the priority 33 | // between flavor dimensions based on the order in which they appear next 34 | // to the flavorDimensions property above--the first dimension has a higher 35 | // priority than the second, and so on. 36 | // minApi24 { 37 | // dimension "api" 38 | // minSdkVersion '24' 39 | // // To ensure the target device receives the version of the app with 40 | // // the highest compatible API level, assign version codes in increasing 41 | // // value with API level. To learn more about assigning version codes to 42 | // // support app updates and uploading to Google Play, read Multiple APK Support 43 | // versionCode 30000 + android.defaultConfig.versionCode 44 | // versionNameSuffix "-minApi24" 45 | // } 46 | 47 | 48 | } 49 | sourceSets { 50 | demo { 51 | res.srcDirs = ['src/main/res', 'src/pad/res'] 52 | } 53 | } 54 | } 55 | 56 | dependencies { 57 | compile fileTree(include: ['*.jar'], dir: 'libs') 58 | compile project(':module2') 59 | } 60 | 61 | tinyPng { 62 | //http://www.bccto.me/ 临时邮箱申请 63 | 64 | enable true 65 | skip9Png true 66 | abortOnError true 67 | appendCompressRecord false 68 | keys = [ 69 | "mT1td5Qt6JW7yy0n2pkJd6ZwBxmHsjBy", 70 | "ctW1PG2wJhpJYxDhcj4NSgQ14WFxC7gb", 71 | "SWxfXRhZ6H1wnXnd3j5HmbK8wCpvdH0X", 72 | "52GXhbcbMv2g4lxWdhzFfW4FSV8kqDSl", 73 | "hVsMLDnLjGfkvTW8rdl923jq821j9MZw", 74 | "4kZy7LDsv4NyWnWBQRdzLXWrSBh30VjK", 75 | "l1W25Yhy32j3gSfV5w56VjNpFzFn0kW2", 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /app/compressed_pictures: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/compressed_pictures -------------------------------------------------------------------------------- /app/exclude_pictures.txt: -------------------------------------------------------------------------------- 1 | app/src/main/res/mipmap-hdpi/ic_launcher.png 2 | main/res/mipmap-mdpi/ic_launc -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/tinypngplugin/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.tinypngplugin.demo; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | public class MainActivity extends Activity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_main); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher2.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-hdpi/ic_launcher2.9.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TinyPngPluginDemo 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/pad/res/drawable/ic_launcher_background_xx.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/pad/res/drawable/ic_launcher_round_xxx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/pad/res/drawable/ic_launcher_round_xxx.png -------------------------------------------------------------------------------- /app/src/pad/res/drawable/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/pad/res/drawable/img1.png -------------------------------------------------------------------------------- /app/src/pad/res/drawable/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/pad/res/drawable/img2.png -------------------------------------------------------------------------------- /app/src/pad/res/drawable/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/pad/res/drawable/img3.png -------------------------------------------------------------------------------- /app/src/pad/res/drawable/img4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/app/src/pad/res/drawable/img4.jpg -------------------------------------------------------------------------------- /app/src/pad/res/layout/activity_main_x.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | // maven { 7 | // url 'tinypng/repo' 8 | // } 9 | google() 10 | jcenter() 11 | } 12 | dependencies { 13 | classpath 'com.android.tools.build:gradle:3.0.0' 14 | // classpath "com.wanjian.plugin:tinypng:1.0.0-SNAPSHOT" 15 | classpath "com.wanjian.plugin:tinypng:0.0.6" 16 | classpath 'com.novoda:bintray-release:0.8.0' 17 | 18 | // NOTE: Do not place your application dependencies here; they belong 19 | // in the individual module build.gradle files 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | google() 26 | jcenter() 27 | } 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | #org.gradle.daemon=true 15 | #org.gradle.debug=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Nov 13 20:49:11 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /module2/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /module2/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: "com.wanjian.tinypng" 3 | android { 4 | compileSdkVersion 28 5 | buildToolsVersion "28.0.3" 6 | 7 | 8 | defaultConfig { 9 | minSdkVersion 19 10 | targetSdkVersion 28 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | } 28 | tinyPng { 29 | enable true 30 | skip9Png true 31 | abortOnError true 32 | appendCompressRecord false 33 | keys=[ 34 | "mT1td5Qt6JW7yy0n2pkJd6ZwBxmHsjBy", 35 | "ctW1PG2wJhpJYxDhcj4NSgQ14WFxC7gb", 36 | "SWxfXRhZ6H1wnXnd3j5HmbK8wCpvdH0X", 37 | "52GXhbcbMv2g4lxWdhzFfW4FSV8kqDSl", 38 | "hVsMLDnLjGfkvTW8rdl923jq821j9MZw", 39 | "4kZy7LDsv4NyWnWBQRdzLXWrSBh30VjK", 40 | "l1W25Yhy32j3gSfV5w56VjNpFzFn0kW2", 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /module2/compressed_pictures: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/module2/compressed_pictures -------------------------------------------------------------------------------- /module2/exclude_pictures.txt: -------------------------------------------------------------------------------- 1 | ic_launcher_round_xxx.png -------------------------------------------------------------------------------- /module2/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /module2/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /module2/src/main/res/drawable/module2_img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/module2/src/main/res/drawable/module2_img1.png -------------------------------------------------------------------------------- /module2/src/main/res/drawable/module2_img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android-notes/TinyPngPlugin/ce459b53496c2efb04bc8bd186c36c90ae418075/module2/src/main/res/drawable/module2_img2.png -------------------------------------------------------------------------------- /module2/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | module2 3 | 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':tinypng', ':module2' 2 | -------------------------------------------------------------------------------- /tinypng/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /tinypng/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'groovy' 2 | apply plugin: 'maven' 3 | apply plugin: 'com.novoda.bintray-release' 4 | repositories { 5 | mavenLocal() 6 | jcenter() 7 | } 8 | buildscript { 9 | repositories { 10 | mavenCentral() 11 | jcenter() 12 | google() 13 | } 14 | dependencies { 15 | classpath 'com.android.tools.build:gradle:3.0.0' 16 | classpath 'com.novoda:bintray-release:0.8.0' 17 | } 18 | } 19 | 20 | dependencies { 21 | compile gradleApi() 22 | compile 'com.tinify:tinify:1.1.1' 23 | } 24 | 25 | group 'com.wanjian.plugin' 26 | version '1.0.0-SNAPSHOT' 27 | 28 | sourceCompatibility = 1.8 29 | 30 | uploadArchives { 31 | repositories { 32 | mavenDeployer { 33 | repository(url: uri('./repo')) 34 | } 35 | } 36 | } 37 | 38 | def getKey() { 39 | Properties properties = new Properties() 40 | File propertyFile = new File(rootDir.getAbsolutePath() + "/local.properties") 41 | if (propertyFile.exists()) { 42 | properties.load(propertyFile.newDataInputStream()) 43 | return properties.getProperty("jcenter_key") 44 | } 45 | } 46 | // clean -- build --- generatePomFileForReleasePublication---publishReleasePublicationToMabenLocal---bintrayUpload---publishing 47 | publish { 48 | groupId = 'com.wanjian.plugin' 49 | artifactId = 'tinypng' 50 | publishVersion = '0.0.6' 51 | desc = 'tiny png plugin 4 android' 52 | website = 'https://github.com/android-notes/TinyPngPlugin' 53 | 54 | bintrayUser = 'wanjian' // 账户名 55 | bintrayKey = getKey() // 就是API key 56 | dryRun = false 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /tinypng/src/main/groovy/com/wanjian/plugin/TinyPngPlugin.groovy: -------------------------------------------------------------------------------- 1 | package com.wanjian.plugin 2 | 3 | import com.wanjian.plugin.config.TinyPng 4 | import com.wanjian.plugin.tasks.TinyPngProcessTask 5 | import org.gradle.api.GradleException 6 | import org.gradle.api.Plugin 7 | import org.gradle.api.Project 8 | 9 | class TinyPngPlugin implements Plugin { 10 | @Override 11 | void apply(Project project) { 12 | // 13 | def variants; 14 | if (project.plugins.hasPlugin('com.android.application')) { 15 | variants = project.android.applicationVariants 16 | } else if (project.plugins.hasPlugin('com.android.library')) { 17 | variants = project.android.libraryVariants 18 | } else { 19 | throw new GradleException('Android plugin required') 20 | } 21 | 22 | project.extensions.create('tinyPng', TinyPng) 23 | 24 | project.afterEvaluate { 25 | if (project.tinyPng.enable == false) { 26 | project.logger.error("tinypng is disabled.") 27 | return 28 | } 29 | if (project.tinyPng.keys.size() == 0) { 30 | throw new GradleException("please add tiny png key !") 31 | } 32 | 33 | variants.all { variant -> 34 | def variantName = variant.name.capitalize() 35 | TinyPngProcessTask tinyPngProcessTask = project.tasks.create("tinyPng${variantName}", TinyPngProcessTask) 36 | tinyPngProcessTask.setVariant(variant) 37 | // project.tasks.findByName("generate${variantName}BuildConfig").dependsOn tinyPngProcessTask 38 | project.tasks.findByName("generate${variantName}Resources").dependsOn tinyPngProcessTask 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tinypng/src/main/groovy/com/wanjian/plugin/config/TinyPng.groovy: -------------------------------------------------------------------------------- 1 | package com.wanjian.plugin.config; 2 | 3 | public class TinyPng { 4 | 5 | boolean enable; 6 | 7 | def keys = []; 8 | /** 9 | * 是否不压缩 9.png图片 10 | */ 11 | boolean skip9Png = true 12 | 13 | /** 14 | * 压缩失败时是否停止task 15 | */ 16 | boolean abortOnError; 17 | 18 | /** 19 | * 是否在compressed_pictures文件中追加压缩后的图片的MD5值 20 | * true: 追加 21 | * false: 重置 22 | */ 23 | boolean appendCompressRecord = false; 24 | } 25 | -------------------------------------------------------------------------------- /tinypng/src/main/groovy/com/wanjian/plugin/tasks/TinyPngProcessTask.groovy: -------------------------------------------------------------------------------- 1 | package com.wanjian.plugin.tasks 2 | 3 | import com.tinify.AccountException 4 | import com.tinify.Tinify 5 | import com.wanjian.plugin.utils.MD5 6 | import org.gradle.api.DefaultTask 7 | import org.gradle.api.GradleException 8 | import org.gradle.api.tasks.TaskAction 9 | 10 | class TinyPngProcessTask extends DefaultTask { 11 | 12 | def variant 13 | def compressedPictureFiles 14 | def excludePictureFiles 15 | 16 | @TaskAction 17 | void process() { 18 | println(">>>>>>>>>>Start Compress Pictures") 19 | 20 | compressedPictureFiles = getCompressedPictureFiles(); 21 | excludePictureFiles = getExcludePictureFiles(); 22 | 23 | excludePictureFiles.each { 24 | println("excludePictureFiles ${it}") 25 | } 26 | def allImageMD5s = []; 27 | def compressingDirs = []; 28 | long total = 0; 29 | variant.sourceSets.each { source -> 30 | source.getRes().getSrcDirs().each { dir -> 31 | println(">>>> ${dir}") 32 | if (compressingDirs.contains(dir)) { 33 | return; 34 | } else { 35 | compressingDirs.add(dir) 36 | } 37 | dir.listFiles(new FilenameFilter() { 38 | @Override 39 | boolean accept(File file, String s) { 40 | return s.startsWith("drawable") || s.startsWith("mipmap") 41 | } 42 | }).each { imgFolder -> 43 | imgFolder.listFiles(new FilenameFilter() { 44 | @Override 45 | boolean accept(File file, String s) { 46 | return s.endsWith("xml") == false 47 | } 48 | }).each { imgFile -> 49 | if (skip(imgFile)) { 50 | println("skip ${imgFile.getAbsolutePath()}") 51 | return 52 | } 53 | String md5 = MD5.get(imgFile); 54 | if (compressedPictureFiles.contains(md5) == false) { 55 | long originSize = imgFile.length(); 56 | if (compressPicture(imgFile)) { 57 | File newImage = new File(imgFile.getAbsolutePath()); 58 | allImageMD5s.add(MD5.get(newImage)) 59 | println("${(1f * newImage.length() / originSize)}%") 60 | total += (originSize - newImage.length()) 61 | } else { 62 | if (project.tinyPng.abortOnError) { 63 | throw new GradleException("tinypng compress failed! ${imgFile.getAbsolutePath()}") 64 | } else { 65 | println("tinypng compress failed! ${imgFile.getAbsolutePath()}") 66 | } 67 | } 68 | } else { 69 | println("compressed ${imgFile}") 70 | allImageMD5s.add(md5) 71 | } 72 | } 73 | } 74 | } 75 | } 76 | println("total size ${total / 1024} KB"); 77 | updateMD5Data(allImageMD5s); 78 | } 79 | 80 | boolean skip(img) { 81 | if (img.getName().endsWith(".9.png") && project.tinyPng.skip9Png) { 82 | return true 83 | } 84 | String relativePath = img.getAbsolutePath().replaceFirst(project.projectDir.getAbsolutePath(), ""); 85 | for (String path : excludePictureFiles) { 86 | if (relativePath.contains(path)) { 87 | return true; 88 | } 89 | } 90 | return false 91 | 92 | } 93 | 94 | boolean compressPicture(img) { 95 | def keys = project.tinyPng.keys; 96 | Iterator iterator = keys.iterator() 97 | while (iterator.hasNext()) { 98 | String key = iterator.next() 99 | println("compressing:${img} key:${key}") 100 | try { 101 | Tinify.setKey(key); 102 | Tinify.validate(); 103 | Tinify.fromFile(img.getAbsolutePath()).toFile(img.getAbsolutePath()); 104 | return true 105 | } catch (AccountException accountExcep) { 106 | iterator.remove() 107 | project.logger.error("Your monthly limit has been exceeded (HTTP 429/TooManyRequests) key:${key}") 108 | } catch (Exception e) { 109 | project.logger.error("tiny png err", e) 110 | } 111 | } 112 | return false 113 | } 114 | 115 | void updateMD5Data(allImageMD5s) { 116 | File compressedPicturesFile = new File("${project.projectDir}/compressed_pictures") 117 | BufferedWriter writer = new BufferedWriter(new FileWriter(compressedPicturesFile, false)) 118 | writer.write("# Do not modify this file !") 119 | 120 | if (project.tinyPng.appendCompressRecord) { 121 | allImageMD5s.addAll(compressedPictureFiles) 122 | } 123 | allImageMD5s.unique() 124 | allImageMD5s.sort() 125 | allImageMD5s.each { 126 | writer.newLine() 127 | writer.write(it) 128 | } 129 | writer.close() 130 | } 131 | 132 | def getCompressedPictureFiles() { 133 | File compressedPictureFiles = new File("${project.projectDir}/compressed_pictures") 134 | def compressedPicturesList = [] 135 | if (compressedPictureFiles.isFile()) { 136 | compressedPictureFiles.eachLine { line -> 137 | if (!line.trim().isEmpty() && line.startsWith("#") == false) { 138 | compressedPicturesList.add(line.trim()) 139 | } 140 | } 141 | } 142 | return compressedPicturesList; 143 | } 144 | 145 | def getExcludePictureFiles() { 146 | File excludePicturesFile = new File("${project.projectDir}/exclude_pictures.txt") 147 | def excludeList = [] 148 | if (excludePicturesFile.isFile()) { 149 | excludePicturesFile.eachLine { line -> 150 | if (!line.trim().isEmpty() && line.startsWith("#") == false) { 151 | excludeList.add(line.trim()) 152 | } 153 | } 154 | } 155 | return excludeList; 156 | } 157 | 158 | void setVariant(variant) { 159 | this.variant = variant 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /tinypng/src/main/groovy/com/wanjian/plugin/utils/MD5.groovy: -------------------------------------------------------------------------------- 1 | package com.wanjian.plugin.utils 2 | 3 | import java.security.MessageDigest 4 | 5 | class MD5 { 6 | static String get(File file) { 7 | MessageDigest digest = MessageDigest.getInstance("MD5") 8 | file.withInputStream() { is -> 9 | int read 10 | byte[] buffer = new byte[8192] 11 | while ((read = is.read(buffer)) > 0) { 12 | digest.update(buffer, 0, read); 13 | } 14 | } 15 | byte[] md5sum = digest.digest() 16 | BigInteger bigInt = new BigInteger(1, md5sum) 17 | return bigInt.toString(16).padLeft(32, '0') 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tinypng/src/main/resources/META-INF/gradle-plugins/com.wanjian.tinypng.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.wanjian.plugin.TinyPngPlugin --------------------------------------------------------------------------------