mirror of
https://github.com/revanced/Apktool.git
synced 2024-12-04 18:12:54 +01:00
Adds doNotCompress list to apktool.yml
This is the list of files (resources, assets, etc) that are stored in the .apk uncompressed. For apps that use AssetFileDescriptor.openFd(), the adding compression will break the call. Maintains support for the resourcesAreCompressed key, but no longer records it when decompiling (it instead records resources.arsc in the doNotCompress list).
This commit is contained in:
parent
2033e305af
commit
392420c909
@ -32,6 +32,7 @@ import brut.util.OS;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
@ -158,6 +159,22 @@ public class Androlib {
|
||||
}
|
||||
}
|
||||
|
||||
public void recordUncompressedFiles(ExtFile apkFile, Collection<String> uncompressedFiles) throws AndrolibException {
|
||||
try {
|
||||
Directory unk = apkFile.getDirectory();
|
||||
Set<String> files = unk.getFiles(true);
|
||||
for (String file : files) {
|
||||
if (isAPKFileNames(file) && !NO_COMPRESS_PATTERN.matcher(file).find()) {
|
||||
if (unk.getCompressionLevel(file) == 0) {
|
||||
uncompressedFiles.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAPKFileNames(String file) {
|
||||
for (String apkFile : APK_STANDARD_ALL_FILENAMES) {
|
||||
if (apkFile.equals(file) || file.startsWith(apkFile + "/")) {
|
||||
@ -171,13 +188,8 @@ public class Androlib {
|
||||
throws AndrolibException {
|
||||
LOGGER.info("Copying unknown files...");
|
||||
File unknownOut = new File(outDir, UNK_DIRNAME);
|
||||
ZipEntry invZipFile;
|
||||
|
||||
// have to use container of ZipFile to help identify compression type
|
||||
// with regular looping of apkFile for easy copy
|
||||
try {
|
||||
Directory unk = apkFile.getDirectory();
|
||||
ZipFile apkZipFile = new ZipFile(apkFile.getAbsolutePath());
|
||||
|
||||
// loop all items in container recursively, ignoring any that are pre-defined by aapt
|
||||
Set<String> files = unk.getFiles(true);
|
||||
@ -186,19 +198,12 @@ public class Androlib {
|
||||
|
||||
// copy file out of archive into special "unknown" folder
|
||||
unk.copyToDir(unknownOut, file);
|
||||
try {
|
||||
invZipFile = apkZipFile.getEntry(file);
|
||||
|
||||
// lets record the name of the file, and its compression type
|
||||
// so that we may re-include it the same way
|
||||
if (invZipFile != null) {
|
||||
mResUnknownFiles.addUnknownFileInfo(invZipFile.getName(), String.valueOf(invZipFile.getMethod()));
|
||||
}
|
||||
} catch (NullPointerException ignored) { }
|
||||
// lets record the name of the file, and its compression type
|
||||
// so that we may re-include it the same way
|
||||
mResUnknownFiles.addUnknownFileInfo(file, String.valueOf(unk.getCompressionLevel(file)));
|
||||
}
|
||||
}
|
||||
apkZipFile.close();
|
||||
} catch (DirectoryException | IOException ex) {
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
}
|
||||
}
|
||||
@ -266,6 +271,7 @@ public class Androlib {
|
||||
apkOptions.resourcesAreCompressed = meta.get("compressionType") == null
|
||||
? false
|
||||
: Boolean.valueOf(meta.get("compressionType").toString());
|
||||
apkOptions.doNotCompress = (Collection<String>) meta.get("doNotCompress");
|
||||
|
||||
mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo"));
|
||||
mAndRes.setPackageId((Map<String, String>) meta.get("packageInfo"));
|
||||
@ -739,4 +745,9 @@ public class Androlib {
|
||||
"AndroidManifest.xml" };
|
||||
private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] {
|
||||
"classes.dex", "AndroidManifest.xml", "resources.arsc", "res", "lib", "libs", "assets", "META-INF" };
|
||||
// Taken from AOSP's frameworks/base/tools/aapt/Package.cpp
|
||||
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)$");
|
||||
|
||||
}
|
||||
|
@ -31,8 +31,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
@ -89,8 +87,6 @@ public class ApkDecoder {
|
||||
LOGGER.info("Using Apktool " + Androlib.getVersion() + " on " + mApkFile.getName());
|
||||
|
||||
if (hasResources()) {
|
||||
setCompressionMode();
|
||||
|
||||
switch (mDecodeResources) {
|
||||
case DECODE_RESOURCES_NONE:
|
||||
mAndrolib.decodeResourcesRaw(mApkFile, outDir);
|
||||
@ -159,6 +155,8 @@ public class ApkDecoder {
|
||||
|
||||
mAndrolib.decodeRawFiles(mApkFile, outDir);
|
||||
mAndrolib.decodeUnknownFiles(mApkFile, outDir, mResTable);
|
||||
mUncompressedFiles = new ArrayList<String>();
|
||||
mAndrolib.recordUncompressedFiles(mApkFile, mUncompressedFiles);
|
||||
mAndrolib.writeOriginalFiles(mApkFile, outDir);
|
||||
writeMetaFile();
|
||||
}
|
||||
@ -193,18 +191,6 @@ public class ApkDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
public void setCompressionMode() throws AndrolibException, IOException {
|
||||
// read the resources.arsc checking for STORED vs DEFLATE
|
||||
// this will determine whether we compress on rebuild or not.
|
||||
ZipFile zf = new ZipFile(mApkFile.getAbsolutePath());
|
||||
ZipEntry ze = zf.getEntry("resources.arsc");
|
||||
if (ze != null) {
|
||||
int compression = ze.getMethod();
|
||||
mCompressResources = (compression == ZipEntry.DEFLATED);
|
||||
}
|
||||
zf.close();
|
||||
}
|
||||
|
||||
public void setTargetSdkVersion() throws AndrolibException, IOException {
|
||||
if (mResTable == null) {
|
||||
mResTable = mAndrolib.getResTable(mApkFile);
|
||||
@ -320,10 +306,10 @@ public class ApkDecoder {
|
||||
putSdkInfo(meta);
|
||||
putPackageInfo(meta);
|
||||
putVersionInfo(meta);
|
||||
putCompressionInfo(meta);
|
||||
putSharedLibraryInfo(meta);
|
||||
}
|
||||
putUnknownInfo(meta);
|
||||
putFileCompressionInfo(meta);
|
||||
|
||||
mAndrolib.writeMetaFile(mOutDir, meta);
|
||||
}
|
||||
@ -391,18 +377,16 @@ public class ApkDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private void putCompressionInfo(Map<String, Object> meta) throws AndrolibException {
|
||||
meta.put("compressionType", getCompressionType());
|
||||
private void putFileCompressionInfo(Map<String, Object> meta) throws AndrolibException {
|
||||
if (!mUncompressedFiles.isEmpty()) {
|
||||
meta.put("doNotCompress", mUncompressedFiles);
|
||||
}
|
||||
}
|
||||
|
||||
private void putSharedLibraryInfo(Map<String, Object> meta) throws AndrolibException {
|
||||
meta.put("sharedLibrary", mResTable.getSharedLibrary());
|
||||
}
|
||||
|
||||
private boolean getCompressionType() {
|
||||
return mCompressResources;
|
||||
}
|
||||
|
||||
private final Androlib mAndrolib;
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(Androlib.class.getName());
|
||||
@ -417,7 +401,7 @@ public class ApkDecoder {
|
||||
private boolean mForceDelete = false;
|
||||
private boolean mKeepBrokenResources = false;
|
||||
private boolean mBakDeb = true;
|
||||
private boolean mCompressResources = false;
|
||||
private Collection<String> mUncompressedFiles;
|
||||
private boolean mAnalysisMode = false;
|
||||
private int mApi = 15;
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package brut.androlib;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ApkOptions {
|
||||
public boolean forceBuildAll = false;
|
||||
public boolean debugMode = false;
|
||||
@ -23,6 +25,7 @@ public class ApkOptions {
|
||||
public boolean updateFiles = false;
|
||||
public boolean isFramework = false;
|
||||
public boolean resourcesAreCompressed = false;
|
||||
public Collection<String> doNotCompress;
|
||||
|
||||
public String frameworkFolderLocation = null;
|
||||
public String frameworkTag = null;
|
||||
|
@ -383,7 +383,13 @@ final public class AndrolibResources {
|
||||
cmd.add("-x");
|
||||
}
|
||||
|
||||
if (! apkOptions.resourcesAreCompressed) {
|
||||
if (apkOptions.doNotCompress != null) {
|
||||
for (String file : apkOptions.doNotCompress) {
|
||||
cmd.add("-0");
|
||||
cmd.add(file);
|
||||
}
|
||||
}
|
||||
if (!apkOptions.resourcesAreCompressed) {
|
||||
cmd.add("-0");
|
||||
cmd.add("arsc");
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import java.util.Set;
|
||||
|
||||
public abstract class AbstractDirectory implements Directory {
|
||||
protected Set<String> mFiles;
|
||||
protected Set<String> mFilesRecursive;
|
||||
protected Map<String, AbstractDirectory> mDirs;
|
||||
|
||||
@Override
|
||||
@ -41,14 +42,15 @@ public abstract class AbstractDirectory implements Directory {
|
||||
if (!recursive) {
|
||||
return mFiles;
|
||||
}
|
||||
|
||||
Set<String> files = new LinkedHashSet<String>(mFiles);
|
||||
for (Map.Entry<String, ? extends Directory> dir : getAbstractDirs().entrySet()) {
|
||||
for (String path : dir.getValue().getFiles(true)) {
|
||||
files.add(dir.getKey() + separator + path);
|
||||
if (mFilesRecursive == null) {
|
||||
mFilesRecursive = new LinkedHashSet<String>(mFiles);
|
||||
for (Map.Entry<String, ? extends Directory> dir : getAbstractDirs().entrySet()) {
|
||||
for (String path : dir.getValue().getFiles(true)) {
|
||||
mFilesRecursive.add(dir.getKey() + separator + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
return files;
|
||||
return mFilesRecursive;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -205,6 +207,11 @@ public abstract class AbstractDirectory implements Directory {
|
||||
DirUtil.copyToDir(this, out, fileName);
|
||||
}
|
||||
|
||||
public int getCompressionLevel(String fileName)
|
||||
throws DirectoryException {
|
||||
return -1; // Unknown
|
||||
}
|
||||
|
||||
protected Map<String, AbstractDirectory> getAbstractDirs() {
|
||||
return getAbstractDirs(false);
|
||||
}
|
||||
|
@ -47,5 +47,8 @@ public interface Directory {
|
||||
public void copyToDir(File out, String fileName)
|
||||
throws DirectoryException;
|
||||
|
||||
public int getCompressionLevel(String fileName)
|
||||
throws DirectoryException;
|
||||
|
||||
public final char separator = '/';
|
||||
}
|
||||
|
@ -100,6 +100,16 @@ public class ZipRODirectory extends AbstractDirectory {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompressionLevel(String fileName)
|
||||
throws DirectoryException {
|
||||
ZipEntry entry = mZipFile.getEntry(fileName);
|
||||
if (entry == null) {
|
||||
throw new PathNotExist("Entry not found: " + fileName);
|
||||
}
|
||||
return entry.getMethod();
|
||||
}
|
||||
|
||||
private void loadAll() {
|
||||
mFiles = new LinkedHashSet<String>();
|
||||
mDirs = new LinkedHashMap<String, AbstractDirectory>();
|
||||
|
Loading…
Reference in New Issue
Block a user