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));
}
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();
}
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());
}
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);
}
Aggregations