package com.taobao.android.builder.tasks;
import com.android.annotations.NonNull;
import com.android.build.gradle.internal.api.VariantContext;
import com.android.build.gradle.internal.pipeline.StreamFilter;
import com.android.build.gradle.internal.scope.ConventionMappingHelper;
import com.android.build.gradle.internal.scope.VariantScope;
import com.android.build.gradle.internal.tasks.IncrementalTask;
import com.android.build.gradle.internal.variant.BaseVariantOutputData;
import com.android.builder.core.VariantConfiguration;
import com.android.ide.common.res2.FileStatus;
import com.android.utils.FileUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.taobao.android.builder.tasks.manager.MtlBaseTaskAction;
import com.taobao.android.builder.tools.zip.ZipUtils;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputDirectory;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
/**
* Created by chenhjohn on 2017/4/24.
*/
public class PrepareBaseApkTask extends IncrementalTask {
// ----- PUBLIC TASK API -----
private File baseApk;
private int dexFilesCount;
private File outputDir;
// ----- PRIVATE TASK API -----
@Override
protected boolean isIncremental() {
// TODO fix once dep file parsing is resolved.
return false;
}
@Override
protected void doFullTaskAction() throws IOException {
File baseApk = getBaseApk();
File outputDir = getOutputDir();
ZipUtils.unzip(baseApk, outputDir.getAbsolutePath());
int dexFilesCount = getDexFilesCount();
Set<File> baseDexFileSet = getProject().fileTree(ImmutableMap.of("dir",
outputDir,
"includes",
ImmutableList.of(
"classes*.dex")))
.getFiles();
File[] baseDexFiles = baseDexFileSet.toArray(new File[baseDexFileSet.size()]);
int j = baseDexFileSet.size() + dexFilesCount;
for (int i = baseDexFiles.length - 1; i >= 0; i--) {
FileUtils.renameTo(baseDexFiles[i], new File(outputDir, "classes" + j + ".dex"));
j--;
}
}
@InputFile
public File getBaseApk() {
return baseApk;
}
public void setBaseApk(File baseApk) {
this.baseApk = baseApk;
}
@Input
public int getDexFilesCount() {
return dexFilesCount;
}
public void setDexFilesCount(int dexFilesCount) {
this.dexFilesCount = dexFilesCount;
}
@OutputDirectory
public File getOutputDir() {
return outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
@Override
protected void doIncrementalTaskAction(Map<File, FileStatus> changedInputs) throws IOException {
for (final Map.Entry<File, FileStatus> entry : changedInputs.entrySet()) {
FileStatus status = entry.getValue();
switch (status) {
case NEW:
break;
case CHANGED:
break;
case REMOVED:
break;
}
}
}
public static class ConfigAction extends MtlBaseTaskAction<PrepareBaseApkTask> {
@NonNull
VariantScope scope;
public ConfigAction(VariantContext variantContext, BaseVariantOutputData baseVariantOutputData) {
super(variantContext, baseVariantOutputData);
this.scope = baseVariantOutputData.getScope().getVariantScope();
}
@Override
@NonNull
public String getName() {
return scope.getTaskName("prepare", "BaseApk");
}
@Override
@NonNull
public Class<PrepareBaseApkTask> getType() {
return PrepareBaseApkTask.class;
}
@Override
public void execute(@NonNull PrepareBaseApkTask prepareBaseApkTask) {
final VariantConfiguration<?, ?, ?> variantConfiguration = scope.getVariantConfiguration();
prepareBaseApkTask.setAndroidBuilder(scope.getGlobalScope().getAndroidBuilder());
prepareBaseApkTask.setVariantName(scope.getVariantConfiguration().getFullName());
prepareBaseApkTask.setIncrementalFolder(scope.getIncrementalDir(getName()));
ConventionMappingHelper.map(prepareBaseApkTask, "baseApk", new Callable<File>() {
@Override
public File call() {
return variantContext.apContext.getBaseApk();
}
});
ConventionMappingHelper.map(prepareBaseApkTask,
"dexFilesCount",
new Callable<Integer>() {
@Override
public Integer call() {
Set<File> dexFolders = scope.getTransformManager()
.getPipelineOutput(StreamFilter.DEX)
.keySet();
// Preconditions.checkState(dexFolders.size() == 1,
// "There must be exactly one output");
return scope.getGlobalScope()
.getProject()
.fileTree(ImmutableMap.of("dir",
Iterables.getOnlyElement(
dexFolders),
"includes",
ImmutableList.of(
"classes*.dex")))
.getFiles()
.size();
}
});
ConventionMappingHelper.map(prepareBaseApkTask, "outputDir", new Callable<File>() {
@Override
public File call() {
return new File(variantContext.apContext.getBaseApk() + "_");
}
});
}
}
}