Search in sources :

Example 11 with XmlProtoElement

use of com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement in project bundletool by google.

the class XmlProtoToXmlConverterTest method testConversionManifest.

@Test
public void testConversionManifest() {
    XmlProtoElement manifestElement = XmlProtoElementBuilder.create("manifest").addNamespaceDeclaration("android", ANDROID_NS).addNamespaceDeclaration("dist", DIST_NS).addAttribute(newAttribute("package").setValueAsString("com.example.app")).addAttribute(newAttribute(ANDROID_NS, "versionCode").setValueAsDecimalInteger(123)).addAttribute(newAttribute(ANDROID_NS, "versionName").setValueAsString("1.2.3")).addChildElement(XmlProtoElementBuilder.create(DIST_NS, "module").addAttribute(newAttribute(DIST_NS, "onDemand").setValueAsBoolean(true)).addAttribute(newAttribute(DIST_NS, "title").setValueAsRefId(0x7f0b0001, "string/title_module"))).addChildElement(XmlProtoElementBuilder.create("application").addAttribute(newAttribute(ANDROID_NS, "name").setValueAsString(".MyApp")).addAttribute(newAttribute(ANDROID_NS, "icon").setValueAsRefId(0x7f010005, "mipmap/ic_launcher")).addAttribute(newAttribute(ANDROID_NS, "supportsRtl").setValueAsBoolean(true)).addChildElement(XmlProtoElementBuilder.create("meta-data").addAttribute(newAttribute(ANDROID_NS, "name").setValueAsString("com.google.android.gms.version")).addAttribute(newAttribute(ANDROID_NS, "value").setValueAsRefId(0x7f0b0002, "integer/google_play_services_version"))).addChildElement(XmlProtoElementBuilder.create("activity").addAttribute(newAttribute(ANDROID_NS, "exported").setValueAsBoolean(true)).addAttribute(newAttribute(ANDROID_NS, "name").setValueAsString("com.example.app.MyActivity")))).build();
    XmlProtoNode manifestProto = XmlProtoNode.createElementNode(manifestElement);
    Document manifestXml = XmlProtoToXmlConverter.convert(manifestProto);
    assertThat(XmlUtils.documentToString(manifestXml)).isEqualTo(LINE_BREAK_JOINER.join("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" " + "xmlns:dist=\"http://schemas.android.com/apk/distribution\" " + "android:versionCode=\"123\" " + "android:versionName=\"1.2.3\" " + "package=\"com.example.app\">", "  <dist:module dist:onDemand=\"true\" dist:title=\"@string/title_module\"/>", "  <application android:icon=\"@mipmap/ic_launcher\" " + "android:name=\".MyApp\" " + "android:supportsRtl=\"true\">", "    <meta-data android:name=\"com.google.android.gms.version\" " + "android:value=\"@integer/google_play_services_version\"/>", "    <activity android:exported=\"true\" " + "android:name=\"com.example.app.MyActivity\"/>", "  </application>", "</manifest>" + LINE_BREAK));
}
Also used : Document(org.w3c.dom.Document) XmlProtoElement(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement) XmlProtoNode(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoNode) Test(org.junit.Test)

Example 12 with XmlProtoElement

use of com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement in project bundletool by google.

the class FusingAndroidManifestMerger method mergeManifests.

