mirror of
https://github.com/revanced/Apktool.git
synced 2024-11-06 12:47:03 +01:00
ApkDecoder use apkFile and unknownFiles from ApkInfo (#3242)
This commit is contained in:
parent
e52c3b0f56
commit
9d7d58016e
@ -21,8 +21,6 @@ import brut.androlib.exceptions.InFileNotFoundException;
|
|||||||
import brut.androlib.exceptions.OutDirExistsException;
|
import brut.androlib.exceptions.OutDirExistsException;
|
||||||
import brut.androlib.apk.ApkInfo;
|
import brut.androlib.apk.ApkInfo;
|
||||||
import brut.androlib.res.ResourcesDecoder;
|
import brut.androlib.res.ResourcesDecoder;
|
||||||
import brut.androlib.res.data.*;
|
|
||||||
import brut.androlib.res.xml.ResXmlPatcher;
|
|
||||||
import brut.androlib.src.SmaliDecoder;
|
import brut.androlib.src.SmaliDecoder;
|
||||||
import brut.directory.Directory;
|
import brut.directory.Directory;
|
||||||
import brut.directory.ExtFile;
|
import brut.directory.ExtFile;
|
||||||
@ -41,9 +39,7 @@ public class ApkDecoder {
|
|||||||
private final static Logger LOGGER = Logger.getLogger(ApkDecoder.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(ApkDecoder.class.getName());
|
||||||
|
|
||||||
private final Config mConfig;
|
private final Config mConfig;
|
||||||
private final ExtFile mApkFile;
|
private final ApkInfo mApkInfo;
|
||||||
protected final ResUnknownFiles mResUnknownFiles;
|
|
||||||
private ApkInfo mApkInfo;
|
|
||||||
private int mMinSdkVersion = 0;
|
private int mMinSdkVersion = 0;
|
||||||
|
|
||||||
private final static String SMALI_DIRNAME = "smali";
|
private final static String SMALI_DIRNAME = "smali";
|
||||||
@ -73,17 +69,17 @@ public class ApkDecoder {
|
|||||||
|
|
||||||
public ApkDecoder(Config config, ExtFile apkFile) {
|
public ApkDecoder(Config config, ExtFile apkFile) {
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
mApkFile = apkFile;
|
mApkInfo = new ApkInfo(apkFile);
|
||||||
mResUnknownFiles = new ResUnknownFiles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApkInfo decode(File outDir) throws AndrolibException, IOException, DirectoryException {
|
public ApkInfo decode(File outDir) throws AndrolibException, IOException, DirectoryException {
|
||||||
|
ExtFile apkFile = mApkInfo.getApkFile();
|
||||||
try {
|
try {
|
||||||
if (!mConfig.forceDelete && outDir.exists()) {
|
if (!mConfig.forceDelete && outDir.exists()) {
|
||||||
throw new OutDirExistsException();
|
throw new OutDirExistsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mApkFile.isFile() || !mApkFile.canRead()) {
|
if (!apkFile.isFile() || !apkFile.canRead()) {
|
||||||
throw new InFileNotFoundException();
|
throw new InFileNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,11 +90,9 @@ public class ApkDecoder {
|
|||||||
}
|
}
|
||||||
outDir.mkdirs();
|
outDir.mkdirs();
|
||||||
|
|
||||||
LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName());
|
LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkInfo.apkFileName);
|
||||||
|
|
||||||
mApkInfo = new ApkInfo(mApkFile);
|
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(mConfig, mApkInfo);
|
||||||
|
|
||||||
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(mConfig, mApkFile, mApkInfo);
|
|
||||||
|
|
||||||
if (mApkInfo.hasResources()) {
|
if (mApkInfo.hasResources()) {
|
||||||
switch (mConfig.decodeResources) {
|
switch (mConfig.decodeResources) {
|
||||||
@ -136,7 +130,7 @@ public class ApkDecoder {
|
|||||||
|
|
||||||
if (mApkInfo.hasMultipleSources()) {
|
if (mApkInfo.hasMultipleSources()) {
|
||||||
// foreach unknown dex file in root, lets disassemble it
|
// foreach unknown dex file in root, lets disassemble it
|
||||||
Set<String> files = mApkFile.getDirectory().getFiles(true);
|
Set<String> files = apkFile.getDirectory().getFiles(true);
|
||||||
for (String file : files) {
|
for (String file : files) {
|
||||||
if (file.endsWith(".dex")) {
|
if (file.endsWith(".dex")) {
|
||||||
if (!file.equalsIgnoreCase("classes.dex")) {
|
if (!file.equalsIgnoreCase("classes.dex")) {
|
||||||
@ -174,7 +168,7 @@ public class ApkDecoder {
|
|||||||
return mApkInfo;
|
return mApkInfo;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
mApkFile.close();
|
apkFile.close();
|
||||||
} catch (IOException ignored) {}
|
} catch (IOException ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +180,7 @@ public class ApkDecoder {
|
|||||||
private void copyManifestRaw(File outDir) throws AndrolibException {
|
private void copyManifestRaw(File outDir) throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
LOGGER.info("Copying raw manifest...");
|
LOGGER.info("Copying raw manifest...");
|
||||||
mApkFile.getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES);
|
mApkInfo.getApkFile().getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES);
|
||||||
} catch (DirectoryException ex) {
|
} catch (DirectoryException ex) {
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
}
|
}
|
||||||
@ -195,7 +189,7 @@ public class ApkDecoder {
|
|||||||
private void copyResourcesRaw(File outDir) throws AndrolibException {
|
private void copyResourcesRaw(File outDir) throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
LOGGER.info("Copying raw resources...");
|
LOGGER.info("Copying raw resources...");
|
||||||
mApkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
|
mApkInfo.getApkFile().getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
|
||||||
} catch (DirectoryException ex) {
|
} catch (DirectoryException ex) {
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
}
|
}
|
||||||
@ -204,7 +198,7 @@ public class ApkDecoder {
|
|||||||
private void copySourcesRaw(File outDir, String filename) throws AndrolibException {
|
private void copySourcesRaw(File outDir, String filename) throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
LOGGER.info("Copying raw " + filename + " file...");
|
LOGGER.info("Copying raw " + filename + " file...");
|
||||||
mApkFile.getDirectory().copyToDir(outDir, filename);
|
mApkInfo.getApkFile().getDirectory().copyToDir(outDir, filename);
|
||||||
} catch (DirectoryException ex) {
|
} catch (DirectoryException ex) {
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
}
|
}
|
||||||
@ -222,7 +216,7 @@ public class ApkDecoder {
|
|||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
smaliDir.mkdirs();
|
smaliDir.mkdirs();
|
||||||
LOGGER.info("Baksmaling " + filename + "...");
|
LOGGER.info("Baksmaling " + filename + "...");
|
||||||
DexFile dexFile = SmaliDecoder.decode(mApkFile, smaliDir, filename,
|
DexFile dexFile = SmaliDecoder.decode(mApkInfo.getApkFile(), smaliDir, filename,
|
||||||
mConfig.baksmaliDebugMode, mConfig.apiLevel);
|
mConfig.baksmaliDebugMode, mConfig.apiLevel);
|
||||||
int minSdkVersion = dexFile.getOpcodes().api;
|
int minSdkVersion = dexFile.getOpcodes().api;
|
||||||
if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) {
|
if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) {
|
||||||
@ -236,7 +230,7 @@ public class ApkDecoder {
|
|||||||
private void copyRawFiles(File outDir) throws AndrolibException {
|
private void copyRawFiles(File outDir) throws AndrolibException {
|
||||||
LOGGER.info("Copying assets and libs...");
|
LOGGER.info("Copying assets and libs...");
|
||||||
try {
|
try {
|
||||||
Directory in = mApkFile.getDirectory();
|
Directory in = mApkInfo.getApkFile().getDirectory();
|
||||||
|
|
||||||
if (mConfig.decodeAssets == Config.DECODE_ASSETS_FULL) {
|
if (mConfig.decodeAssets == Config.DECODE_ASSETS_FULL) {
|
||||||
if (in.containsDir("assets")) {
|
if (in.containsDir("assets")) {
|
||||||
@ -270,7 +264,7 @@ public class ApkDecoder {
|
|||||||
LOGGER.info("Copying unknown files...");
|
LOGGER.info("Copying unknown files...");
|
||||||
File unknownOut = new File(outDir, UNK_DIRNAME);
|
File unknownOut = new File(outDir, UNK_DIRNAME);
|
||||||
try {
|
try {
|
||||||
Directory unk = mApkFile.getDirectory();
|
Directory unk = mApkInfo.getApkFile().getDirectory();
|
||||||
|
|
||||||
// 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);
|
||||||
@ -281,11 +275,9 @@ public class ApkDecoder {
|
|||||||
unk.copyToDir(unknownOut, file);
|
unk.copyToDir(unknownOut, file);
|
||||||
// let's record the name of the file, and its compression type
|
// let's record the name of the file, and its compression type
|
||||||
// so that we may re-include it the same way
|
// so that we may re-include it the same way
|
||||||
mResUnknownFiles.addUnknownFileInfo(file, String.valueOf(unk.getCompressionLevel(file)));
|
mApkInfo.addUnknownFileInfo(file, String.valueOf(unk.getCompressionLevel(file)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update apk info
|
|
||||||
mApkInfo.unknownFiles = mResUnknownFiles.getUnknownFiles();
|
|
||||||
} catch (DirectoryException ex) {
|
} catch (DirectoryException ex) {
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
}
|
}
|
||||||
@ -300,7 +292,7 @@ public class ApkDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Directory in = mApkFile.getDirectory();
|
Directory in = mApkInfo.getApkFile().getDirectory();
|
||||||
if (in.containsFile("AndroidManifest.xml")) {
|
if (in.containsFile("AndroidManifest.xml")) {
|
||||||
in.copyToDir(originalDir, "AndroidManifest.xml");
|
in.copyToDir(originalDir, "AndroidManifest.xml");
|
||||||
}
|
}
|
||||||
@ -326,7 +318,7 @@ public class ApkDecoder {
|
|||||||
private void recordUncompressedFiles(Map<String, String> resFileMapping) throws AndrolibException {
|
private void recordUncompressedFiles(Map<String, String> resFileMapping) throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
List<String> uncompressedFilesOrExts = new ArrayList<>();
|
List<String> uncompressedFilesOrExts = new ArrayList<>();
|
||||||
Directory unk = mApkFile.getDirectory();
|
Directory unk = mApkInfo.getApkFile().getDirectory();
|
||||||
Set<String> files = unk.getFiles(true);
|
Set<String> files = unk.getFiles(true);
|
||||||
|
|
||||||
for (String file : files) {
|
for (String file : files) {
|
||||||
|
@ -39,7 +39,7 @@ public class ApkInfo implements YamlSerializable {
|
|||||||
public boolean resourcesAreCompressed;
|
public boolean resourcesAreCompressed;
|
||||||
public boolean sharedLibrary;
|
public boolean sharedLibrary;
|
||||||
public boolean sparseResources;
|
public boolean sparseResources;
|
||||||
public Map<String, String> unknownFiles;
|
public Map<String, String> unknownFiles = new LinkedHashMap<>();
|
||||||
public List<String> doNotCompress;
|
public List<String> doNotCompress;
|
||||||
|
|
||||||
/** @deprecated use {@link #resourcesAreCompressed} */
|
/** @deprecated use {@link #resourcesAreCompressed} */
|
||||||
@ -120,6 +120,10 @@ public class ApkInfo implements YamlSerializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addUnknownFileInfo(String file, String value) {
|
||||||
|
unknownFiles.put(file, value);
|
||||||
|
}
|
||||||
|
|
||||||
public String checkTargetSdkVersionBounds() {
|
public String checkTargetSdkVersionBounds() {
|
||||||
int target = mapSdkShorthandToVersion(getTargetSdkVersion());
|
int target = mapSdkShorthandToVersion(getTargetSdkVersion());
|
||||||
|
|
||||||
@ -295,7 +299,9 @@ public class ApkInfo implements YamlSerializable {
|
|||||||
writer.writeBool("resourcesAreCompressed", resourcesAreCompressed);
|
writer.writeBool("resourcesAreCompressed", resourcesAreCompressed);
|
||||||
writer.writeBool("sharedLibrary", sharedLibrary);
|
writer.writeBool("sharedLibrary", sharedLibrary);
|
||||||
writer.writeBool("sparseResources", sparseResources);
|
writer.writeBool("sparseResources", sparseResources);
|
||||||
writer.writeStringMap("unknownFiles", unknownFiles);
|
if (unknownFiles.size() > 0) {
|
||||||
|
writer.writeStringMap("unknownFiles", unknownFiles);
|
||||||
|
}
|
||||||
writer.writeList("doNotCompress", doNotCompress);
|
writer.writeList("doNotCompress", doNotCompress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ import brut.androlib.res.xml.ResValuesXmlSerializable;
|
|||||||
import brut.androlib.res.xml.ResXmlPatcher;
|
import brut.androlib.res.xml.ResXmlPatcher;
|
||||||
import brut.directory.Directory;
|
import brut.directory.Directory;
|
||||||
import brut.directory.DirectoryException;
|
import brut.directory.DirectoryException;
|
||||||
import brut.directory.ExtFile;
|
|
||||||
import brut.directory.FileDirectory;
|
import brut.directory.FileDirectory;
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
|
|
||||||
@ -39,7 +38,6 @@ public class ResourcesDecoder {
|
|||||||
private final static Logger LOGGER = Logger.getLogger(ResourcesDecoder.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(ResourcesDecoder.class.getName());
|
||||||
|
|
||||||
private final Config mConfig;
|
private final Config mConfig;
|
||||||
private final ExtFile mApkFile;
|
|
||||||
private final ApkInfo mApkInfo;
|
private final ApkInfo mApkInfo;
|
||||||
private final ResTable mResTable;
|
private final ResTable mResTable;
|
||||||
private final Map<String, String> mResFileMapping = new HashMap<>();
|
private final Map<String, String> mResFileMapping = new HashMap<>();
|
||||||
@ -48,9 +46,8 @@ public class ResourcesDecoder {
|
|||||||
"android", "com.htc", "com.lge", "com.lge.internal", "yi", "flyme", "air.com.adobe.appentry",
|
"android", "com.htc", "com.lge", "com.lge.internal", "yi", "flyme", "air.com.adobe.appentry",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFF" };
|
"FFFFFFFFFFFFFFFFFFFFFF" };
|
||||||
|
|
||||||
public ResourcesDecoder(Config config, ExtFile apkFile, ApkInfo apkInfo) {
|
public ResourcesDecoder(Config config, ApkInfo apkInfo) {
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
mApkFile = apkFile;
|
|
||||||
mApkInfo = apkInfo;
|
mApkInfo = apkInfo;
|
||||||
mResTable = new ResTable(mConfig, mApkInfo);
|
mResTable = new ResTable(mConfig, mApkInfo);
|
||||||
}
|
}
|
||||||
@ -68,7 +65,7 @@ public class ResourcesDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadMainPkg() throws AndrolibException {
|
public void loadMainPkg() throws AndrolibException {
|
||||||
mResTable.loadMainPkg(mApkFile);
|
mResTable.loadMainPkg(mApkInfo.getApkFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decodeManifest(File outDir) throws AndrolibException {
|
public void decodeManifest(File outDir) throws AndrolibException {
|
||||||
@ -81,7 +78,7 @@ public class ResourcesDecoder {
|
|||||||
|
|
||||||
Directory inApk, out;
|
Directory inApk, out;
|
||||||
try {
|
try {
|
||||||
inApk = mApkFile.getDirectory();
|
inApk = mApkInfo.getApkFile().getDirectory();
|
||||||
out = new FileDirectory(outDir);
|
out = new FileDirectory(outDir);
|
||||||
|
|
||||||
if (mApkInfo.hasResources()) {
|
if (mApkInfo.hasResources()) {
|
||||||
@ -147,7 +144,7 @@ public class ResourcesDecoder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mResTable.loadMainPkg(mApkFile);
|
mResTable.loadMainPkg(mApkInfo.getApkFile());
|
||||||
|
|
||||||
ResStreamDecoderContainer decoders = new ResStreamDecoderContainer();
|
ResStreamDecoderContainer decoders = new ResStreamDecoderContainer();
|
||||||
decoders.setDecoder("raw", new ResRawStreamDecoder());
|
decoders.setDecoder("raw", new ResRawStreamDecoder());
|
||||||
@ -161,7 +158,7 @@ public class ResourcesDecoder {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
out = new FileDirectory(outDir);
|
out = new FileDirectory(outDir);
|
||||||
in = mApkFile.getDirectory();
|
in = mApkInfo.getApkFile().getDirectory();
|
||||||
out = out.createDir("res");
|
out = out.createDir("res");
|
||||||
} catch (DirectoryException ex) {
|
} catch (DirectoryException ex) {
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010 Ryszard Wiśniewski <brut.alll@gmail.com>
|
|
||||||
* Copyright (C) 2010 Connor Tumbleson <connor.tumbleson@gmail.com>
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package brut.androlib.res.data;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class ResUnknownFiles {
|
|
||||||
|
|
||||||
private final Map<String, String> mUnknownFiles = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
public void addUnknownFileInfo(String file, String value) {
|
|
||||||
mUnknownFiles.put(file, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getUnknownFiles() {
|
|
||||||
return mUnknownFiles;
|
|
||||||
}
|
|
||||||
}
|
|
@ -54,7 +54,7 @@ public class NonStandardPkgIdTest extends BaseTest {
|
|||||||
|
|
||||||
LOGGER.info("Decoding pkgid8.apk...");
|
LOGGER.info("Decoding pkgid8.apk...");
|
||||||
ApkInfo testInfo = new ApkInfo(testApk);
|
ApkInfo testInfo = new ApkInfo(testApk);
|
||||||
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), testApk, testInfo);
|
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), testInfo);
|
||||||
|
|
||||||
sTestNewDir.mkdirs();
|
sTestNewDir.mkdirs();
|
||||||
resourcesDecoder.decodeResources(sTestNewDir);
|
resourcesDecoder.decodeResources(sTestNewDir);
|
||||||
|
@ -55,7 +55,7 @@ public class DecodeArrayTest extends BaseTest {
|
|||||||
ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk");
|
ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk");
|
||||||
ApkInfo apkInfo = new ApkInfo(apkFile);
|
ApkInfo apkInfo = new ApkInfo(apkFile);
|
||||||
//ApkDecoder apkDecoder = new ApkDecoder(apkFile);
|
//ApkDecoder apkDecoder = new ApkDecoder(apkFile);
|
||||||
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkFile, apkInfo);
|
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkInfo);
|
||||||
|
|
||||||
resourcesDecoder.loadMainPkg();
|
resourcesDecoder.loadMainPkg();
|
||||||
ResTable resTable = resourcesDecoder.getResTable();
|
ResTable resTable = resourcesDecoder.getResTable();
|
||||||
@ -68,7 +68,7 @@ public class DecodeArrayTest extends BaseTest {
|
|||||||
public void decodeArray() throws BrutException {
|
public void decodeArray() throws BrutException {
|
||||||
ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk");
|
ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk");
|
||||||
ApkInfo apkInfo = new ApkInfo(apkFile);
|
ApkInfo apkInfo = new ApkInfo(apkFile);
|
||||||
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkFile, apkInfo);
|
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkInfo);
|
||||||
|
|
||||||
resourcesDecoder.loadMainPkg();
|
resourcesDecoder.loadMainPkg();
|
||||||
ResTable resTable = resourcesDecoder.getResTable();
|
ResTable resTable = resourcesDecoder.getResTable();
|
||||||
|
Loading…
Reference in New Issue
Block a user