com.faker.android.gradle.SmaliBuilderTask Maven / Gradle / Ivy
The newest version!
package com.faker.android.gradle;
import com.android.build.api.artifact.BuildableArtifact;
import com.android.build.gradle.api.AndroidSourceSet;
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension;
import com.android.build.gradle.internal.scope.VariantScope;
import com.android.build.gradle.internal.tasks.VariantAwareTask;
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction;
import com.android.tools.build.bundletool.io.ZipBuilder;
import com.faker.android.SmaliCompiler;
import com.google.common.io.Files;
import com.googlecode.d2j.dex.Dex2jar;
import com.googlecode.dex2jar.tools.BaksmaliBaseDexExceptionHandler;
//import com.googlecode.d2j.dex.Dex2jar;
//import com.googlecode.dex2jar.tools.BaksmaliBaseDexExceptionHandler;
import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.Incubating;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileType;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SkipWhenEmpty;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.bundling.Zip;
import org.gradle.work.ChangeType;
import org.gradle.work.FileChange;
import org.gradle.work.Incremental;
import org.gradle.work.InputChanges;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import brut.directory.ZipUtils;
import static com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope.ALL;
import static com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType.CLASSES;
import static com.android.build.gradle.internal.publishing.AndroidArtifacts.ConsumedConfigType.RUNTIME_CLASSPATH;
import static com.android.build.gradle.internal.scope.InternalArtifactType.JAVAC;
public class SmaliBuilderTask extends DefaultTask implements VariantAwareTask {//TODO this task should produce javascaffoding for dev
private String variantName;
private final DirectoryProperty destinationDirectory;
private final DirectoryProperty destinationjarDirectory;
private FileCollection source;
@Input
public int getApiLevel() {
return apiLevel;
}
public void setApiLevel(int apiLevel) {
this.apiLevel = apiLevel;
}
private int apiLevel;
public DirectoryProperty getDestinationjarDirectory() {
return destinationjarDirectory;
}
public SmaliBuilderTask() {
this.destinationDirectory = getProject().getObjects().directoryProperty();
this.destinationjarDirectory = getProject().getObjects().directoryProperty();
}
@TaskAction
protected void compile(InputChanges inputs) {//TODO MY FOCUS ON
System.out.println("compiling the smali to dex ...");
if(!inputs.isIncremental()) {
try {
FileUtils.deleteDirectory(getDestinationDirectory().getAsFile().getOrNull());
} catch (Exception e) {
e.printStackTrace();
}
}
Iterable sourceChanges = inputs.getFileChanges(getSource());
for (FileChange fileChange: sourceChanges) {
if (fileChange.getFileType() != FileType.FILE) {
continue;
}
String absPath = fileChange.getFile().getAbsolutePath();
String path = fileChange.getNormalizedPath();
String nonePrefixNamePath = getFileNameNoEx(path);
String toDexPath = nonePrefixNamePath +".dex";
String toDexAbsPath = new File(getDestinationDirectory().getAsFile().getOrNull(),toDexPath).getAbsolutePath();
File smaliFile = new File(absPath);
File dexFile = new File(toDexAbsPath);
if(fileChange.getChangeType()== ChangeType.ADDED||fileChange.getChangeType()== ChangeType.MODIFIED) {
if(!dexFile.getParentFile().exists()){
dexFile.getParentFile().mkdirs();
}
try {
String classesAspath = getClassesFileCollection().getAsPath();
File isClassFile = new File(classesAspath,nonePrefixNamePath+".class");
if(isClassFile.exists()){
System.out.println("current dex "+toDexPath+" ref smali is covered by "+ nonePrefixNamePath+".class ref java");
continue;
}
SmaliCompiler.build(smaliFile,dexFile,apiLevel);
//System.out.println("add dex or mod flie:"+ toDexPath);
File scaffdingJarFile = new File(getDestinationjarDirectory().getAsFile().getOrNull(),"classes.all.dex.jar");
if(scaffdingJarFile.exists()) {
if(fileChange.getChangeType()== ChangeType.MODIFIED){
BaksmaliBaseDexExceptionHandler handler = false ? null : new BaksmaliBaseDexExceptionHandler();
Dex2jar.from(dexFile).withExceptionHandler(handler).reUseReg(false).topoLogicalSort()
.skipDebug(false).optimizeSynchronized(false).printIR(false)
.noCode(false).skipExceptions(false).to(scaffdingJarFile.toPath());
System.out.println("a smali "+path+" file mod has been found the java scaffding jar file sync with it...");
}
}else{
System.err.println(" no javaScaffoding base jar with name "+scaffdingJarFile.getName()+" has been found --");
}
} catch (Exception e) {
e.printStackTrace();
}
}else {
if(dexFile.exists()){
System.out.println("del dex flie :"+ toDexPath);
dexFile.delete();
}
}
}
Iterable classChanges = inputs.getFileChanges(getClassesFileCollection());
for (FileChange fileChange: classChanges) {//TODO catch the classes in project
if (fileChange.getFileType() != FileType.FILE) {
continue;
}
String normalizedPathClassPath = fileChange.getNormalizedPath();
String noExtNormalizedPathClassPath = getFileNameNoEx(normalizedPathClassPath);
if(fileChange.getChangeType()== ChangeType.ADDED){
File destinationDirectoryFile = getDestinationDirectory().getAsFile().getOrNull();
File isDex = new File(destinationDirectoryFile,noExtNormalizedPathClassPath+".dex");
if(isDex.exists()){
isDex.delete();
System.out.println("isDex del:"+noExtNormalizedPathClassPath+".dex");
}
}
if(fileChange.getChangeType()== ChangeType.REMOVED){
String sourcePath = getSource().getAsPath();
File isSmali = new File(sourcePath,noExtNormalizedPathClassPath+".smali");
System.out.println("isSmali:"+isSmali.getAbsolutePath());
if(isSmali.exists()){
File isToDex = new File(getDestinationDirectory().getAsFile().getOrNull(),noExtNormalizedPathClassPath+".dex");
try {
if(!isToDex.exists()){
SmaliCompiler.build(isSmali,isToDex,apiLevel);
}
System.out.println("class remove now recover the smali file to dex path smali:"+noExtNormalizedPathClassPath+".smali");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Iterable jarChanges = inputs.getFileChanges(getJarFileCollection());
for (FileChange fileChange: jarChanges) {//TODO catch the classes in project
// System.out.println("jar change path:" +fileChange.getFile().getAbsolutePath());
// System.out.println("jar change name:"+fileChange.getNormalizedPath());
}
}
public static String getFileNameNoEx(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length()))) {
return filename.substring(0, dot);
}
}
return filename;
}
@OutputDirectory
public DirectoryProperty getDestinationDirectory() {
return destinationDirectory;
}
@NotNull
@Override
public String getVariantName() {
return variantName;
}
@Override
public void setVariantName(@NotNull String variantName) {
this.variantName = variantName;
}
@Incremental
@Incubating
@SkipWhenEmpty
@PathSensitive(PathSensitivity.RELATIVE)
@InputFiles
public FileCollection getClassesFileCollection() {
return classesFileCollection;
}
private void setClassesFileCollection(FileCollection classesFileCollection) {
this.classesFileCollection = classesFileCollection;
}
private FileCollection classesFileCollection;
private FileCollection jarFileCollection;//TODO
@Incremental
@InputFiles
@Incubating
@PathSensitive(PathSensitivity.RELATIVE)
@SkipWhenEmpty
public FileCollection getSource() {
return source;
}
public void setSource(FileCollection source) {
this.source = source;
}
@Incremental
@InputFiles
@Incubating
@PathSensitive(PathSensitivity.RELATIVE)
@SkipWhenEmpty
public FileCollection getJarFileCollection() {
return jarFileCollection;
}
public void setJarFileCollection(FileCollection jarFileCollection) {
this.jarFileCollection = jarFileCollection;
}
public void setDestinationDir(File destinationDir) {
this.destinationDirectory.set(destinationDir);
}
public void setDestinationJarDir(File destinationJarDir) {
this.destinationjarDirectory.set(destinationJarDir);
}
public static class CreationAction extends VariantTaskCreationAction {
TaskProvider taskProvider;
File destinationDir;
File destinationJarDir;
public CreationAction(@NotNull VariantScope variantScope, TaskProvider taskProvider) {
super(variantScope);
this.taskProvider = taskProvider;
}
@NotNull
@Override
public String getName() {
return getVariantScope().getTaskName("smali");
}
@NotNull
@Override
public Class getType() {
return SmaliBuilderTask.class;
}
@Override
public void preConfigure(@NotNull String taskName) {
super.preConfigure(taskName);
destinationDir = getVariantScope().getArtifacts().appendArtifact(FakerBuildArtifactType.SMALIDEXES, taskName, "dexes");
Project project = getVariantScope().getVariantData().getScope().getGlobalScope().getProject();
File file = project.getBuildscript().getSourceFile().getParentFile();
destinationJarDir = new File(file,"javaScaffoding");
if(!destinationJarDir.exists()){
destinationJarDir.mkdirs();
}
}
@Override
public void configure(@NotNull SmaliBuilderTask task) {
super.configure(task);
task.setDestinationDir(destinationDir);
task.setDestinationJarDir(destinationJarDir);
Project project = getVariantScope().getVariantData().getScope().getGlobalScope().getProject();
BaseAppModuleExtension appExtension = project.getExtensions().getByType(BaseAppModuleExtension.class);
AndroidSourceSet androidSourceSet = appExtension.getSourceSets().getByName("main");
File smalis = new File(androidSourceSet.getManifest().getSrcFile().getParent(),"smali");
int apiLevel = appExtension.getDefaultConfig().getMinSdkVersion().getApiLevel();
task.setApiLevel(apiLevel);
//TODO this is filecollection of smali files
ConfigurableFileCollection source = getVariantScope().getGlobalScope().getProject().files(smalis);
task.setSource(source);
//TODO this is a .class filecollection in current moudle
final BuildableArtifact javacOutput = getVariantScope().getArtifacts().getArtifactFiles(JAVAC);
final FileCollection preJavacGeneratedBytecode = getVariantScope().getVariantData().getAllPreJavacGeneratedBytecode();
final FileCollection postJavacGeneratedBytecode = getVariantScope().getVariantData().getAllPostJavacGeneratedBytecode();
ConfigurableFileCollection classFiles = getVariantScope().getGlobalScope().getProject().files(javacOutput, preJavacGeneratedBytecode, postJavacGeneratedBytecode);
task.setClassesFileCollection(classFiles);
//TODO this is a .jar filecollection in current moudle
FileCollection jarFiles =getVariantScope().getArtifactCollection(RUNTIME_CLASSPATH, ALL, CLASSES).getArtifactFiles();//
task.setJarFileCollection(jarFiles);
//设置必须运行在javac之后
task.mustRunAfter(taskProvider);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy