Skip to content

Commit 07d0b85

Browse files
committed
添加Tiny图片压缩插件
1 parent e2607aa commit 07d0b85

File tree

12 files changed

+264
-5
lines changed

12 files changed

+264
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@
1818
/flutter_module/.flutter-plugins
1919
/flutter_module/.flutter-plugins-dependencies
2020
/flutter_module/.packages
21+
/app/compress-image.json

app/build.gradle

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ apply plugin: 'kotlin-android-extensions'
44
apply plugin: 'kotlin-kapt'
55
apply plugin: 'android-aspectjx'
66
apply plugin: 'com.didi.dokit'
7+
apply plugin: 'image-compress-plugin'
78
apply from: '../channel.gradle'
89
apply from: '../protect.gradle'
910
apply from: '../uploadpgy.gradle'
1011

12+
compressOption {
13+
apiKey '8PyvN9g9jxjVjS1B86bnv2pKC8cRD43p'
14+
limitSize 1024
15+
suffix "_opt"
16+
}
17+
1118
aspectjx {
1219
//排除所有特定class文件
1320
exclude 'module-info', 'kotlinx.coroutines', 'androidx.paging', 'com.lxj.xpopup', 'com.just.agentweb'
@@ -122,7 +129,7 @@ dependencies {
122129
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
123130
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
124131
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
125-
implementation 'com.github.fmtjava:LiveDataBus:1.0.0'
132+
implementation 'com.github.fmtjava:LiveDataBus:1.0.1'
126133

127134
//okhttp + retrofit(2.6.0以后支持协程)
128135
implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2")
@@ -142,7 +149,7 @@ dependencies {
142149
implementation "androidx.paging:paging-runtime-ktx:3.1.0-alpha02"
143150

144151
//WorkManager
145-
implementation "androidx.work:work-runtime-ktx:2.6.0-beta01"
152+
implementation "androidx.work:work-runtime-ktx:2.6.0-beta02"
146153

147154
//koin(依赖注入)
148155
implementation "org.koin:koin-androidx-scope:2.2.2"
@@ -171,14 +178,15 @@ dependencies {
171178
implementation 'io.github.idisfkj:android-startup:1.0.7'
172179

173180
//bugly捕获异常
174-
implementation 'com.tencent.bugly:crashreport:3.3.92'
181+
implementation 'com.tencent.bugly:crashreport:3.4.4'
175182

176183
//aspectj
177184
implementation 'org.aspectj:aspectjrt:1.9.5'//需要使用aspectJ能力的模块
178185

179186
//DoKit
180187
debugImplementation 'com.didichuxing.doraemonkit:dokitx:3.3.5'
181188
releaseImplementation 'com.didichuxing.doraemonkit:dokitx-no-op:3.3.5'
189+
debugImplementation 'com.didichuxing.doraemonkit:doraemonkit-leakcanary:3.1.5'
182190

183191
//flutter
184192
implementation project(':flutter')

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
apply from: './config.gradle'
33

44
buildscript {
5-
ext.kotlin_version = '1.5.10'
5+
ext.kotlin_version = '1.4.10'
66
repositories {
77
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
88
maven { url 'https://maven.aliyun.com/repository/google' }

buildSrc/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

buildSrc/build.gradle

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//引入groovy插件
2+
apply plugin: 'groovy'
3+
4+
//添加远程依赖
5+
repositories {
6+
mavenCentral()
7+
google()
8+
jcenter()
9+
}
10+
11+
dependencies {
12+
//工具包
13+
implementation 'com.android.tools.build:gradle:3.4.2'
14+
//相当于android sdk
15+
implementation gradleApi()
16+
//本地Groovy
17+
implementation localGroovy()
18+
//TinyPng压缩 -->https://tinypng.com/developers(开发网址)
19+
implementation 'com.tinify:tinify:1.6.4'
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.fmt.github.plugin
2+
3+
class CompressExt {
4+
5+
String apiKey//在TinyPng平台使用邮箱获取即可
6+
int limitSize//压缩的最小大小
7+
String suffix//压缩图片的后缀,默认为空(覆盖原图)
8+
9+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.fmt.github.plugin
2+
3+
class CompressImageInfo{
4+
String name
5+
String path
6+
String fileSize
7+
String compressedSize
8+
String md5
9+
10+
CompressImageInfo(String name, String path, String fileSize, String compressedSize, String md5) {
11+
this.name = name
12+
this.path = path
13+
this.fileSize = fileSize
14+
this.compressedSize = compressedSize
15+
this.md5 = md5
16+
}
17+
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package com.fmt.github.plugin
2+
3+
import com.android.build.gradle.BaseExtension
4+
import com.tinify.Tinify
5+
import groovy.json.JsonOutput
6+
import groovy.json.JsonSlurper
7+
import org.apache.commons.codec.digest.DigestUtils
8+
import org.gradle.api.DefaultTask
9+
import org.gradle.api.tasks.SourceSet
10+
import org.gradle.api.tasks.TaskAction
11+
import java.text.DecimalFormat
12+
import java.util.concurrent.CopyOnWriteArrayList
13+
import java.util.concurrent.CountDownLatch
14+
import java.util.concurrent.ExecutorService
15+
import java.util.concurrent.Executors
16+
import java.util.concurrent.TimeUnit
17+
18+
/**
19+
* 自定义压缩任务
20+
*/
21+
class CompressTask extends DefaultTask {
22+
23+
CompressExt mCompressOption
24+
ExecutorService mExecutorService
25+
26+
CompressTask() {
27+
mCompressOption = project.compressOption
28+
mExecutorService = Executors.newCachedThreadPool()
29+
}
30+
31+
@TaskAction
32+
void run() {
33+
println("CompressTask start ...")
34+
//1.判断ApiKey是否为空
35+
if (mCompressOption.apiKey == null) {
36+
throw new IllegalArgumentException("TinyPng ApiKey should be set")
37+
}
38+
//2.校验ApiKey是否合法
39+
try {
40+
Tinify.setKey(mCompressOption.apiKey)
41+
Tinify.validate()
42+
} catch (Exception ignored) {
43+
throw new IllegalArgumentException("TinyPng ApiKey is not available")
44+
}
45+
46+
//3.加载图片资源所在目录 -->res目录
47+
def androidExt = project.extensions.findByType(BaseExtension.class)
48+
def sourceSets = androidExt.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME)
49+
def resDir = sourceSets.res.srcDirs.first()
50+
51+
//4.读取已经压缩过的图片集合
52+
def compressedList = loadCompressedImage()
53+
54+
//5.过滤res目录下的文件夹 -->只对drawable-、mipmap-做处理
55+
def drawablePattern = "drawable-[a-z]*"
56+
def mipmapPattern = "mipmap-[a-z]*"
57+
def validFiles = new ArrayList<File>()
58+
resDir.listFiles().each { dir ->
59+
if (dir.name.matches(drawablePattern) || dir.name.matches(mipmapPattern)) {
60+
dir.listFiles().each { file ->
61+
if (validFile(file, compressedList)) {
62+
validFiles.add(file)
63+
}
64+
}
65+
}
66+
}
67+
//6.开启多线程进行图片压缩
68+
CountDownLatch countDownLatch = new CountDownLatch(validFiles.size())
69+
validFiles.each { file ->
70+
mExecutorService.execute(new Runnable() {
71+
@Override
72+
void run() {
73+
def ret = compressImage(file)
74+
compressedList.add(ret)
75+
countDownLatch.countDown()
76+
}
77+
})
78+
}
79+
//7.等待所有的图片都压缩完成,再将压缩后的图片信息写入json文件中
80+
countDownLatch.await(10, TimeUnit.MINUTES)
81+
writeCompressResource(compressedList)
82+
83+
println("CompressionTask finished")
84+
}
85+
86+
//将压缩后的图片信息写入json文件中
87+
def writeCompressResource(List<CompressImageInfo> compressImageList) {
88+
def compressFile = new File(project.projectDir, "compress-image.json")
89+
JsonOutput jsonOutput = new JsonOutput()
90+
def json = jsonOutput.toJson(compressImageList)
91+
compressFile.write(json, "utf-8")
92+
}
93+
94+
//压缩图片
95+
def compressImage(File file) {
96+
println("compress ${file.name} start")
97+
//判断是否需要覆盖原图
98+
def dstFile
99+
if (mCompressOption.suffix == null) {
100+
dstFile = new File(file.parent, file.name)
101+
} else {
102+
def fileName = file.name
103+
def prefix = fileName.substring(0, fileName.lastIndexOf("."))
104+
def suffix = fileName.substring(fileName.lastIndexOf("."))
105+
dstFile = new File(file.parent, "$prefix${mCompressOption.suffix}$suffix")
106+
}
107+
108+
if (!dstFile.exists()) {
109+
dstFile.createNewFile()
110+
}
111+
112+
//使用Tinify进行压缩
113+
def source = Tinify.fromFile(file.path)
114+
source.toFile(dstFile.path)
115+
116+
println("compress ${file.name} finished")
117+
118+
return new CompressImageInfo(file.name, file.path, formatSize(file.size()), formatSize(dstFile.size()), DigestUtils.md5Hex(file.newInputStream()))
119+
}
120+
121+
//格式化文件的大小
122+
static def formatSize(long fileSize) {
123+
def df = new DecimalFormat("#.0")
124+
if (fileSize < 1024) {
125+
return "${fileSize}B"
126+
} else if (fileSize < 1024 * 1024) {
127+
return "${df.format(fileSize * 1.0f / 1024)}KB"
128+
} else {
129+
return "${df.format(fileSize * 1.0f / 1024 / 1024)}M"
130+
}
131+
}
132+
133+
//获取已经压缩过的图片集合
134+
def loadCompressedImage() {
135+
def compressFile = new File(project.projectDir, "compress-image.json")
136+
if (!compressFile.exists()) {
137+
compressFile.createNewFile()
138+
} else {
139+
try {
140+
def ret = new JsonSlurper().parse(compressFile, "utf-8")
141+
if (ret instanceof List<CompressImageInfo>) {
142+
return ret
143+
}
144+
} catch (Exception e) {
145+
throw e
146+
}
147+
}
148+
return new CopyOnWriteArrayList<CompressImageInfo>()
149+
}
150+
151+
//判断图片是否合法
152+
def validFile(File file, List<CompressImageInfo> compressList) {
153+
if (file.isDirectory()) {
154+
return false
155+
}
156+
if (file.name.endsWith(".9")) {
157+
println("skip file ${file.name} which is .9")
158+
return false
159+
}
160+
if (file.name.endsWith(".xml")) {
161+
println("skip file ${file.name} which is .xml")
162+
return false
163+
}
164+
if (mCompressOption.suffix != null && file.name.contains(mCompressOption.suffix)) {
165+
println("skip file ${file.name} which has compressed")
166+
return false
167+
}
168+
long fileSize = file.size()
169+
if (fileSize < mCompressOption.limitSize) {
170+
println("skip file ${file.name} which file size less than ${mCompressOption.limitSize}")
171+
return false
172+
}
173+
def md5 = DigestUtils.md5Hex(file.newInputStream())
174+
def match = compressList.any { imageInfo ->
175+
return imageInfo.md5 == md5
176+
}
177+
if (match) {
178+
println("skip file ${file.name} which has compressed")
179+
return false
180+
}
181+
return true
182+
}
183+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.fmt.github.plugin
2+
3+
import org.gradle.api.Plugin
4+
import org.gradle.api.Project
5+
6+
/**
7+
* 自定义图片压缩插件
8+
*/
9+
class ImageCompressPlugin implements Plugin<Project> {
10+
11+
@Override
12+
void apply(Project project) {
13+
//注册扩展属性
14+
project.extensions.create("compressOption", CompressExt.class)
15+
//注册Task
16+
project.tasks.create("imageCompress", CompressTask.class).setGroup("Tiny")
17+
}
18+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
implementation-class=com.fmt.github.plugin.ImageCompressPlugin

0 commit comments

Comments
 (0)