mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-01 22:54:26 +02:00
fix multi-package xml compiling #40
This commit is contained in:
parent
e136a8d570
commit
ada5aaf17d
@ -18,8 +18,11 @@ package com.reandroid.apk;
|
||||
import com.reandroid.archive.APKArchive;
|
||||
import com.reandroid.archive.FileInputSource;
|
||||
import com.reandroid.apk.xmlencoder.RESEncoder;
|
||||
import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.archive.InputSourceUtil;
|
||||
import com.reandroid.archive2.block.ApkSignatureBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||
import com.reandroid.json.JSONArray;
|
||||
import com.reandroid.xml.XMLException;
|
||||
|
||||
@ -43,6 +46,7 @@ public class ApkModuleXmlEncoder {
|
||||
scanRootDir(rootDir);
|
||||
restorePathMap(mainDirectory);
|
||||
restoreSignatures(mainDirectory);
|
||||
sortFiles();
|
||||
}
|
||||
private void restoreSignatures(File dir) throws IOException {
|
||||
File sigDir = new File(dir, ApkUtil.SIGNATURE_DIR_NAME);
|
||||
@ -79,6 +83,24 @@ public class ApkModuleXmlEncoder {
|
||||
archive.add(inputSource);
|
||||
}
|
||||
}
|
||||
private void sortFiles(){
|
||||
APKArchive archive=getApkModule().getApkArchive();
|
||||
int i = 1;
|
||||
for(InputSource inputSource:archive.listInputSources()){
|
||||
if(inputSource.getSort() == 0){
|
||||
inputSource.setSort(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
InputSource manifest = archive.getInputSource(AndroidManifestBlock.FILE_NAME);
|
||||
if(manifest != null){
|
||||
manifest.setSort(0);
|
||||
}
|
||||
List<InputSource> sourceList = archive.listInputSources();
|
||||
InputSourceUtil.sort(sourceList);
|
||||
archive.clear();
|
||||
archive.addAll(sourceList);
|
||||
}
|
||||
private void loadUncompressedFiles(File mainDirectory) throws IOException, XMLException {
|
||||
File file=new File(mainDirectory, UncompressedFiles.JSON_FILE);
|
||||
UncompressedFiles uncompressedFiles = getApkModule().getUncompressedFiles();
|
||||
|
@ -29,7 +29,6 @@ import com.reandroid.arsc.util.FrameworkTable;
|
||||
import com.reandroid.arsc.util.HexUtil;
|
||||
import com.reandroid.arsc.util.ResNameMap;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.common.Frameworks;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@ -38,6 +37,7 @@ import java.util.regex.Matcher;
|
||||
public class EncodeMaterials {
|
||||
private final Set<ResourceIds.Table.Package> packageIdSet = new HashSet<>();
|
||||
private PackageBlock currentPackage;
|
||||
private ResourceIds.Table.Package currentLocalPackage;
|
||||
private final Set<FrameworkTable> frameworkTables = new HashSet<>();
|
||||
private APKLogger apkLogger;
|
||||
private boolean mForceCreateNamespaces = true;
|
||||
@ -99,6 +99,10 @@ public class EncodeMaterials {
|
||||
}
|
||||
String type = matcher.group(4);
|
||||
String name = matcher.group(5);
|
||||
if(isLocalPackageName(packageName)){
|
||||
return resolveLocalResourceId(packageName, type, name);
|
||||
}
|
||||
|
||||
if(EncodeUtil.isEmpty(packageName)
|
||||
|| packageName.equals(getCurrentPackageName())
|
||||
|| !isFrameworkPackageName(packageName)){
|
||||
@ -106,13 +110,36 @@ public class EncodeMaterials {
|
||||
}
|
||||
return resolveFrameworkResourceId(packageName, type, name);
|
||||
}
|
||||
private int resolveLocalResourceId(String packageName, String type, String name){
|
||||
ResourceIds.Table.Package pkg = getLocalPackage(packageName);
|
||||
Integer resourceId = pkg.getResourceId(type, name);
|
||||
if(resourceId != null){
|
||||
return resourceId;
|
||||
}
|
||||
EntryGroup entryGroup=getLocalEntryGroup(type, name);
|
||||
if(entryGroup!=null){
|
||||
return entryGroup.getResourceId();
|
||||
}
|
||||
throw new EncodeException("Local entry not found: " +
|
||||
"package=" + packageName +
|
||||
", type=" + type +
|
||||
", name=" + name);
|
||||
}
|
||||
public int resolveLocalResourceId(String type, String name){
|
||||
ResourceIds.Table.Package current = this.currentLocalPackage;
|
||||
if(current != null){
|
||||
Integer resId = current.getResourceId(type, name);
|
||||
if(resId != null){
|
||||
return resId;
|
||||
}
|
||||
}else {
|
||||
for(ResourceIds.Table.Package pkg:packageIdSet){
|
||||
Integer resId = pkg.getResourceId(type, name);
|
||||
if(resId!=null){
|
||||
return resId;
|
||||
}
|
||||
}
|
||||
}
|
||||
EntryGroup entryGroup=getLocalEntryGroup(type, name);
|
||||
if(entryGroup!=null){
|
||||
return entryGroup.getResourceId();
|
||||
@ -286,8 +313,73 @@ public class EncodeMaterials {
|
||||
}
|
||||
public EncodeMaterials setCurrentPackage(PackageBlock currentPackage) {
|
||||
this.currentPackage = currentPackage;
|
||||
onCurrentPackageChanged(currentPackage);
|
||||
return this;
|
||||
}
|
||||
public EncodeMaterials setCurrentLocalPackage(ResourceIds.Table.Package currentLocalPackage) {
|
||||
this.currentLocalPackage = currentLocalPackage;
|
||||
return this;
|
||||
}
|
||||
private void onCurrentPackageChanged(PackageBlock currentPackage){
|
||||
if(currentPackage == null){
|
||||
return;
|
||||
}
|
||||
ResourceIds.Table.Package current = null;
|
||||
if(isUniquePackageIds()){
|
||||
current = getLocalPackage(currentPackage.getId());
|
||||
}
|
||||
if(current == null && isUniquePackageNames()){
|
||||
current = getLocalPackage(currentPackage.getName());
|
||||
}
|
||||
if(current != null){
|
||||
this.currentLocalPackage = current;
|
||||
}
|
||||
}
|
||||
private ResourceIds.Table.Package getLocalPackage(int packageId){
|
||||
byte id = (byte) packageId;
|
||||
for(ResourceIds.Table.Package pkg : packageIdSet){
|
||||
if(id == pkg.id){
|
||||
return pkg;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private ResourceIds.Table.Package getLocalPackage(String name){
|
||||
if(name == null){
|
||||
return null;
|
||||
}
|
||||
for(ResourceIds.Table.Package pkg : packageIdSet){
|
||||
if(name.equals(pkg.name)){
|
||||
return pkg;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private boolean isLocalPackageName(String packageName){
|
||||
if(packageName == null){
|
||||
return false;
|
||||
}
|
||||
for(ResourceIds.Table.Package pkg : packageIdSet){
|
||||
if(packageName.equals(pkg.name)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private boolean isUniquePackageNames(){
|
||||
Set<String> names = new HashSet<>();
|
||||
for(ResourceIds.Table.Package pkg : packageIdSet){
|
||||
names.add(pkg.name);
|
||||
}
|
||||
return names.size() == packageIdSet.size();
|
||||
}
|
||||
private boolean isUniquePackageIds(){
|
||||
Set<Byte> ids = new HashSet<>();
|
||||
for(ResourceIds.Table.Package pkg : packageIdSet){
|
||||
ids.add(pkg.id);
|
||||
}
|
||||
return ids.size() == packageIdSet.size();
|
||||
}
|
||||
public EncodeMaterials addFramework(FrameworkApk frameworkApk) {
|
||||
if(frameworkApk!=null){
|
||||
addFramework(frameworkApk.getTableBlock());
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -15,21 +15,21 @@
|
||||
*/
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.archive.APKArchive;
|
||||
import com.reandroid.archive.FileInputSource;
|
||||
import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.apk.ApkUtil;
|
||||
import com.reandroid.apk.UncompressedFiles;
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.xml.source.XMLFileSource;
|
||||
import com.reandroid.xml.source.XMLSource;
|
||||
import com.reandroid.archive.APKArchive;
|
||||
import com.reandroid.archive.FileInputSource;
|
||||
import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.apk.ApkUtil;
|
||||
import com.reandroid.apk.UncompressedFiles;
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.xml.source.XMLFileSource;
|
||||
import com.reandroid.xml.source.XMLSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class FilePathEncoder {
|
||||
public class FilePathEncoder {
|
||||
private final EncodeMaterials materials;
|
||||
private APKArchive apkArchive;
|
||||
private UncompressedFiles uncompressedFiles;
|
||||
@ -78,6 +78,9 @@ package com.reandroid.apk.xmlencoder;
|
||||
entry.setValueAsString(path);
|
||||
entry.setSpecReference(materials.getSpecString(name));
|
||||
InputSource inputSource=createInputSource(path, resFile);
|
||||
if(inputSource instanceof XMLEncodeSource){
|
||||
((XMLEncodeSource)inputSource).setEntry(entry);
|
||||
}
|
||||
addInputSource(inputSource);
|
||||
return inputSource;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -45,14 +45,13 @@ class PackageCreator {
|
||||
}
|
||||
public PackageBlock createNew(TableBlock tableBlock, ResourceIds.Table.Package pkgResourceIds){
|
||||
loadNames(pkgResourceIds);
|
||||
PackageBlock packageBlock=new PackageBlock();
|
||||
PackageBlock packageBlock = tableBlock.getPackageArray().createNext();
|
||||
packageBlock.setName(mPackageName);
|
||||
packageBlock.setId(mPackageId);
|
||||
|
||||
loadPackageInfoJson(packageBlock);
|
||||
this.mPackageName = packageBlock.getName();
|
||||
|
||||
tableBlock.getPackageArray()
|
||||
.add(packageBlock);
|
||||
packageBlock.getSpecStringPool()
|
||||
.addStrings(mSpecNames);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -13,24 +13,24 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.apk.*;
|
||||
import com.reandroid.archive.APKArchive;
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||
import com.reandroid.xml.XMLDocument;
|
||||
import com.reandroid.xml.XMLException;
|
||||
import com.reandroid.xml.source.XMLFileSource;
|
||||
import com.reandroid.xml.source.XMLSource;
|
||||
import com.reandroid.apk.*;
|
||||
import com.reandroid.archive.APKArchive;
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||
import com.reandroid.xml.XMLDocument;
|
||||
import com.reandroid.xml.XMLException;
|
||||
import com.reandroid.xml.source.XMLFileSource;
|
||||
import com.reandroid.xml.source.XMLSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public class RESEncoder {
|
||||
public class RESEncoder {
|
||||
private APKLogger apkLogger;
|
||||
private final TableBlock tableBlock;
|
||||
private final Set<File> parsedFiles = new HashSet<>();
|
||||
@ -75,7 +75,7 @@
|
||||
Map<File, PackageBlock> packageBlockMap=new HashMap<>();
|
||||
|
||||
for(File pubXmlFile:pubXmlFileList){
|
||||
ResourceIds.Table.Package pkgResourceIds=map.get(pubXmlFile);
|
||||
ResourceIds.Table.Package pkgResourceIds = map.get(pubXmlFile);
|
||||
if(pkgResourceIds==null){
|
||||
continue;
|
||||
}
|
||||
@ -83,6 +83,7 @@
|
||||
|
||||
PackageBlock packageBlock = createPackage(pkgResourceIds, pubXmlFile);
|
||||
encodeMaterials.setCurrentPackage(packageBlock);
|
||||
encodeMaterials.setCurrentLocalPackage(pkgResourceIds);
|
||||
packageBlockMap.put(pubXmlFile, packageBlock);
|
||||
|
||||
ValuesEncoder valuesEncoder = new ValuesEncoder(encodeMaterials);
|
||||
@ -101,12 +102,16 @@
|
||||
addParsedFiles(fileAttrs);
|
||||
}
|
||||
}
|
||||
File manifestFile = null;
|
||||
for(File pubXmlFile:pubXmlFileList){
|
||||
ResourceIds.Table.Package pkgResourceIds=map.get(pubXmlFile);
|
||||
ResourceIds.Table.Package pkgResourceIds = map.get(pubXmlFile);
|
||||
if(pkgResourceIds==null){
|
||||
continue;
|
||||
}
|
||||
addParsedFiles(pubXmlFile);
|
||||
if(manifestFile == null){
|
||||
manifestFile = toAndroidManifest(pubXmlFile);
|
||||
}
|
||||
|
||||
PackageBlock packageBlock=packageBlockMap.get(pubXmlFile);
|
||||
|
||||
@ -114,6 +119,7 @@
|
||||
packageBlock = createPackage(pkgResourceIds, pubXmlFile);
|
||||
}
|
||||
encodeMaterials.setCurrentPackage(packageBlock);
|
||||
encodeMaterials.setCurrentLocalPackage(pkgResourceIds);
|
||||
|
||||
File resDir=toResDirectory(pubXmlFile);
|
||||
encodeResDir(encodeMaterials, resDir);
|
||||
@ -124,16 +130,19 @@
|
||||
|
||||
packageBlock.sortTypes();
|
||||
packageBlock.refresh();
|
||||
|
||||
File manifestFile=toAndroidManifest(pubXmlFile);
|
||||
}
|
||||
tableBlock.refresh();
|
||||
PackageBlock packageBlock = tableBlock.pickOne();
|
||||
if(manifestFile != null){
|
||||
if(packageBlock != null){
|
||||
encodeMaterials.setCurrentPackage(packageBlock);
|
||||
}
|
||||
XMLSource xmlSource =
|
||||
new XMLFileSource(AndroidManifestBlock.FILE_NAME, manifestFile);
|
||||
XMLEncodeSource xmlEncodeSource =
|
||||
new XMLEncodeSource(encodeMaterials, xmlSource);
|
||||
|
||||
getApkModule().getApkArchive().add(xmlEncodeSource);
|
||||
}
|
||||
tableBlock.refresh();
|
||||
}
|
||||
private PackageBlock createPackage(ResourceIds.Table.Package pkgResourceIds
|
||||
, File pubXmlFile){
|
||||
@ -303,4 +312,4 @@
|
||||
apkLogger.logVerbose(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -17,7 +17,9 @@ package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.archive.ByteInputSource;
|
||||
import com.reandroid.apk.CrcOutputStream;
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.xml.XMLException;
|
||||
import com.reandroid.xml.source.XMLSource;
|
||||
|
||||
@ -28,11 +30,27 @@ public class XMLEncodeSource extends ByteInputSource {
|
||||
private final EncodeMaterials encodeMaterials;
|
||||
private final XMLSource xmlSource;
|
||||
private ResXmlDocument resXmlDocument;
|
||||
public XMLEncodeSource(EncodeMaterials encodeMaterials, XMLSource xmlSource){
|
||||
private Entry mEntry;
|
||||
public XMLEncodeSource(EncodeMaterials encodeMaterials, XMLSource xmlSource, Entry entry){
|
||||
super(new byte[0], xmlSource.getPath());
|
||||
this.encodeMaterials=encodeMaterials;
|
||||
this.xmlSource=xmlSource;
|
||||
this.encodeMaterials = encodeMaterials;
|
||||
this.xmlSource = xmlSource;
|
||||
this.mEntry = entry;
|
||||
}
|
||||
public XMLEncodeSource(EncodeMaterials encodeMaterials, XMLSource xmlSource){
|
||||
this(encodeMaterials, xmlSource, null);
|
||||
}
|
||||
|
||||
public XMLSource getXmlSource() {
|
||||
return xmlSource;
|
||||
}
|
||||
public Entry getEntry(){
|
||||
return mEntry;
|
||||
}
|
||||
public void setEntry(Entry entry) {
|
||||
this.mEntry = entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() throws IOException{
|
||||
return getResXmlBlock().countBytes();
|
||||
@ -64,7 +82,13 @@ public class XMLEncodeSource extends ByteInputSource {
|
||||
try {
|
||||
XMLFileEncoder xmlFileEncoder=new XMLFileEncoder(encodeMaterials);
|
||||
xmlFileEncoder.setCurrentPath(xmlSource.getPath());
|
||||
encodeMaterials.logVerbose("Encoding xml: "+xmlSource.getPath());
|
||||
EncodeMaterials encodeMaterials = this.encodeMaterials;
|
||||
encodeMaterials.logVerbose("Encoding xml: " + xmlSource.getPath());
|
||||
PackageBlock currentPackage = encodeMaterials.getCurrentPackage();
|
||||
PackageBlock packageBlock = getEntryPackageBlock();
|
||||
if(packageBlock != null && packageBlock != currentPackage){
|
||||
encodeMaterials.setCurrentPackage(packageBlock);
|
||||
}
|
||||
resXmlDocument = xmlFileEncoder.encode(xmlSource.getXMLDocument());
|
||||
} catch (XMLException ex) {
|
||||
throw new EncodeException("XMLException on: '"+xmlSource.getPath()
|
||||
@ -72,6 +96,13 @@ public class XMLEncodeSource extends ByteInputSource {
|
||||
}
|
||||
return resXmlDocument;
|
||||
}
|
||||
private PackageBlock getEntryPackageBlock(){
|
||||
Entry entry = getEntry();
|
||||
if(entry != null){
|
||||
return entry.getPackageBlock();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void disposeInputSource(){
|
||||
this.xmlSource.disposeXml();
|
||||
|
Loading…
x
Reference in New Issue
Block a user