All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.yawk.valda.xml.Aapt2 Maven / Gradle / Ivy

package at.yawk.valda.xml;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.MoreFiles;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.eclipse.collections.impl.block.function.checked.ThrowingFunction;
import org.intellij.lang.annotations.Language;
import org.testng.SkipException;
import org.zeroturnaround.exec.ProcessExecutor;

/**
 * @author yawkat
 */
public final class Aapt2 {
    private static final String BUILD_TOOLS = System.getenv("ANDROID_BUILD_TOOLS");
    private static final String PLATFORM = System.getenv("ANDROID_PLATFORM");

    private final Map files = new HashMap<>();
    private final String manifest;

    public static boolean available() {
        return BUILD_TOOLS != null && PLATFORM != null;
    }

    public static void checkAvailable() {
        if (!available()) { throw new SkipException("ANDROID_BUILD_TOOLS and/or ANDROID_PLATFORM env variable not set"); }
    }

    public Aapt2(@Language("xml") String manifest) {
        checkAvailable();
        this.manifest = manifest;
    }

    public Aapt2 xml(String fileName, @Language("xml") String xml) {
        files.put(fileName, xml);
        return this;
    }

    @SuppressWarnings("UseOfSystemOutOrSystemErr")
    public  R compile(ThrowingFunction access)
            throws Exception {
        Path tmp = Files.createTempDirectory(Aapt2.class.getName());
        try {
            Path inDir = tmp.resolve("in/res");
            for (Map.Entry entry : files.entrySet()) {
                Path inFile = inDir.resolve(entry.getKey());
                Files.createDirectories(inFile.getParent());
                Files.write(inFile, entry.getValue().getBytes(StandardCharsets.UTF_8));
            }

            Path compiled = tmp.resolve("compile.zip");
            new ProcessExecutor()
                    .command(ImmutableList.builder()
                                     .add(Paths.get(BUILD_TOOLS, "aapt2").toString(),
                                          "compile",
                                          "-o", compiled.toString(),
                                          "--dir", inDir.toString())
                                     .build())
                    .exitValueNormal()
                    .readOutput(true)
                    .timeout(20, TimeUnit.SECONDS)
                    .execute();

            Path manifest = tmp.resolve("AndroidManifest.xml");
            Files.write(manifest, this.manifest.getBytes(StandardCharsets.UTF_8));

            Path linked = tmp.resolve("link.apk");
            new ProcessExecutor()
                    .command(Paths.get(BUILD_TOOLS, "aapt2").toString(),
                             "link",
                             "-I", PLATFORM + "/android.jar",
                             "--manifest", manifest.toString(),
                             "-o", linked.toString(),
                             compiled.toString())
                    .exitValueNormal()
                    .readOutput(true)
                    .timeout(20, TimeUnit.SECONDS)
                    .execute();

            new ProcessExecutor()
                    .command(Paths.get(BUILD_TOOLS, "aapt2").toString(),
                             "dump",
                             linked.toString())
                    .exitValueNormal()
                    .redirectOutput(System.out)
                    .timeout(20, TimeUnit.SECONDS)
                    .execute();

            Files.walk(tmp).forEach(System.out::println);

            try (FileSystem zipFs = FileSystems.newFileSystem(linked, null)) {
                return access.safeValueOf(Iterables.getOnlyElement(zipFs.getRootDirectories()));
            }
        } finally {
            MoreFiles.deleteRecursively(tmp);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy