mirror of
https://github.com/revanced/Apktool.git
synced 2025-05-01 14:44:26 +02:00
Merge pull request #1020 from agrieve/stored-entries
Adds doNotCompress list to apktool.yml
This commit is contained in:
commit
5c6f325c06
@ -32,6 +32,7 @@ import brut.util.OS;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipFile;
|
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) {
|
private boolean isAPKFileNames(String file) {
|
||||||
for (String apkFile : APK_STANDARD_ALL_FILENAMES) {
|
for (String apkFile : APK_STANDARD_ALL_FILENAMES) {
|
||||||
if (apkFile.equals(file) || file.startsWith(apkFile + "/")) {
|
if (apkFile.equals(file) || file.startsWith(apkFile + "/")) {
|
||||||
@ -171,13 +188,8 @@ public class Androlib {
|
|||||||
throws AndrolibException {
|
throws AndrolibException {
|
||||||
LOGGER.info("Copying unknown files...");
|
LOGGER.info("Copying unknown files...");
|
||||||
File unknownOut = new File(outDir, UNK_DIRNAME);
|
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 {
|
try {
|
||||||
Directory unk = apkFile.getDirectory();
|
Directory unk = apkFile.getDirectory();
|
||||||
ZipFile apkZipFile = new ZipFile(apkFile.getAbsolutePath());
|
|
||||||
|
|
||||||
// loop all items in container recursively, ignoring any that are pre-defined by aapt
|
// loop all items in container recursively, ignoring any that are pre-defined by aapt
|
||||||
Set<String> files = unk.getFiles(true);
|
Set<String> files = unk.getFiles(true);
|
||||||
@ -186,19 +198,12 @@ public class Androlib {
|
|||||||
|
|
||||||
// copy file out of archive into special "unknown" folder
|
// copy file out of archive into special "unknown" folder
|
||||||
unk.copyToDir(unknownOut, file);
|
unk.copyToDir(unknownOut, file);
|
||||||
try {
|
// lets record the name of the file, and its compression type
|
||||||
invZipFile = apkZipFile.getEntry(file);
|
// so that we may re-include it the same way
|
||||||
|
mResUnknownFiles.addUnknownFileInfo(file, String.valueOf(unk.getCompressionLevel(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) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apkZipFile.close();
|
} catch (DirectoryException ex) {
|
||||||
} catch (DirectoryException | IOException ex) {
|
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,6 +271,7 @@ public class Androlib {
|
|||||||
apkOptions.resourcesAreCompressed = meta.get("compressionType") == null
|
apkOptions.resourcesAreCompressed = meta.get("compressionType") == null
|
||||||
? false
|
? false
|
||||||
: Boolean.valueOf(meta.get("compressionType").toString());
|
: Boolean.valueOf(meta.get("compressionType").toString());
|
||||||
|
apkOptions.doNotCompress = (Collection<String>) meta.get("doNotCompress");
|
||||||
|
|
||||||
mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo"));
|
mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo"));
|
||||||
mAndRes.setPackageId((Map<String, String>) meta.get("packageInfo"));
|
mAndRes.setPackageId((Map<String, String>) meta.get("packageInfo"));
|
||||||
@ -739,4 +745,9 @@ public class Androlib {
|
|||||||
"AndroidManifest.xml" };
|
"AndroidManifest.xml" };
|
||||||
private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] {
|
private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] {
|
||||||
"classes.dex", "AndroidManifest.xml", "resources.arsc", "res", "lib", "libs", "assets", "META-INF" };
|
"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.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
@ -89,8 +87,6 @@ public class ApkDecoder {
|
|||||||
LOGGER.info("Using Apktool " + Androlib.getVersion() + " on " + mApkFile.getName());
|
LOGGER.info("Using Apktool " + Androlib.getVersion() + " on " + mApkFile.getName());
|
||||||
|
|
||||||
if (hasResources()) {
|
if (hasResources()) {
|
||||||
setCompressionMode();
|
|
||||||
|
|
||||||
switch (mDecodeResources) {
|
switch (mDecodeResources) {
|
||||||
case DECODE_RESOURCES_NONE:
|
case DECODE_RESOURCES_NONE:
|
||||||
mAndrolib.decodeResourcesRaw(mApkFile, outDir);
|
mAndrolib.decodeResourcesRaw(mApkFile, outDir);
|
||||||
@ -159,6 +155,8 @@ public class ApkDecoder {
|
|||||||
|
|
||||||
mAndrolib.decodeRawFiles(mApkFile, outDir);
|
mAndrolib.decodeRawFiles(mApkFile, outDir);
|
||||||
mAndrolib.decodeUnknownFiles(mApkFile, outDir, mResTable);
|
mAndrolib.decodeUnknownFiles(mApkFile, outDir, mResTable);
|
||||||
|
mUncompressedFiles = new ArrayList<String>();
|
||||||
|
mAndrolib.recordUncompressedFiles(mApkFile, mUncompressedFiles);
|
||||||
mAndrolib.writeOriginalFiles(mApkFile, outDir);
|
mAndrolib.writeOriginalFiles(mApkFile, outDir);
|
||||||
writeMetaFile();
|
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 {
|
public void setTargetSdkVersion() throws AndrolibException, IOException {
|
||||||
if (mResTable == null) {
|
if (mResTable == null) {
|
||||||
mResTable = mAndrolib.getResTable(mApkFile);
|
mResTable = mAndrolib.getResTable(mApkFile);
|
||||||
@ -320,10 +306,10 @@ public class ApkDecoder {
|
|||||||
putSdkInfo(meta);
|
putSdkInfo(meta);
|
||||||
putPackageInfo(meta);
|
putPackageInfo(meta);
|
||||||
putVersionInfo(meta);
|
putVersionInfo(meta);
|
||||||
putCompressionInfo(meta);
|
|
||||||
putSharedLibraryInfo(meta);
|
putSharedLibraryInfo(meta);
|
||||||
}
|
}
|
||||||
putUnknownInfo(meta);
|
putUnknownInfo(meta);
|
||||||
|
putFileCompressionInfo(meta);
|
||||||
|
|
||||||
mAndrolib.writeMetaFile(mOutDir, meta);
|
mAndrolib.writeMetaFile(mOutDir, meta);
|
||||||
}
|
}
|
||||||
@ -391,18 +377,16 @@ public class ApkDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putCompressionInfo(Map<String, Object> meta) throws AndrolibException {
|
private void putFileCompressionInfo(Map<String, Object> meta) throws AndrolibException {
|
||||||
meta.put("compressionType", getCompressionType());
|
if (!mUncompressedFiles.isEmpty()) {
|
||||||
|
meta.put("doNotCompress", mUncompressedFiles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putSharedLibraryInfo(Map<String, Object> meta) throws AndrolibException {
|
private void putSharedLibraryInfo(Map<String, Object> meta) throws AndrolibException {
|
||||||
meta.put("sharedLibrary", mResTable.getSharedLibrary());
|
meta.put("sharedLibrary", mResTable.getSharedLibrary());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean getCompressionType() {
|
|
||||||
return mCompressResources;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Androlib mAndrolib;
|
private final Androlib mAndrolib;
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(Androlib.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(Androlib.class.getName());
|
||||||
@ -417,7 +401,7 @@ public class ApkDecoder {
|
|||||||
private boolean mForceDelete = false;
|
private boolean mForceDelete = false;
|
||||||
private boolean mKeepBrokenResources = false;
|
private boolean mKeepBrokenResources = false;
|
||||||
private boolean mBakDeb = true;
|
private boolean mBakDeb = true;
|
||||||
private boolean mCompressResources = false;
|
private Collection<String> mUncompressedFiles;
|
||||||
private boolean mAnalysisMode = false;
|
private boolean mAnalysisMode = false;
|
||||||
private int mApi = 15;
|
private int mApi = 15;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package brut.androlib;
|
package brut.androlib;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
public class ApkOptions {
|
public class ApkOptions {
|
||||||
public boolean forceBuildAll = false;
|
public boolean forceBuildAll = false;
|
||||||
public boolean debugMode = false;
|
public boolean debugMode = false;
|
||||||
@ -23,6 +25,7 @@ public class ApkOptions {
|
|||||||
public boolean updateFiles = false;
|
public boolean updateFiles = false;
|
||||||
public boolean isFramework = false;
|
public boolean isFramework = false;
|
||||||
public boolean resourcesAreCompressed = false;
|
public boolean resourcesAreCompressed = false;
|
||||||
|
public Collection<String> doNotCompress;
|
||||||
|
|
||||||
public String frameworkFolderLocation = null;
|
public String frameworkFolderLocation = null;
|
||||||
public String frameworkTag = null;
|
public String frameworkTag = null;
|
||||||
|
@ -383,7 +383,13 @@ final public class AndrolibResources {
|
|||||||
cmd.add("-x");
|
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("-0");
|
||||||
cmd.add("arsc");
|
cmd.add("arsc");
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
public abstract class AbstractDirectory implements Directory {
|
public abstract class AbstractDirectory implements Directory {
|
||||||
protected Set<String> mFiles;
|
protected Set<String> mFiles;
|
||||||
|
protected Set<String> mFilesRecursive;
|
||||||
protected Map<String, AbstractDirectory> mDirs;
|
protected Map<String, AbstractDirectory> mDirs;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,14 +42,15 @@ public abstract class AbstractDirectory implements Directory {
|
|||||||
if (!recursive) {
|
if (!recursive) {
|
||||||
return mFiles;
|
return mFiles;
|
||||||
}
|
}
|
||||||
|
if (mFilesRecursive == null) {
|
||||||
Set<String> files = new LinkedHashSet<String>(mFiles);
|
mFilesRecursive = new LinkedHashSet<String>(mFiles);
|
||||||
for (Map.Entry<String, ? extends Directory> dir : getAbstractDirs().entrySet()) {
|
for (Map.Entry<String, ? extends Directory> dir : getAbstractDirs().entrySet()) {
|
||||||
for (String path : dir.getValue().getFiles(true)) {
|
for (String path : dir.getValue().getFiles(true)) {
|
||||||
files.add(dir.getKey() + separator + path);
|
mFilesRecursive.add(dir.getKey() + separator + path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return files;
|
return mFilesRecursive;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -205,6 +207,11 @@ public abstract class AbstractDirectory implements Directory {
|
|||||||
DirUtil.copyToDir(this, out, fileName);
|
DirUtil.copyToDir(this, out, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCompressionLevel(String fileName)
|
||||||
|
throws DirectoryException {
|
||||||
|
return -1; // Unknown
|
||||||
|
}
|
||||||
|
|
||||||
protected Map<String, AbstractDirectory> getAbstractDirs() {
|
protected Map<String, AbstractDirectory> getAbstractDirs() {
|
||||||
return getAbstractDirs(false);
|
return getAbstractDirs(false);
|
||||||
}
|
}
|
||||||
|
@ -47,5 +47,8 @@ public interface Directory {
|
|||||||
public void copyToDir(File out, String fileName)
|
public void copyToDir(File out, String fileName)
|
||||||
throws DirectoryException;
|
throws DirectoryException;
|
||||||
|
|
||||||
|
public int getCompressionLevel(String fileName)
|
||||||
|
throws DirectoryException;
|
||||||
|
|
||||||
public final char separator = '/';
|
public final char separator = '/';
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,16 @@ public class ZipRODirectory extends AbstractDirectory {
|
|||||||
throw new UnsupportedOperationException();
|
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() {
|
private void loadAll() {
|
||||||
mFiles = new LinkedHashSet<String>();
|
mFiles = new LinkedHashSet<String>();
|
||||||
mDirs = new LinkedHashMap<String, AbstractDirectory>();
|
mDirs = new LinkedHashMap<String, AbstractDirectory>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user