mirror of
https://github.com/revanced/Apktool.git
synced 2025-05-06 08:44:30 +02:00
Added possibility to keep invalid resources, so they could be fixed manually.
This commit is contained in:
parent
0c1a55cb31
commit
430fc72388
@ -17,6 +17,7 @@
|
|||||||
package brut.androlib;
|
package brut.androlib;
|
||||||
|
|
||||||
import brut.androlib.err.OutDirExistsException;
|
import brut.androlib.err.OutDirExistsException;
|
||||||
|
import brut.androlib.res.AndrolibResources;
|
||||||
import brut.androlib.res.data.ResPackage;
|
import brut.androlib.res.data.ResPackage;
|
||||||
import brut.androlib.res.data.ResTable;
|
import brut.androlib.res.data.ResTable;
|
||||||
import brut.androlib.res.util.ExtFile;
|
import brut.androlib.res.util.ExtFile;
|
||||||
@ -128,12 +129,17 @@ public class ApkDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setKeepBrokenResources(boolean keepBrokenResources) {
|
||||||
|
mKeepBrokenResources = keepBrokenResources;
|
||||||
|
}
|
||||||
|
|
||||||
public ResTable getResTable() throws AndrolibException {
|
public ResTable getResTable() throws AndrolibException {
|
||||||
if (mResTable == null) {
|
if (mResTable == null) {
|
||||||
if (! hasResources()) {
|
if (! hasResources()) {
|
||||||
throw new AndrolibException(
|
throw new AndrolibException(
|
||||||
"Apk doesn't containt resources.arsc file");
|
"Apk doesn't containt resources.arsc file");
|
||||||
}
|
}
|
||||||
|
AndrolibResources.sKeepBroken = mKeepBrokenResources;
|
||||||
mResTable = mAndrolib.getResTable(mApkFile);
|
mResTable = mAndrolib.getResTable(mApkFile);
|
||||||
mResTable.setFrameTag(mFrameTag);
|
mResTable.setFrameTag(mFrameTag);
|
||||||
}
|
}
|
||||||
@ -218,4 +224,5 @@ public class ApkDecoder {
|
|||||||
private boolean mDebug = false;
|
private boolean mDebug = false;
|
||||||
private boolean mForceDelete = false;
|
private boolean mForceDelete = false;
|
||||||
private String mFrameTag;
|
private String mFrameTag;
|
||||||
|
private boolean mKeepBrokenResources = false;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,8 @@ final public class AndrolibResources {
|
|||||||
public ResPackage loadMainPkg(ResTable resTable, ExtFile apkFile)
|
public ResPackage loadMainPkg(ResTable resTable, ExtFile apkFile)
|
||||||
throws AndrolibException {
|
throws AndrolibException {
|
||||||
LOGGER.info("Loading resource table...");
|
LOGGER.info("Loading resource table...");
|
||||||
ResPackage[] pkgs = getResPackagesFromApk(apkFile, resTable);
|
ResPackage[] pkgs = getResPackagesFromApk(
|
||||||
|
apkFile, resTable, sKeepBroken);
|
||||||
ResPackage pkg = null;
|
ResPackage pkg = null;
|
||||||
|
|
||||||
switch (pkgs.length) {
|
switch (pkgs.length) {
|
||||||
@ -78,7 +79,8 @@ final public class AndrolibResources {
|
|||||||
File apk = getFrameworkApk(id, frameTag);
|
File apk = getFrameworkApk(id, frameTag);
|
||||||
|
|
||||||
LOGGER.info("Loading resource table from file: " + apk);
|
LOGGER.info("Loading resource table from file: " + apk);
|
||||||
ResPackage[] pkgs = getResPackagesFromApk(new ExtFile(apk), resTable);
|
ResPackage[] pkgs = getResPackagesFromApk(
|
||||||
|
new ExtFile(apk), resTable, true);
|
||||||
|
|
||||||
if (pkgs.length != 1) {
|
if (pkgs.length != 1) {
|
||||||
throw new AndrolibException(
|
throw new AndrolibException(
|
||||||
@ -300,11 +302,11 @@ final public class AndrolibResources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ResPackage[] getResPackagesFromApk(ExtFile apkFile,
|
private ResPackage[] getResPackagesFromApk(ExtFile apkFile,
|
||||||
ResTable resTable) throws AndrolibException {
|
ResTable resTable, boolean keepBroken) throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
return ARSCDecoder.decode(
|
return ARSCDecoder.decode(
|
||||||
apkFile.getDirectory().getFileInput("resources.arsc"), false,
|
apkFile.getDirectory().getFileInput("resources.arsc"), false,
|
||||||
resTable).getPackages();
|
keepBroken, resTable).getPackages();
|
||||||
} catch (DirectoryException ex) {
|
} catch (DirectoryException ex) {
|
||||||
throw new AndrolibException(
|
throw new AndrolibException(
|
||||||
"Could not load resources.arsc from file: " + apkFile, ex);
|
"Could not load resources.arsc from file: " + apkFile, ex);
|
||||||
@ -372,7 +374,7 @@ final public class AndrolibResources {
|
|||||||
byte[] data = IOUtils.toByteArray(in);
|
byte[] data = IOUtils.toByteArray(in);
|
||||||
|
|
||||||
ARSCData arsc = ARSCDecoder.decode(
|
ARSCData arsc = ARSCDecoder.decode(
|
||||||
new ByteArrayInputStream(data), true);
|
new ByteArrayInputStream(data), true, true);
|
||||||
publicizeResources(data, arsc.getFlagsOffsets());
|
publicizeResources(data, arsc.getFlagsOffsets());
|
||||||
|
|
||||||
File outFile = new File(getFrameworkDir(),
|
File outFile = new File(getFrameworkDir(),
|
||||||
@ -439,7 +441,7 @@ final public class AndrolibResources {
|
|||||||
|
|
||||||
public void publicizeResources(byte[] arsc) throws AndrolibException {
|
public void publicizeResources(byte[] arsc) throws AndrolibException {
|
||||||
publicizeResources(arsc,
|
publicizeResources(arsc,
|
||||||
ARSCDecoder.decode(new ByteArrayInputStream(arsc), true)
|
ARSCDecoder.decode(new ByteArrayInputStream(arsc), true, true)
|
||||||
.getFlagsOffsets());
|
.getFlagsOffsets());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,6 +553,11 @@ final public class AndrolibResources {
|
|||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: dirty static hack. I have to refactor decoding mechanisms.
|
||||||
|
public static boolean sKeepBroken = false;
|
||||||
|
|
||||||
|
|
||||||
private final static Logger LOGGER =
|
private final static Logger LOGGER =
|
||||||
Logger.getLogger(AndrolibResources.class.getName());
|
Logger.getLogger(AndrolibResources.class.getName());
|
||||||
}
|
}
|
||||||
|
@ -34,16 +34,17 @@ import org.apache.commons.io.input.CountingInputStream;
|
|||||||
*/
|
*/
|
||||||
public class ARSCDecoder {
|
public class ARSCDecoder {
|
||||||
public static ARSCData decode(InputStream arscStream,
|
public static ARSCData decode(InputStream arscStream,
|
||||||
boolean findFlagsOffsets) throws AndrolibException {
|
boolean findFlagsOffsets, boolean keepBroken)
|
||||||
return decode(arscStream, findFlagsOffsets, new ResTable());
|
throws AndrolibException {
|
||||||
|
return decode(arscStream, findFlagsOffsets, keepBroken, new ResTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ARSCData decode(InputStream arscStream,
|
public static ARSCData decode(InputStream arscStream,
|
||||||
boolean findFlagsOffsets, ResTable resTable)
|
boolean findFlagsOffsets, boolean keepBroken, ResTable resTable)
|
||||||
throws AndrolibException {
|
throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
ARSCDecoder decoder = new ARSCDecoder(arscStream, resTable,
|
ARSCDecoder decoder = new ARSCDecoder(arscStream, resTable,
|
||||||
findFlagsOffsets);
|
findFlagsOffsets, keepBroken);
|
||||||
ResPackage[] pkgs = decoder.readTable();
|
ResPackage[] pkgs = decoder.readTable();
|
||||||
return new ARSCData(
|
return new ARSCData(
|
||||||
pkgs,
|
pkgs,
|
||||||
@ -56,7 +57,7 @@ public class ARSCDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ARSCDecoder(InputStream arscStream, ResTable resTable,
|
private ARSCDecoder(InputStream arscStream, ResTable resTable,
|
||||||
boolean storeFlagsOffsets) {
|
boolean storeFlagsOffsets, boolean keepBroken) {
|
||||||
if (storeFlagsOffsets) {
|
if (storeFlagsOffsets) {
|
||||||
arscStream = mCountIn = new CountingInputStream(arscStream);
|
arscStream = mCountIn = new CountingInputStream(arscStream);
|
||||||
mFlagsOffsets = new ArrayList<FlagsOffset>();
|
mFlagsOffsets = new ArrayList<FlagsOffset>();
|
||||||
@ -66,6 +67,7 @@ public class ARSCDecoder {
|
|||||||
}
|
}
|
||||||
mIn = new ExtDataInput(new LEDataInputStream(arscStream));
|
mIn = new ExtDataInput(new LEDataInputStream(arscStream));
|
||||||
mResTable = resTable;
|
mResTable = resTable;
|
||||||
|
mKeepBroken = keepBroken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResPackage[] readTable() throws IOException, AndrolibException {
|
private ResPackage[] readTable() throws IOException, AndrolibException {
|
||||||
@ -142,11 +144,20 @@ public class ARSCDecoder {
|
|||||||
ResConfigFlags flags = readConfigFlags();
|
ResConfigFlags flags = readConfigFlags();
|
||||||
int[] entryOffsets = mIn.readIntArray(entryCount);
|
int[] entryOffsets = mIn.readIntArray(entryCount);
|
||||||
|
|
||||||
ResConfig config;
|
|
||||||
if (flags.isInvalid) {
|
if (flags.isInvalid) {
|
||||||
config = null;
|
String resName = mType.getName() + flags.getQualifiers();
|
||||||
|
if (mKeepBroken) {
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
"Invalid config flags detected. Dropping resources: " + mType.getName() + flags.getQualifiers());
|
"Invalid config flags detected: " + resName);
|
||||||
|
} else {
|
||||||
|
LOGGER.warning(
|
||||||
|
"Invalid config flags detected. Dropping resources: " + resName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResConfig config;
|
||||||
|
if (flags.isInvalid && ! mKeepBroken) {
|
||||||
|
config = null;
|
||||||
} else if (mPkg.hasConfig(flags)) {
|
} else if (mPkg.hasConfig(flags)) {
|
||||||
config = mPkg.getConfig(flags);
|
config = mPkg.getConfig(flags);
|
||||||
} else {
|
} else {
|
||||||
@ -328,6 +339,7 @@ public class ARSCDecoder {
|
|||||||
private final ResTable mResTable;
|
private final ResTable mResTable;
|
||||||
private final CountingInputStream mCountIn;
|
private final CountingInputStream mCountIn;
|
||||||
private final List<FlagsOffset> mFlagsOffsets;
|
private final List<FlagsOffset> mFlagsOffsets;
|
||||||
|
private final boolean mKeepBroken;
|
||||||
|
|
||||||
private Header mHeader;
|
private Header mHeader;
|
||||||
private StringBlock mTableStrings;
|
private StringBlock mTableStrings;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user