mirror of
https://github.com/revanced/Apktool.git
synced 2025-02-11 19:36:47 +01:00
Support explicit operation for when to load full resource table (#3217)
This commit is contained in:
parent
20afa7d2e5
commit
7a4a20ba34
@ -22,6 +22,7 @@ import brut.androlib.exceptions.OutDirExistsException;
|
||||
import brut.androlib.apk.ApkInfo;
|
||||
import brut.androlib.res.ResourcesDecoder;
|
||||
import brut.androlib.res.data.*;
|
||||
import brut.androlib.res.xml.ResXmlPatcher;
|
||||
import brut.androlib.src.SmaliDecoder;
|
||||
import brut.directory.Directory;
|
||||
import brut.directory.ExtFile;
|
||||
@ -50,6 +51,10 @@ public class ApkDecoder {
|
||||
private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] {
|
||||
"classes.dex", "AndroidManifest.xml", "resources.arsc", "res", "r", "R",
|
||||
"lib", "libs", "assets", "META-INF", "kotlin" };
|
||||
private final static String[] APK_RESOURCES_FILENAMES = new String[] {
|
||||
"resources.arsc", "res", "r", "R" };
|
||||
private final static String[] APK_MANIFEST_FILENAMES = new String[] {
|
||||
"AndroidManifest.xml" };
|
||||
private final static Pattern NO_COMPRESS_PATTERN = Pattern.compile("(" +
|
||||
"jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|imy|xmf|mp4|" +
|
||||
"m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv)$");
|
||||
@ -92,8 +97,27 @@ public class ApkDecoder {
|
||||
LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName());
|
||||
|
||||
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(mConfig, mApkFile);
|
||||
resourcesDecoder.decodeManifest(outDir);
|
||||
resourcesDecoder.decodeResources(outDir);
|
||||
if (hasResources()) {
|
||||
switch (mConfig.decodeResources) {
|
||||
case Config.DECODE_RESOURCES_NONE:
|
||||
copyResourcesRaw(outDir);
|
||||
break;
|
||||
case Config.DECODE_RESOURCES_FULL:
|
||||
resourcesDecoder.decodeResources(outDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasManifest()) {
|
||||
if (mConfig.decodeResources == Config.DECODE_RESOURCES_FULL ||
|
||||
mConfig.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
|
||||
resourcesDecoder.decodeManifest(outDir);
|
||||
}
|
||||
else {
|
||||
copyManifestRaw(outDir);
|
||||
}
|
||||
}
|
||||
resourcesDecoder.updateApkInfo(outDir);
|
||||
|
||||
if (hasSources()) {
|
||||
switch (mConfig.decodeSources) {
|
||||
@ -135,7 +159,7 @@ public class ApkDecoder {
|
||||
|
||||
// In case we have no resources. We should store the minSdk we pulled from the source opcode api level
|
||||
ApkInfo apkInfo = resourcesDecoder.getApkInfo();
|
||||
if (! resourcesDecoder.hasResources() && mMinSdkVersion > 0) {
|
||||
if (!hasResources() && mMinSdkVersion > 0) {
|
||||
apkInfo.setSdkInfoField("minSdkVersion", Integer.toString(mMinSdkVersion));
|
||||
}
|
||||
|
||||
@ -154,6 +178,22 @@ public class ApkDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasManifest() throws AndrolibException {
|
||||
try {
|
||||
return mApkFile.getDirectory().containsFile("AndroidManifest.xml");
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasResources() throws AndrolibException {
|
||||
try {
|
||||
return mApkFile.getDirectory().containsFile("resources.arsc");
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasSources() throws AndrolibException {
|
||||
try {
|
||||
return mApkFile.getDirectory().containsFile("classes.dex");
|
||||
@ -187,6 +227,26 @@ public class ApkDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private void copyManifestRaw(File outDir)
|
||||
throws AndrolibException {
|
||||
try {
|
||||
LOGGER.info("Copying raw manifest...");
|
||||
mApkFile.getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES);
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyResourcesRaw(File outDir)
|
||||
throws AndrolibException {
|
||||
try {
|
||||
LOGGER.info("Copying raw resources...");
|
||||
mApkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void copySourcesRaw(File outDir, String filename)
|
||||
throws AndrolibException {
|
||||
try {
|
||||
|
@ -29,7 +29,6 @@ import brut.directory.Directory;
|
||||
import brut.directory.DirectoryException;
|
||||
import brut.directory.ExtFile;
|
||||
import brut.directory.FileDirectory;
|
||||
import brut.util.Duo;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.File;
|
||||
@ -48,10 +47,6 @@ public class ResourcesDecoder {
|
||||
private final ApkInfo mApkInfo;
|
||||
private final Map<String, String> mResFileMapping = new HashMap<>();
|
||||
|
||||
private final static String[] APK_RESOURCES_FILENAMES = new String[] {
|
||||
"resources.arsc", "res", "r", "R" };
|
||||
private final static String[] APK_MANIFEST_FILENAMES = new String[] {
|
||||
"AndroidManifest.xml" };
|
||||
private final static String[] IGNORED_PACKAGES = new String[] {
|
||||
"android", "com.htc", "com.lge", "com.lge.internal", "yi", "flyme", "air.com.adobe.appentry",
|
||||
"FFFFFFFFFFFFFFFFFFFFFF" };
|
||||
@ -85,9 +80,6 @@ public class ResourcesDecoder {
|
||||
throw new AndrolibException(
|
||||
"Apk doesn't contain either AndroidManifest.xml file or resources.arsc file");
|
||||
}
|
||||
if (hasResources() && !mResTable.isMainPkgLoaded()) {
|
||||
mResTable.loadMainPkg(mApkFile);
|
||||
}
|
||||
return mResTable;
|
||||
}
|
||||
|
||||
@ -101,38 +93,31 @@ public class ResourcesDecoder {
|
||||
|
||||
public void decodeManifest(File outDir) throws AndrolibException {
|
||||
if (hasManifest()) {
|
||||
if (mConfig.decodeResources == Config.DECODE_RESOURCES_FULL ||
|
||||
mConfig.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
|
||||
decodeManifest(getResTable(), mApkFile, outDir);
|
||||
if (hasResources()) {
|
||||
if (!mConfig.analysisMode) {
|
||||
// Remove versionName / versionCode (aapt API 16)
|
||||
//
|
||||
// check for a mismatch between resources.arsc package and the package listed in AndroidManifest
|
||||
// also remove the android::versionCode / versionName from manifest for rebuild
|
||||
// this is a required change to prevent aapt warning about conflicting versions
|
||||
// it will be passed as a parameter to aapt like "--min-sdk-version" via apktool.yml
|
||||
adjustPackageManifest(getResTable(), outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml");
|
||||
decodeManifest(getResTable(), mApkFile, outDir);
|
||||
if (hasResources()) {
|
||||
if (!mConfig.analysisMode) {
|
||||
// Remove versionName / versionCode (aapt API 16)
|
||||
//
|
||||
// check for a mismatch between resources.arsc package and the package listed in AndroidManifest
|
||||
// also remove the android::versionCode / versionName from manifest for rebuild
|
||||
// this is a required change to prevent aapt warning about conflicting versions
|
||||
// it will be passed as a parameter to aapt like "--min-sdk-version" via apktool.yml
|
||||
adjustPackageManifest(getResTable(), outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml");
|
||||
|
||||
ResXmlPatcher.removeManifestVersions(new File(
|
||||
outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"));
|
||||
ResXmlPatcher.removeManifestVersions(new File(
|
||||
outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"));
|
||||
|
||||
// update apk info
|
||||
mApkInfo.packageInfo.forcedPackageId = String.valueOf(mResTable.getPackageId());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
LOGGER.info("Copying raw manifest...");
|
||||
mApkFile.getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES);
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
// update apk info
|
||||
mApkInfo.packageInfo.forcedPackageId = String.valueOf(mResTable.getPackageId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateApkInfo(File outDir) throws AndrolibException {
|
||||
mResTable.initApkInfo(mApkInfo, outDir);
|
||||
}
|
||||
|
||||
private void decodeManifest(ResTable resTable, ExtFile apkFile, File outDir)
|
||||
throws AndrolibException {
|
||||
|
||||
@ -191,22 +176,14 @@ public class ResourcesDecoder {
|
||||
return serial;
|
||||
}
|
||||
|
||||
public void loadMainPkg() throws AndrolibException {
|
||||
mResTable.loadMainPkg(mApkFile);
|
||||
}
|
||||
|
||||
public ResTable decodeResources(File outDir) throws AndrolibException {
|
||||
if (hasResources()) {
|
||||
switch (mConfig.decodeResources) {
|
||||
case Config.DECODE_RESOURCES_NONE:
|
||||
try {
|
||||
LOGGER.info("Copying raw resources...");
|
||||
mApkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
break;
|
||||
case Config.DECODE_RESOURCES_FULL:
|
||||
decodeResources(getResTable(), mApkFile, outDir);
|
||||
break;
|
||||
}
|
||||
mResTable.initApkInfo(mApkInfo, outDir);
|
||||
loadMainPkg();
|
||||
decodeResources(getResTable(), mApkFile, outDir);
|
||||
}
|
||||
return mResTable;
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ public class NonStandardPkgIdTest extends BaseTest {
|
||||
Config.getDefaultConfig(), new ExtFile(testApk));
|
||||
|
||||
sTestNewDir.mkdirs();
|
||||
resourcesDecoder.decodeManifest(sTestNewDir);
|
||||
mResTable = resourcesDecoder.decodeResources(sTestNewDir);
|
||||
resourcesDecoder.decodeManifest(sTestNewDir);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
@ -57,6 +57,7 @@ public class DecodeArrayTest extends BaseTest {
|
||||
Config.getDefaultConfig(),
|
||||
new ExtFile(sTmpDir + File.separator + apk));
|
||||
|
||||
resourcesDecoder.loadMainPkg();
|
||||
ResTable resTable = resourcesDecoder.getResTable();
|
||||
ResValue value = resTable.getResSpec(0x7f020001).getDefaultResource().getValue();
|
||||
|
||||
@ -70,6 +71,7 @@ public class DecodeArrayTest extends BaseTest {
|
||||
Config.getDefaultConfig(),
|
||||
new ExtFile(sTmpDir + File.separator + apk));
|
||||
|
||||
resourcesDecoder.loadMainPkg();
|
||||
ResTable resTable = resourcesDecoder.getResTable();
|
||||
ResValue value = resTable.getResSpec(0x7f020000).getDefaultResource().getValue();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user