From fa97a2c74bf71baa128b293406d875b8bb8d5ac8 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Mon, 9 Jan 2023 09:47:24 -0500 Subject: [PATCH] handle multiple packages on xml encoding --- .../com/reandroid/lib/apk/ResourceIds.java | 1 + .../lib/apk/xmlencoder/EncodeMaterials.java | 42 +++++++---- .../lib/apk/xmlencoder/RESEncoder.java | 75 +++++++++++-------- 3 files changed, 71 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/reandroid/lib/apk/ResourceIds.java b/src/main/java/com/reandroid/lib/apk/ResourceIds.java index 3a62be9..08a63ee 100644 --- a/src/main/java/com/reandroid/lib/apk/ResourceIds.java +++ b/src/main/java/com/reandroid/lib/apk/ResourceIds.java @@ -83,6 +83,7 @@ import java.util.*; public void fromXml(XMLDocument xmlDocument) throws IOException { mTable.fromXml(xmlDocument); } + public XMLDocument toXMLDocument(){ return mTable.toXMLDocument(); } diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/EncodeMaterials.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/EncodeMaterials.java index 0b1310f..cb6623b 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/EncodeMaterials.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/EncodeMaterials.java @@ -35,11 +35,12 @@ import java.util.regex.Matcher; public class EncodeMaterials implements ResourceResolver { - private ResourceIds.Table.Package packageIds; + private final Set packageIdSet = new HashSet<>(); private PackageBlock currentPackage; private final Set frameworkTables = new HashSet<>(); private APKLogger apkLogger; private boolean mForceCreateNamespaces = true; + private Set mFrameworkPackageNames; public EncodeMaterials(){ } public SpecString getSpecString(String name){ @@ -134,10 +135,11 @@ return getFrameworkEntry(packageName, type, name); } public int resolveLocalResourceId(String type, String name){ - ResourceIds.Table.Package.Type.Entry entry = - this.packageIds.getEntry(type, name); - if(entry!=null){ - return entry.getResourceId(); + for(ResourceIds.Table.Package pkg:packageIdSet){ + ResourceIds.Table.Package.Type.Entry entry = pkg.getEntry(type, name); + if(entry!=null){ + return entry.getResourceId(); + } } EntryGroup entryGroup=getLocalEntryGroup(type, name); if(entryGroup!=null){ @@ -240,14 +242,20 @@ return null; } private boolean isFrameworkPackageName(String packageName){ + return getFrameworkPackageNames().contains(packageName); + } + private Set getFrameworkPackageNames(){ + if(mFrameworkPackageNames!=null){ + return mFrameworkPackageNames; + } + Set results=new HashSet<>(); for(FrameworkTable table:frameworkTables){ for(PackageBlock packageBlock:table.listPackages()){ - if(packageName.equals(packageBlock.getName())){ - return true; - } + results.add(packageBlock.getName()); } } - return false; + mFrameworkPackageNames=results; + return results; } public EntryBlock getFrameworkEntry(String packageName, String type, String name){ for(FrameworkTable table:frameworkTables){ @@ -280,8 +288,12 @@ this.mForceCreateNamespaces = force; return this; } - public EncodeMaterials setPackageIds(ResourceIds.Table.Package packageIds) { - this.packageIds = packageIds; + public EncodeMaterials addPackageIds(Collection packageIdList) { + this.packageIdSet.addAll(packageIdList); + return this; + } + public EncodeMaterials addPackageIds(ResourceIds.Table.Package packageIds) { + this.packageIdSet.add(packageIds); return this; } public EncodeMaterials setCurrentPackage(PackageBlock currentPackage) { @@ -291,6 +303,7 @@ public EncodeMaterials addFramework(FrameworkTable frameworkTable) { frameworkTable.loadResourceNameMap(); this.frameworkTables.add(frameworkTable); + this.mFrameworkPackageNames=null; return this; } public EncodeMaterials setAPKLogger(APKLogger logger) { @@ -298,9 +311,6 @@ return this; } - public ResourceIds.Table.Package getPackageIds() { - return packageIds; - } public PackageBlock getCurrentPackage() { return currentPackage; } @@ -317,7 +327,7 @@ @Override public int resolveResourceId(String packageName, String type, String name) { - if(packageName==null || packageName.equals(getCurrentPackageName())){ + if(!isFrameworkPackageName(packageName)){ return resolveLocalResourceId(type, name); } return resolveFrameworkResourceId(packageName, type, name); @@ -356,7 +366,7 @@ resourceIds.loadPackageBlock(packageBlock); ResourceIds.Table.Package packageId = resourceIds.getTable().listPackages().get(0); return new EncodeMaterials() - .setPackageIds(packageId) + .addPackageIds(packageId) .setCurrentPackage(packageBlock) .addFramework(Frameworks.getAndroid()); } diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/RESEncoder.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/RESEncoder.java index 2fd8105..0610ef4 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/RESEncoder.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/RESEncoder.java @@ -28,10 +28,7 @@ import java.io.File; import java.io.IOException; - import java.util.ArrayList; - import java.util.HashSet; - import java.util.List; - import java.util.Set; + import java.util.*; import java.util.zip.ZipEntry; public class RESEncoder { @@ -70,9 +67,23 @@ +ApkUtil.FILE_NAME_PUBLIC_XML+" file found in '"+mainDir); } preloadStringPool(pubXmlFileList); - for(File pubXmlFile:pubXmlFileList){ - EncodeMaterials encodeMaterials = loadPublicXml(pubXmlFile); + + EncodeMaterials encodeMaterials=new EncodeMaterials(); + + Map map = + initializeEncodeMaterials(pubXmlFileList, encodeMaterials); + + for(Map.Entry entry:map.entrySet()){ + File pubXmlFile=entry.getKey(); + ResourceIds.Table.Package pkgResourceIds=entry.getValue(); addParsedFiles(pubXmlFile); + + PackageCreator packageCreator = new PackageCreator(); + packageCreator.setPackageName(pkgResourceIds.name); + + PackageBlock packageBlock = packageCreator.createNew(tableBlock, pkgResourceIds); + encodeMaterials.setCurrentPackage(packageBlock); + File resDir=toResDirectory(pubXmlFile); encodeResDir(encodeMaterials, resDir); FilePathEncoder filePathEncoder = new FilePathEncoder(encodeMaterials); @@ -80,7 +91,6 @@ filePathEncoder.setUncompressedFiles(getApkModule().getUncompressedFiles()); filePathEncoder.encodeResDir(resDir); - PackageBlock packageBlock = encodeMaterials.getCurrentPackage(); packageBlock.sortTypes(); packageBlock.refresh(); @@ -99,7 +109,6 @@ ValuesStringPoolBuilder poolBuilder=new ValuesStringPoolBuilder(); for(File pubXml:pubXmlFileList){ File resDir=toResDirectory(pubXml); - logMessage("Scanning: "+resDir.getParentFile().getName()); List valuesDirList = listValuesDir(resDir); for(File dir:valuesDirList){ logVerbose(poolBuilder.size()+" building pool: "+dir.getName()); @@ -108,33 +117,37 @@ } poolBuilder.addTo(tableBlock.getTableStringPool()); } - private EncodeMaterials loadPublicXml(File pubXmlFile) throws IOException, XMLException { - ResourceIds resourceIds=new ResourceIds(); - resourceIds.fromXml(pubXmlFile); - List pkgList = resourceIds - .getTable().listPackages(); - if(pkgList.size()!=1){ - throw new IOException("Package count should be 1, count=" - +pkgList.size()+", in file: "+pubXmlFile); + private Map initializeEncodeMaterials( + List pubXmlFileList, EncodeMaterials encodeMaterials) + throws IOException, XMLException { + + Map results = new HashMap<>(); + + String packageName=null; + for(File pubXmlFile:pubXmlFileList){ + if(packageName==null){ + packageName=readManifestPackageName(toAndroidManifest(pubXmlFile)); + } + ResourceIds resourceIds=new ResourceIds(); + resourceIds.fromXml(pubXmlFile); + ResourceIds.Table.Package pkg = resourceIds.getTable() + .listPackages().get(0); + if(pkg.name==null){ + pkg.name=packageName; + } + encodeMaterials.addPackageIds(pkg); + results.put(pubXmlFile, pkg); } - XMLDocument manifestDocument = XMLDocument.load(toAndroidManifest(pubXmlFile)); - String packageName = manifestDocument - .getDocumentElement().getAttributeValue("package"); - - ResourceIds.Table.Package pkgResourceIds = pkgList.get(0); - - PackageCreator packageCreator = new PackageCreator(); - packageCreator.setPackageName(packageName); - - PackageBlock packageBlock = packageCreator.createNew(tableBlock, pkgResourceIds); - - return new EncodeMaterials() - .addFramework(Frameworks.getAndroid()) - .setCurrentPackage(packageBlock) - .setPackageIds(pkgResourceIds) + encodeMaterials.addFramework(Frameworks.getAndroid()) .setAPKLogger(apkLogger); + return results; + } + private String readManifestPackageName(File manifestFile) throws XMLException { + XMLDocument manifestDocument = XMLDocument.load(manifestFile); + return manifestDocument + .getDocumentElement().getAttributeValue("package"); } private void encodeResDir(EncodeMaterials materials, File resDir) throws XMLException {