private AndroidManifest mergeManifests(AndroidManifest baseManifest, List<AndroidManifest> featureManifests) {
    // Gather all child elements of 'application' from all manifest. If element with the same name
    // and type is presented in more than one manifest we give precedency to one in feature module.
    // All feature manifests are sorted by feature module name in this method.
    ImmutableListMultimap<ApplicationElementId, XmlProtoElement> applicationElements = gatherApplicationElementsManifests(ImmutableList.<AndroidManifest>builder().addAll(featureManifests).add(baseManifest).build(), elementsToMerge);
    // This is optimization that allows to skip merging if there is no mergeable elements in
    // feature modules.
    long numberOfMergeableElementsInBase = baseManifest.getManifestRoot().getElement().getChildrenElements(AndroidManifest.APPLICATION_ELEMENT_NAME).flatMap(application -> application.getChildrenElements()).filter(element -> elementsToMerge.contains(element.getName())).count();
    if (numberOfMergeableElementsInBase == applicationElements.size()) {
        return baseManifest;
    }
    // Merge manifest elements with the same name and type based on specified mode.
    ImmutableMap<ApplicationElementId, XmlProtoElement> mergedElements = applicationElements.keySet().stream().collect(toImmutableMap(Function.identity(), key -> mergeElements(key, applicationElements.get(key))));
    ManifestEditor manifestEditor = baseManifest.toEditor();
    XmlProtoElementBuilder applicationElement = manifestEditor.getRawProto().getOrCreateChildElement(AndroidManifest.APPLICATION_ELEMENT_NAME);
    // Replace original elements from the base manifest with merged ones. This is done in a way to
    // preserve original elements ordering and additional elements are added to the end.
    Set<XmlProtoElement> replacedElements = Sets.newIdentityHashSet();
    applicationElement.modifyChildElements(child -> stream(getCorrespondingElementFromMergedElements(child, mergedElements)).peek(replacedElements::add).map(element -> XmlProtoNodeBuilder.createElementNode(element.toBuilder())).collect(toOptional()).orElse(child));
    mergedElements.values().stream().filter(not(replacedElements::contains)).forEach(element -> applicationElement.addChildElement(element.toBuilder()));
    return manifestEditor.save();
}
Also used : Iterables(com.google.common.collect.Iterables) BundleModuleName(com.android.tools.build.bundletool.model.BundleModuleName) AndroidManifest(com.android.tools.build.bundletool.model.AndroidManifest) XmlProtoAttributeBuilder(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoAttributeBuilder) BASE_MODULE_NAME(com.android.tools.build.bundletool.model.BundleModuleName.BASE_MODULE_NAME) Function(java.util.function.Function) Predicates.not(com.google.common.base.Predicates.not) ImmutableList(com.google.common.collect.ImmutableList) Map(java.util.Map) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) XmlProtoNodeBuilder(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoNodeBuilder) XmlProtoElement(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement) MoreCollectors.toOptional(com.google.common.collect.MoreCollectors.toOptional) XmlProtoElementBuilder(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElementBuilder) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) CommandExecutionException(com.android.tools.build.bundletool.model.exceptions.CommandExecutionException) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) SetMultimap(com.google.common.collect.SetMultimap) Sets(com.google.common.collect.Sets) Streams.stream(com.google.common.collect.Streams.stream) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) List(java.util.List) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) AutoValue(com.google.auto.value.AutoValue) Optional(java.util.Optional) ManifestEditor(com.android.tools.build.bundletool.model.ManifestEditor) Comparator(java.util.Comparator) XmlProtoElementBuilder(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElementBuilder) ManifestEditor(com.android.tools.build.bundletool.model.ManifestEditor) AndroidManifest(com.android.tools.build.bundletool.model.AndroidManifest) XmlProtoElement(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement)

Example 13 with XmlProtoElement

use of com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement in project bundletool by google.

the class ManifestDeliveryElement method parseDeviceGroupsCondition.

