diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/Options.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/Options.java index b1e716c558..1cb657818e 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/Options.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/Options.java @@ -41,6 +41,7 @@ public Options(ProcessingEnvironment processingEnvironment) { options = processingEnvironment.getOptions(); addSupportedOption(AndroidManifestFinder.OPTION_MANIFEST); addSupportedOption(AndroidManifestFinder.OPTION_LIBRARY); + addSupportedOption(AndroidManifestFinder.OPTION_INSTANT_FEATURE); addSupportedOption(ProjectRClassFinder.OPTION_RESOURCE_PACKAGE_NAME); addSupportedOption(ProjectRClassFinder.OPTION_USE_R2); addSupportedOption(ModelConstants.OPTION_CLASS_SUFFIX); diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/helper/AndroidManifestFinder.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/helper/AndroidManifestFinder.java index 2173af26fa..1977db37a6 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/helper/AndroidManifestFinder.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/helper/AndroidManifestFinder.java @@ -19,9 +19,11 @@ import static org.androidannotations.helper.CaseHelper.upperCaseFirst; import static org.androidannotations.helper.ModelConstants.classSuffix; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -54,6 +56,7 @@ public class AndroidManifestFinder { public static final Option OPTION_MANIFEST = new Option("androidManifestFile", null); public static final Option OPTION_LIBRARY = new Option("library", "false"); + public static final Option OPTION_INSTANT_FEATURE = new Option("instantAppFeature", "false"); private static final Logger LOGGER = LoggerFactory.getLogger(AndroidManifestFinder.class); @@ -124,7 +127,7 @@ private File findManifestInKnownPaths() throws FileNotFoundException { } File findManifestInKnownPathsStartingFromGenFolder(String sourcesGenerationFolder) throws FileNotFoundException { - Iterable strategies = Arrays.asList(new GradleAndroidManifestFinderStrategy(sourcesGenerationFolder), + Iterable strategies = Arrays.asList(new GradleAndroidManifestFinderStrategy(environment, sourcesGenerationFolder), new MavenAndroidManifestFinderStrategy(sourcesGenerationFolder), new EclipseAndroidManifestFinderStrategy(sourcesGenerationFolder)); AndroidManifestFinderStrategy applyingStrategy = null; @@ -181,14 +184,18 @@ boolean applies() { private static class GradleAndroidManifestFinderStrategy extends AndroidManifestFinderStrategy { static final Pattern GRADLE_GEN_FOLDER = Pattern.compile("^(.*?)build[\\\\/]generated[\\\\/]source[\\\\/](k?apt)(.*)$"); + static final Pattern OUTPUT_JSON_PATTERN = Pattern.compile(".*,\"path\":\"(.*?)\",.*"); private static final List SUPPORTED_ABI_SPLITS = Arrays.asList("arm64-v8a", "armeabi", "armeabi-v7a", "mips", "mips64", "x86", "x86_64"); private static final List SUPPORTED_DENSITY_SPLITS = Arrays.asList("hdpi", "ldpi", "mdpi", "xhdpi", "xxhdpi", "xxxhdpi"); private static final String BUILD_TOOLS_V32_MANIFEST_PATH = "build/intermediates/merged_manifests"; - GradleAndroidManifestFinderStrategy(String sourceFolder) { + private final AndroidAnnotationsEnvironment environment; + + GradleAndroidManifestFinderStrategy(AndroidAnnotationsEnvironment environment, String sourceFolder) { super("Gradle", GRADLE_GEN_FOLDER, sourceFolder); + this.environment = environment; } @Override @@ -198,14 +205,45 @@ Iterable possibleLocations() { String gradleVariant = matcher.group(3); String variantPart = gradleVariant.substring(1); - ArrayList possibleLocations = new ArrayList<>(); - + List possibleLocations = new ArrayList<>(); findPossibleLocationsV32(path, variantPart, possibleLocations); for (String directory : Arrays.asList("build/intermediates/manifests/full", "build/intermediates/bundles", "build/intermediates/manifests/aapt")) { findPossibleLocations(path, directory, variantPart, possibleLocations); } - return possibleLocations; + return updateLocations(path, possibleLocations); + } + + private List updateLocations(String path, List possibleLocations) { + List knownLocations = new ArrayList<>(); + for (String location : possibleLocations) { + String expectedLocation = path + "/" + location; + File file = new File(expectedLocation + "/output.json"); + if (file.exists()) { + Matcher matcher = OUTPUT_JSON_PATTERN.matcher(readJsonFromFile(file)); + if (matcher.matches()) { + String relativeManifestPath = matcher.group(1); + File manifestFile = new File(expectedLocation + "/" + relativeManifestPath); + String manifestDirectory = manifestFile.getParentFile().getAbsolutePath(); + knownLocations.add(manifestDirectory.substring(path.length())); + } + } + } + + if (knownLocations.isEmpty()) { + knownLocations.addAll(possibleLocations); + } + + return knownLocations; + } + + private String readJsonFromFile(File file) { + try (BufferedReader fileReader = new BufferedReader(new FileReader(file))) { + return fileReader.readLine(); + } catch (IOException e) { + LOGGER.error(e, "unable to read json file: {}", file); + return ""; + } } private void findPossibleLocationsV32(String basePath, String variantPart, List possibleLocations) { @@ -219,6 +257,11 @@ private void findPossibleLocationsV32(String basePath, String variantPart, List< variantPart = variantPart.substring(1); } + boolean isFeature = environment.getOptionBooleanValue(OPTION_INSTANT_FEATURE) && (variantPart.startsWith("feature/") || variantPart.startsWith("feature\\")); + if (isFeature) { + variantPart = variantPart.substring(8); + } + String[] variantParts = variantPart.split("[/\\\\]"); if (variantParts.length > 1) { StringBuilder sb = new StringBuilder(variantParts[0]); @@ -230,6 +273,11 @@ private void findPossibleLocationsV32(String basePath, String variantPart, List< } String possibleLocation = BUILD_TOOLS_V32_MANIFEST_PATH + "/" + variantPart; + if (isFeature) { + variantPart += "Feature"; + possibleLocation += "Feature"; + } + findPossibleLocations(basePath, possibleLocations, possibleLocation); findPossibleLocations(basePath, possibleLocations, possibleLocation + "/process" + upperCaseFirst(variantPart) + "Manifest/merged"); } diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/internal/helper/AndroidManifestFinderTest.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/internal/helper/AndroidManifestFinderTest.java index db0ffc511e..3a56923801 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/internal/helper/AndroidManifestFinderTest.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/internal/helper/AndroidManifestFinderTest.java @@ -26,9 +26,11 @@ import java.util.Arrays; import java.util.Objects; +import org.androidannotations.AndroidAnnotationsEnvironment; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.mockito.Mockito; @RunWith(Parameterized.class) public class AndroidManifestFinderTest { @@ -158,7 +160,10 @@ public static Iterable createTestData() { @Test public void testFindManifestInKnownPathsStartingFromGenFolder() throws IOException { - AndroidManifestFinder finder = new AndroidManifestFinder(null); + AndroidAnnotationsEnvironment mockEnvironment = Mockito.mock(AndroidAnnotationsEnvironment.class); + Mockito.when(mockEnvironment.getOptionBooleanValue(AndroidManifestFinder.OPTION_INSTANT_FEATURE)).thenReturn(false); + + AndroidManifestFinder finder = new AndroidManifestFinder(mockEnvironment); tempDirectory = Files.createTempDirectory("AA"); File genFolder = createGenFolder(genFolderPath);