Created
May 5, 2018 07:13
-
-
Save tiann/42f829ae86b90934c8467f6f76dd6a85 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.android.build.api.transform.* | |
import com.android.build.gradle.internal.pipeline.TransformManager | |
import org.apache.commons.io.FileUtils | |
import java.util.jar.JarEntry | |
import java.util.jar.JarFile | |
import java.util.jar.JarOutputStream | |
import java.util.zip.ZipEntry | |
class JarZipUtil { | |
static List<String> blackList = Arrays.asList( | |
// "io.virtualapp.XApp", | |
// "io.virtualapp.VCommends", | |
"xxxxxxxxxxxx" | |
) | |
/** | |
* 将该jar包解压到指定目录 | |
* @param jarPath jar包的绝对路径 | |
* @param destDirPath jar包解压后的保存路径 | |
* @return 返回该jar包中包含的所有class的完整类名类名集合,其中一条数据如:com.aitski.hotpatch.Xxxx.class | |
*/ | |
public static List unzipJar(String jarPath, String destDirPath) { | |
List list = new ArrayList() | |
if (jarPath.endsWith('.jar')) { | |
JarFile jarFile = new JarFile(jarPath) | |
Enumeration<JarEntry> jarEntrys = jarFile.entries() | |
while (jarEntrys.hasMoreElements()) { | |
JarEntry jarEntry = jarEntrys.nextElement() | |
if (jarEntry.directory) { | |
continue | |
} | |
String entryName = jarEntry.getName() | |
if (entryName.endsWith('.class')) { | |
String className = entryName.replace('\\', '.').replace('/', '.') | |
list.add(className) | |
} | |
String outFileName = destDirPath + "/" + entryName | |
File outFile = new File(outFileName) | |
outFile.getParentFile().mkdirs() | |
InputStream inputStream = jarFile.getInputStream(jarEntry) | |
FileOutputStream fileOutputStream = new FileOutputStream(outFile) | |
fileOutputStream << inputStream | |
fileOutputStream.close() | |
inputStream.close() | |
} | |
jarFile.close() | |
} | |
return list | |
} | |
/** | |
* 重新打包jar | |
* @param packagePath 将这个目录下的所有文件打包成jar | |
* @param destPath 打包好的jar包的绝对路径 | |
*/ | |
public static void zipJar(String packagePath, String destPath) { | |
File file = new File(packagePath) | |
JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(destPath)) | |
file.eachFileRecurse { File f -> | |
String entryName = f.getAbsolutePath().substring(packagePath.length() + 1) | |
String pkg = entryName.replaceAll('/', '.') | |
boolean ignore = false | |
blackList.each { black -> | |
if (pkg.contains(black)) { | |
println "found target pkg: ${pkg}" | |
ignore = true | |
} | |
} | |
if (ignore) { | |
println("ignore class: ${f}") | |
} else { | |
outputStream.putNextEntry(new ZipEntry(entryName)) | |
if (!f.directory) { | |
InputStream inputStream = new FileInputStream(f) | |
outputStream << inputStream | |
inputStream.close() | |
} | |
} | |
} | |
outputStream.close() | |
} | |
} | |
class MyClassTransform extends Transform { | |
private Project mProject; | |
public MyClassTransform(Project p) { | |
this.mProject = p; | |
} | |
@Override | |
public String getName() { | |
return "MyClassTransform"; | |
} | |
@Override | |
public Set<QualifiedContent.ContentType> getInputTypes() { | |
return TransformManager.CONTENT_CLASS; | |
} | |
@Override | |
public Set<QualifiedContent.Scope> getScopes() { | |
return TransformManager.SCOPE_FULL_PROJECT; | |
} | |
@Override | |
public boolean isIncremental() { | |
return false | |
} | |
private void deleteFiles(File dir, FileFilter filter) { | |
if (dir.file) { | |
if (filter != null && filter.accept(dir)) { | |
dir.delete() | |
} | |
} else { | |
File[] files = dir.listFiles() | |
for (File f : files) { | |
deleteFiles(f, filter) | |
} | |
} | |
} | |
@Override | |
public void transform(Context context, | |
Collection<TransformInput> inputs, | |
Collection<TransformInput> referencedInputs, | |
TransformOutputProvider outputProvider, | |
boolean isIncremental) throws IOException, TransformException, InterruptedException { | |
inputs.each { | |
TransformInput input -> | |
input.directoryInputs.each { | |
DirectoryInput directoryInput -> | |
//BuryInject.injectDir(directoryInput.file.absolutePath,"com\\sasas\\dsdsd") | |
// 获取output目录</strong></span> | |
def dest = outputProvider.getContentLocation(directoryInput.name, | |
directoryInput.contentTypes, directoryInput.scopes, | |
Format.DIRECTORY); | |
deleteFiles(directoryInput.file, new FileFilter() { | |
@Override | |
boolean accept(File pathname) { | |
String abspath = pathname.absolutePath.replaceAll("/", ".") | |
for (String s : JarZipUtil.blackList) { | |
if (abspath.contains(s)) { | |
println "ignore class: ${pathname}, for: ${s}" | |
return true | |
} else { | |
println "${pathname} does not contains: ${s}" | |
} | |
} | |
return false | |
} | |
}) | |
println("" + directoryInput.file + " transform" + dest); | |
FileUtils.copyDirectory(directoryInput.file, dest) | |
} | |
input.jarInputs.each { | |
JarInput jarInput -> | |
def jarName = jarInput.name | |
injectJar(jarInput.file.absolutePath) | |
if (jarName.endsWith(".jar")) { | |
jarName = jarName.substring(0, jarName.length() - 4) | |
} | |
def dest = outputProvider.getContentLocation(jarName, | |
jarInput.contentTypes, jarInput.scopes, Format.JAR) | |
println("jar " + jarInput.file + " transform " + dest) | |
FileUtils.copyFile(jarInput.file, dest) | |
} | |
} | |
} | |
public static void injectJar(String path) { | |
if (path.endsWith(".jar")) { | |
File jarFile = new File(path) | |
String jarZipDir = jarFile.getParent() + "/" + jarFile.getName().replace('.jar', '') | |
List classNameList = JarZipUtil.unzipJar(path, jarZipDir) | |
jarFile.delete() | |
for (String className : classNameList) { | |
if (className.endsWith(".class") | |
&& !className.contains('R$') | |
&& !className.contains('R.class') | |
&& !className.contains("BuildConfig.class")) { | |
String tmp = className.substring(0, className.lastIndexOf('.')) | |
tmp = tmp.substring(0, tmp.lastIndexOf('.')) | |
// println "processing package : ${tmp}" | |
} | |
} | |
JarZipUtil.zipJar(jarZipDir, path) | |
FileUtils.deleteDirectory(new File(jarZipDir)) | |
} | |
} | |
} | |
class GreetingPlugin implements Plugin<Project> { | |
void apply(Project project) { | |
def classTransform = new MyClassTransform(project) | |
project.android.registerTransform(classTransform) | |
} | |
} | |
apply plugin: GreetingPlugin |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
大佬,弱弱的问一句,这个插件怎么用啊?