Use NestedZip linking with copy fallback

Make APK packaging more robust by conditionally embedding the original APK (based on sigbypassLevel) and opening the source as either a NestedZip or a read-only ZFile. Attempt to add file links via NestedZip.addFileLink for entries, and fall back to copying the entry stream on failure or when source is read-only. Clean up related logic (remove the earlier separate embedding block), improve error messages, and minor reordering (minSdkVersion declaration) to streamline patch processing.
This commit is contained in:
NkBe 2026-02-10 21:45:38 +08:00
parent 834fefe421
commit f2713a342b
No known key found for this signature in database
GPG Key ID: 9FACEE0DB6DF678E
1 changed files with 32 additions and 19 deletions

View File

@ -195,8 +195,12 @@ public class NPatch {
logger.i("Parsing original apk...");
boolean embedOriginal = sigbypassLevel >= Constants.SIGBYPASS_LV_PM_OPENAT;
try (ZFile dstZFile = ZFile.openReadWrite(outputFile, Z_FILE_OPTIONS);
NestedZip srcZFile = dstZFile.addNestedZip((ignore) -> ORIGINAL_APK_ASSET_PATH, srcApkFile, false)) {
ZFile srcZFile = embedOriginal
? dstZFile.addNestedZip((ignore) -> Constants.ORIGINAL_APK_ASSET_PATH, srcApkFile, false)
: ZFile.openReadOnly(srcApkFile)) {
// sign apk
try {
@ -239,9 +243,9 @@ public class NPatch {
String newPackage = newPackageName;
int minSdkVersion;
// parse the app appComponentFactory full name from the manifest file
final String appComponentFactory;
int minSdkVersion;
ManifestParser.Pair pair;
try (var is = manifestEntry.open()) {
pair = ManifestParser.parseManifestFile(is);
@ -253,7 +257,7 @@ public class NPatch {
logger.d("original appComponentFactory class: " + appComponentFactory);
logger.d("original minSdkVersion: " + minSdkVersion);
if (newPackage == null || newPackage.isEmpty()){
if (newPackage == null || newPackage.isEmpty()) {
newPackage = pair.packageName;
}
@ -270,7 +274,13 @@ public class NPatch {
if (dstZFile.get(name) != null) continue;
if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA")))
continue;
srcZFile.addFileLink(name, name);
if (srcZFile instanceof NestedZip) {
((NestedZip) srcZFile).addFileLink(name, name);
} else {
try (InputStream is = entry.open()) {
dstZFile.add(name, is);
}
}
}
return;
}
@ -309,14 +319,6 @@ public class NPatch {
} catch (Throwable e) {
throw new PatchError("Error when adding dex", e);
}
if (sigbypassLevel >= Constants.SIGBYPASS_LV_PM_OPENAT) {
logger.i("Embedding original apk for SigBypass...");
try (var is = new FileInputStream(srcApkFile)) {
dstZFile.add(Constants.ORIGINAL_APK_ASSET_PATH, is);
} catch (Throwable e) {
throw new PatchError("Error when embedding original apk", e);
}
}
if (isInjectProvider){
try (var is = getClass().getClassLoader().getResourceAsStream("assets/mtprovider.dex")) {
@ -371,6 +373,16 @@ public class NPatch {
if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA")))
continue;
boolean linked = false;
if (srcZFile instanceof NestedZip) {
try {
linked = ((NestedZip) srcZFile).addFileLink(name, name);
} catch (IOException e) {
logger.e("Failed to link entry: " + name + ", falling back to copy.");
}
}
if (!linked) {
try (InputStream is = entry.open()) {
if (name.endsWith(".so") || name.equals("resources.arsc")) {
dstZFile.add(name, is, false);
@ -381,6 +393,7 @@ public class NPatch {
throw new PatchError("Failed to copy entry: " + name, e);
}
}
}
dstZFile.realign();
logger.i("Writing apk...");