private DeviceGroupsCondition parseDeviceGroupsCondition(XmlProtoElement conditionElement) {
    ImmutableList<XmlProtoElement> children = conditionElement.getChildrenElements().collect(toImmutableList());
    if (children.isEmpty()) {
        throw InvalidBundleException.builder().withUserMessage("At least one device group should be specified in '<dist:%s>' element.", CONDITION_DEVICE_GROUPS_NAME).build();
    }
    ImmutableSet.Builder<String> deviceGroups = ImmutableSet.builder();
    for (XmlProtoElement deviceGroupElement : children) {
        if (!deviceGroupElement.getName().equals(DEVICE_GROUP_ELEMENT_NAME)) {
            throw InvalidBundleException.builder().withUserMessage("Expected only '<dist:%s>' elements inside '<dist:%s>', but found %s.", DEVICE_GROUP_ELEMENT_NAME, CONDITION_DEVICE_GROUPS_NAME, printElement(deviceGroupElement)).build();
        }
        String groupName = deviceGroupElement.getAttribute(DISTRIBUTION_NAMESPACE_URI, NAME_ATTRIBUTE_NAME).map(XmlProtoAttribute::getValueAsString).orElseThrow(() -> InvalidBundleException.builder().withUserMessage("'<dist:%s>' element is expected to have 'dist:%s' attribute " + "but found none.", DEVICE_GROUP_ELEMENT_NAME, NAME_ATTRIBUTE_NAME).build());
        DeviceTargetingUtils.validateDeviceGroupForConditionalModule(groupName);
        deviceGroups.add(groupName);
    }
    return DeviceGroupsCondition.create(deviceGroups.build());
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) XmlProtoElement(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement)

Example 14 with XmlProtoElement

use of com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement in project bundletool by google.

the class ManifestDeliveryElement method parseUserCountriesCondition.

private UserCountriesCondition parseUserCountriesCondition(XmlProtoElement conditionElement) {
    ImmutableList.Builder<String> countryCodes = ImmutableList.builder();
    for (XmlProtoElement countryElement : conditionElement.getChildrenElements().collect(toImmutableList())) {
        if (!countryElement.getName().equals(COUNTRY_ELEMENT_NAME)) {
            throw InvalidBundleException.builder().withUserMessage("Expected only <dist:country> elements inside <dist:user-countries>, but found %s", printElement(conditionElement)).build();
        }
        countryCodes.add(countryElement.getAttribute(DISTRIBUTION_NAMESPACE_URI, CODE_ATTRIBUTE_NAME).map(XmlProtoAttribute::getValueAsString).map(String::toUpperCase).orElseThrow(() -> InvalidBundleException.builder().withUserMessage("<dist:country> element is expected to have 'dist:code' attribute " + "but found none.").build()));
    }
    boolean exclude = conditionElement.getAttribute(DISTRIBUTION_NAMESPACE_URI, EXCLUDE_ATTRIBUTE_NAME).map(XmlProtoAttribute::getValueAsBoolean).orElse(false);
    return UserCountriesCondition.create(countryCodes.build(), exclude);
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) XmlProtoElement(com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement)

Aggregations

XmlProtoElement (com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElement)14 Test (org.junit.Test)7 XmlProtoNode (com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoNode)3 ImmutableList (com.google.common.collect.ImmutableList)3 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)3 ImmutableSet (com.google.common.collect.ImmutableSet)3 AndroidManifest (com.android.tools.build.bundletool.model.AndroidManifest)2 BundleModuleName (com.android.tools.build.bundletool.model.BundleModuleName)2 BASE_MODULE_NAME (com.android.tools.build.bundletool.model.BundleModuleName.BASE_MODULE_NAME)2 ManifestEditor (com.android.tools.build.bundletool.model.ManifestEditor)2 CommandExecutionException (com.android.tools.build.bundletool.model.exceptions.CommandExecutionException)2 InvalidBundleException (com.android.tools.build.bundletool.model.exceptions.InvalidBundleException)2 XmlProtoAttributeBuilder (com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoAttributeBuilder)2 XmlProtoElementBuilder (com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoElementBuilder)2 XmlProtoNodeBuilder (com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoNodeBuilder)2 AutoValue (com.google.auto.value.AutoValue)2 Predicates.not (com.google.common.base.Predicates.not)2 ImmutableListMultimap (com.google.common.collect.ImmutableListMultimap)2 ImmutableMap (com.google.common.collect.ImmutableMap)2 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)2