Skip to content

Commit dfca9f5

Browse files
committed
[Manifest-Merge] Delete splits xml and apply extractNativeLibraries #92
1 parent 1b08966 commit dfca9f5

3 files changed

Lines changed: 75 additions & 18 deletions

File tree

src/main/java/com/reandroid/apk/AndroidManifestBlockMerger.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,6 @@ public AndroidManifestBlockMerger initializeBase(AndroidManifestBlock base) {
4848
throw new IllegalArgumentException("Base manifest already initialized");
4949
}
5050
this.baseManifest = base;
51-
AndroidManifestBlockSplitSanitizer sanitizer = getSplitSanitizer();
52-
if (sanitizer != null) {
53-
sanitizer.sanitize(base);
54-
}
5551
return this;
5652
}
5753

@@ -91,15 +87,25 @@ public boolean merge(AndroidManifestBlock split) {
9187
return false;
9288
}
9389
boolean result = mergeManifestElement(split.getManifestElement());
94-
AndroidManifestBlockSplitSanitizer sanitizer = getSplitSanitizer();
95-
if (sanitizer != null) {
96-
result = sanitizer.sanitize(base) || result;
90+
if (base.isExtractNativeLibs() == null) {
91+
Boolean extractNativeLibs = split.isExtractNativeLibs();
92+
if (extractNativeLibs != null) {
93+
base.setExtractNativeLibs(extractNativeLibs);
94+
result = true;
95+
}
9796
}
9897
if (result) {
9998
base.refresh();
10099
}
101100
return result;
102101
}
102+
public boolean sanitize(ApkModule apkModule) {
103+
AndroidManifestBlockSplitSanitizer sanitizer = getSplitSanitizer();
104+
if (sanitizer != null) {
105+
return sanitizer.sanitize(apkModule);
106+
}
107+
return false;
108+
}
103109
private boolean mergeManifestElement(ResXmlElement manifest) {
104110
boolean result = false;
105111
Iterator<ResXmlElement> iterator = manifest.getElements();

src/main/java/com/reandroid/apk/AndroidManifestBlockSplitSanitizer.java

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@
1616
package com.reandroid.apk;
1717

1818
import com.reandroid.app.AndroidManifest;
19+
import com.reandroid.arsc.chunk.TableBlock;
1920
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
21+
import com.reandroid.arsc.chunk.xml.ResXmlAttribute;
22+
import com.reandroid.arsc.chunk.xml.ResXmlElement;
23+
import com.reandroid.arsc.model.ResourceEntry;
24+
import com.reandroid.arsc.value.Entry;
25+
import com.reandroid.arsc.value.ValueType;
2026
import com.reandroid.utils.collection.CollectionUtil;
27+
import com.reandroid.utils.collection.ComputeIterator;
2128
import com.reandroid.xml.XMLPath;
2229

2330
import java.util.Set;
@@ -27,15 +34,11 @@ public class AndroidManifestBlockSplitSanitizer {
2734
private boolean mEnabled;
2835
private final Set<XMLPath> removeAttributeList;
2936
private final Set<XMLPath> removeElementList;
37+
private final XMLPath splitsPath;
3038

3139
public AndroidManifestBlockSplitSanitizer() {
3240
this.mEnabled = true;
3341

34-
XMLPath manifest = XMLPath.newElement(AndroidManifest.TAG_manifest);
35-
XMLPath application = manifest.element(AndroidManifest.TAG_application);
36-
XMLPath appMetaData = application.element(AndroidManifest.TAG_meta_data);
37-
XMLPath appMetaDataName = appMetaData.attribute(AndroidManifest.ID_name);
38-
3942
this.removeAttributeList = CollectionUtil.asHashSet(
4043
XMLPath.newElement(XMLPath.ANY_ELEMENT_PATH)
4144
.attribute(AndroidManifest.ID_isFeatureSplit)
@@ -51,12 +54,16 @@ public AndroidManifestBlockSplitSanitizer() {
5154
.alternate(AndroidManifest.NAME_isSplitRequired)
5255
);
5356

57+
XMLPath appMetaDataName = AndroidManifest.PATH_APPLICATION_META_DATA_NAME;
58+
59+
this.splitsPath = appMetaDataName.value("com.android.vending.splits");
60+
5461
this.removeElementList = CollectionUtil.asHashSet(
55-
manifest.element(AndroidManifest.TAG_uses_split),
56-
appMetaDataName.value("com.android.vending.splits.required"),
57-
appMetaDataName.value("com.android.vending.splits"),
58-
appMetaDataName.value("com.android.stamp.source"),
59-
appMetaDataName.value("com.android.stamp.type")
62+
AndroidManifest.PATH_MANIFEST.element(AndroidManifest.TAG_uses_split),
63+
appMetaDataName.alternateValue("com.android.vending.splits.required"),
64+
appMetaDataName.alternateValue("com.android.stamp.source"),
65+
appMetaDataName.alternateValue("com.android.stamp.type"),
66+
appMetaDataName.alternateValue("com.android.vending.derived.apk.id")
6067
);
6168
}
6269

@@ -77,6 +84,19 @@ public boolean isEnabled() {
7784
return mEnabled;
7885
}
7986

87+
public boolean sanitize(ApkModule apkModule) {
88+
if (!isEnabled()) {
89+
return false;
90+
}
91+
AndroidManifestBlock manifestBlock = apkModule.getAndroidManifest();
92+
if (manifestBlock == null) {
93+
return false;
94+
}
95+
boolean result = sanitize(manifestBlock);
96+
result = deleteSplitsXml(apkModule, manifestBlock) || result;
97+
apkModule.setExtractNativeLibs(manifestBlock.isExtractNativeLibs());
98+
return result;
99+
}
80100
public boolean sanitize(AndroidManifestBlock manifestBlock) {
81101
if (!isEnabled()) {
82102
return false;
@@ -89,7 +109,35 @@ public boolean sanitize(AndroidManifestBlock manifestBlock) {
89109
result = removeElements(manifestBlock) || result;
90110
return result;
91111
}
92-
112+
private boolean deleteSplitsXml(ApkModule apkModule, AndroidManifestBlock manifestBlock) {
113+
ResXmlElement element = manifestBlock.getNamedElement(AndroidManifest.PATH_APPLICATION_META_DATA,
114+
"com.android.vending.splits");
115+
if (element == null) {
116+
return false;
117+
}
118+
ResXmlAttribute attribute = element.searchAttributeByResourceId(AndroidManifest.ID_resource);
119+
if (attribute == null) {
120+
attribute = element.searchAttributeByResourceId(AndroidManifest.ID_value);
121+
}
122+
if (attribute == null || attribute.getValueType() != ValueType.REFERENCE) {
123+
return false;
124+
}
125+
TableBlock tableBlock = apkModule.getTableBlock();
126+
if (tableBlock == null) {
127+
return false;
128+
}
129+
ResourceEntry resourceEntry = tableBlock.getResource(attribute.getData());
130+
if (resourceEntry == null) {
131+
return false;
132+
}
133+
element.removeSelf();
134+
String path = CollectionUtil.getFirst(ComputeIterator.of(
135+
resourceEntry.iterator(true), Entry::getValueAsString));
136+
if (path != null) {
137+
return apkModule.removeResFile(path, false);
138+
}
139+
return true;
140+
}
93141
private boolean removeAttributes(AndroidManifestBlock manifestBlock) {
94142
boolean results = false;
95143
for (XMLPath path : removeAttributeList) {

src/main/java/com/reandroid/apk/ApkBundle.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ public ApkModule mergeModules(boolean force) throws IOException {
7474
manifestMerger.merge(module.getAndroidManifest());
7575
}
7676
}
77+
if (manifestMerger != null) {
78+
manifestMerger.sanitize(result);
79+
}
7780

7881
result.setApkSignatureBlock(signatureBlock);
7982

0 commit comments

Comments
 (0)