Skip to content

Commit e9a8455

Browse files
committed
refactor class ApkDecoder
1 parent 40d427e commit e9a8455

File tree

2 files changed

+124
-129
lines changed

2 files changed

+124
-129
lines changed

brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java

Lines changed: 31 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
111111
if (hasResources()) {
112112
switch (config.decodeResources) {
113113
case Config.DECODE_RESOURCES_NONE:
114-
decodeResourcesRaw(mApkFile, outDir);
114+
copyResourcesRaw(mApkFile, outDir);
115115
if (config.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
116116
// done after raw decoding of resources because copyToDir overwrites dest files
117117
if (hasManifest()) {
@@ -135,15 +135,15 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
135135
decodeManifestFull(mApkFile, outDir, getResTable());
136136
}
137137
else {
138-
decodeManifestRaw(mApkFile, outDir);
138+
copyManifestRaw(mApkFile, outDir);
139139
}
140140
}
141141
}
142142

143143
if (hasSources()) {
144144
switch (config.decodeSources) {
145145
case Config.DECODE_SOURCES_NONE:
146-
decodeSourcesRaw(mApkFile, outDir, "classes.dex");
146+
copySourcesRaw(mApkFile, outDir, "classes.dex");
147147
break;
148148
case Config.DECODE_SOURCES_SMALI:
149149
case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES:
@@ -160,7 +160,7 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
160160
if (! file.equalsIgnoreCase("classes.dex")) {
161161
switch(config.decodeSources) {
162162
case Config.DECODE_SOURCES_NONE:
163-
decodeSourcesRaw(mApkFile, outDir, file);
163+
copySourcesRaw(mApkFile, outDir, file);
164164
break;
165165
case Config.DECODE_SOURCES_SMALI:
166166
decodeSourcesSmali(mApkFile, outDir, file);
@@ -169,7 +169,7 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
169169
if (file.startsWith("classes") && file.endsWith(".dex")) {
170170
decodeSourcesSmali(mApkFile, outDir, file);
171171
} else {
172-
decodeSourcesRaw(mApkFile, outDir, file);
172+
copySourcesRaw(mApkFile, outDir, file);
173173
}
174174
break;
175175
}
@@ -178,11 +178,11 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
178178
}
179179
}
180180

181-
decodeRawFiles(mApkFile, outDir);
182-
decodeUnknownFiles(mApkFile, outDir);
181+
copyRawFiles(mApkFile, outDir);
182+
copyUnknownFiles(mApkFile, outDir);
183183
mUncompressedFiles = new ArrayList<>();
184184
recordUncompressedFiles(mApkFile, mUncompressedFiles);
185-
writeOriginalFiles(mApkFile, outDir);
185+
copyOriginalFiles(mApkFile, outDir);
186186
writeMetaFile(outDir);
187187
} finally {
188188
try {
@@ -250,25 +250,25 @@ public void close() throws IOException {
250250
mAndRes.close();
251251
}
252252

253-
public void writeMetaFile(File outDir)
254-
throws AndrolibException {
253+
public void writeMetaFile(File outDir) throws AndrolibException {
255254
MetaInfo meta = new MetaInfo();
256255
meta.version = ApktoolProperties.getVersion();
257256
meta.apkFileName = mApkFile.getName();
258257

259258
if (mResTable != null) {
260-
meta.isFrameworkApk = mResTable.isFrameworkApk();
261-
putUsesFramework(meta);
262-
putSdkInfo(outDir, meta);
263-
putPackageInfo(meta);
264-
putVersionInfo(outDir, meta);
265-
putSharedLibraryInfo(meta);
266-
putSparseResourcesInfo(meta);
259+
mResTable.initMetaInfo(meta, outDir);
260+
if (config.frameworkTag != null) {
261+
meta.usesFramework.tag = config.frameworkTag;
262+
}
267263
} else {
268-
putMinSdkInfo(meta);
264+
if (mMinSdkVersion > 0) {
265+
meta.sdkInfo = getMinSdkInfo();
266+
}
267+
}
268+
meta.unknownFiles = mResUnknownFiles.getUnknownFiles();
269+
if (mUncompressedFiles != null && !mUncompressedFiles.isEmpty()) {
270+
meta.doNotCompress = mUncompressedFiles;
269271
}
270-
putUnknownInfo(meta);
271-
putFileCompressionInfo(meta);
272272

273273
try {
274274
meta.save(new File(outDir, "apktool.yml"));
@@ -277,111 +277,13 @@ public void writeMetaFile(File outDir)
277277
}
278278
}
279279

280-
private void putUsesFramework(MetaInfo meta) {
281-
Set<ResPackage> pkgs = mResTable.listFramePackages();
282-
if (pkgs.isEmpty()) {
283-
return;
284-
}
285-
286-
Integer[] ids = new Integer[pkgs.size()];
287-
int i = 0;
288-
for (ResPackage pkg : pkgs) {
289-
ids[i++] = pkg.getId();
290-
}
291-
Arrays.sort(ids);
292-
293-
meta.usesFramework = new UsesFramework();
294-
meta.usesFramework.ids = Arrays.asList(ids);
295-
296-
if (config.frameworkTag != null) {
297-
meta.usesFramework.tag = config.frameworkTag;
298-
}
299-
}
300-
301-
private void putSdkInfo(File outDir, MetaInfo meta) {
302-
Map<String, String> info = mResTable.getSdkInfo();
303-
if (info.size() > 0) {
304-
String refValue;
305-
if (info.get("minSdkVersion") != null) {
306-
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("minSdkVersion"));
307-
if (refValue != null) {
308-
info.put("minSdkVersion", refValue);
309-
}
310-
}
311-
if (info.get("targetSdkVersion") != null) {
312-
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("targetSdkVersion"));
313-
if (refValue != null) {
314-
info.put("targetSdkVersion", refValue);
315-
}
316-
}
317-
if (info.get("maxSdkVersion") != null) {
318-
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("maxSdkVersion"));
319-
if (refValue != null) {
320-
info.put("maxSdkVersion", refValue);
321-
}
322-
}
323-
meta.sdkInfo = info;
324-
}
325-
}
326-
327-
private void putMinSdkInfo(MetaInfo meta) {
328-
if (mMinSdkVersion > 0) {
329-
Map<String, String> sdkInfo = new LinkedHashMap<>();
330-
sdkInfo.put("minSdkVersion", Integer.toString(mMinSdkVersion));
331-
meta.sdkInfo = sdkInfo;
332-
}
333-
}
334-
335-
private void putPackageInfo(MetaInfo meta) throws AndrolibException {
336-
String renamed = mResTable.getPackageRenamed();
337-
String original = mResTable.getPackageOriginal();
338-
339-
int id = mResTable.getPackageId();
340-
try {
341-
id = mResTable.getPackage(renamed).getId();
342-
} catch (UndefinedResObjectException ignored) {}
343-
344-
if (Strings.isNullOrEmpty(original)) {
345-
return;
346-
}
347-
348-
meta.packageInfo = new PackageInfo();
349-
350-
// only put rename-manifest-package into apktool.yml, if the change will be required
351-
if (!renamed.equalsIgnoreCase(original)) {
352-
meta.packageInfo.renameManifestPackage = renamed;
353-
}
354-
meta.packageInfo.forcedPackageId = String.valueOf(id);
355-
}
356-
357-
private void putVersionInfo(File outDir, MetaInfo meta) {
358-
VersionInfo info = mResTable.getVersionInfo();
359-
String refValue = ResXmlPatcher.pullValueFromStrings(outDir, info.versionName);
360-
if (refValue != null) {
361-
info.versionName = refValue;
362-
}
363-
meta.versionInfo = info;
364-
}
365-
366-
private void putSharedLibraryInfo(MetaInfo meta) {
367-
meta.sharedLibrary = mResTable.getSharedLibrary();
368-
}
369-
370-
private void putSparseResourcesInfo(MetaInfo meta) {
371-
meta.sparseResources = mResTable.getSparseResources();
372-
}
373-
374-
private void putUnknownInfo(MetaInfo meta) {
375-
meta.unknownFiles = mResUnknownFiles.getUnknownFiles();
376-
}
377-
378-
private void putFileCompressionInfo(MetaInfo meta) {
379-
if (mUncompressedFiles != null && !mUncompressedFiles.isEmpty()) {
380-
meta.doNotCompress = mUncompressedFiles;
381-
}
280+
private Map<String, String> getMinSdkInfo() {
281+
Map<String, String> sdkInfo = new LinkedHashMap<>();
282+
sdkInfo.put("minSdkVersion", Integer.toString(mMinSdkVersion));
283+
return sdkInfo;
382284
}
383285

384-
public void decodeSourcesRaw(ExtFile apkFile, File outDir, String filename)
286+
public void copySourcesRaw(ExtFile apkFile, File outDir, String filename)
385287
throws AndrolibException {
386288
try {
387289
LOGGER.info("Copying raw " + filename + " file...");
@@ -415,7 +317,7 @@ public void decodeSourcesSmali(File apkFile, File outDir, String filename)
415317
}
416318
}
417319

418-
public void decodeManifestRaw(ExtFile apkFile, File outDir)
320+
public void copyManifestRaw(ExtFile apkFile, File outDir)
419321
throws AndrolibException {
420322
try {
421323
LOGGER.info("Copying raw manifest...");
@@ -430,7 +332,7 @@ public void decodeManifestFull(ExtFile apkFile, File outDir, ResTable resTable)
430332
mAndRes.decodeManifest(resTable, apkFile, outDir);
431333
}
432334

433-
public void decodeResourcesRaw(ExtFile apkFile, File outDir)
335+
public void copyResourcesRaw(ExtFile apkFile, File outDir)
434336
throws AndrolibException {
435337
try {
436338
LOGGER.info("Copying raw resources...");
@@ -450,7 +352,7 @@ public void decodeManifestWithResources(ExtFile apkFile, File outDir, ResTable r
450352
mAndRes.decodeManifestWithResources(resTable, apkFile, outDir);
451353
}
452354

453-
public void decodeRawFiles(ExtFile apkFile, File outDir)
355+
public void copyRawFiles(ExtFile apkFile, File outDir)
454356
throws AndrolibException {
455357
LOGGER.info("Copying assets and libs...");
456358
try {
@@ -484,7 +386,7 @@ private boolean isAPKFileNames(String file) {
484386
return false;
485387
}
486388

487-
public void decodeUnknownFiles(ExtFile apkFile, File outDir)
389+
public void copyUnknownFiles(ExtFile apkFile, File outDir)
488390
throws AndrolibException {
489391
LOGGER.info("Copying unknown files...");
490392
File unknownOut = new File(outDir, UNK_DIRNAME);
@@ -508,7 +410,7 @@ public void decodeUnknownFiles(ExtFile apkFile, File outDir)
508410
}
509411
}
510412

511-
public void writeOriginalFiles(ExtFile apkFile, File outDir)
413+
public void copyOriginalFiles(ExtFile apkFile, File outDir)
512414
throws AndrolibException {
513415
LOGGER.info("Copying original files...");
514416
File originalDir = new File(outDir, "original");
@@ -531,7 +433,7 @@ public void writeOriginalFiles(ExtFile apkFile, File outDir)
531433
if (in.containsDir("META-INF/services")) {
532434
// If the original APK contains the folder META-INF/services folder
533435
// that is used for service locators (like coroutines on android),
534-
// copy it to the destination folder so it does not get dropped.
436+
// copy it to the destination folder, so it does not get dropped.
535437
LOGGER.info("Copying META-INF/services directory");
536438
in.copyToDir(outDir, "META-INF/services");
537439
}

brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@
1818

1919
import brut.androlib.exceptions.AndrolibException;
2020
import brut.androlib.exceptions.UndefinedResObjectException;
21+
import brut.androlib.meta.MetaInfo;
22+
import brut.androlib.meta.PackageInfo;
23+
import brut.androlib.meta.UsesFramework;
2124
import brut.androlib.meta.VersionInfo;
2225
import brut.androlib.res.AndrolibResources;
2326
import brut.androlib.res.data.value.ResValue;
27+
import brut.androlib.res.xml.ResXmlPatcher;
28+
import com.google.common.base.Strings;
29+
30+
import java.io.File;
2431
import java.util.*;
2532

2633
public class ResTable {
@@ -220,4 +227,90 @@ public boolean isFrameworkApk() {
220227
}
221228
return false;
222229
}
230+
231+
public void initMetaInfo(MetaInfo meta, File outDir) throws AndrolibException {
232+
meta.isFrameworkApk = isFrameworkApk();
233+
if (!listFramePackages().isEmpty()) {
234+
meta.usesFramework = getUsesFramework();
235+
}
236+
if (!getSdkInfo().isEmpty()) {
237+
initSdkInfo(outDir);
238+
meta.sdkInfo = getSdkInfo();
239+
}
240+
meta.packageInfo = getPackageInfo();
241+
meta.versionInfo = getVersionInfoWithName(outDir);
242+
meta.sharedLibrary = getSharedLibrary();
243+
meta.sparseResources = getSparseResources();
244+
}
245+
246+
private UsesFramework getUsesFramework() {
247+
Set<ResPackage> pkgs = listFramePackages();
248+
249+
Integer[] ids = new Integer[pkgs.size()];
250+
int i = 0;
251+
for (ResPackage pkg : pkgs) {
252+
ids[i++] = pkg.getId();
253+
}
254+
Arrays.sort(ids);
255+
256+
UsesFramework info = new UsesFramework();
257+
info.ids = Arrays.asList(ids);
258+
259+
return info;
260+
}
261+
262+
private void initSdkInfo(File outDir) {
263+
Map<String, String> info = mSdkInfo;
264+
String refValue;
265+
if (info.get("minSdkVersion") != null) {
266+
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("minSdkVersion"));
267+
if (refValue != null) {
268+
info.put("minSdkVersion", refValue);
269+
}
270+
}
271+
if (info.get("targetSdkVersion") != null) {
272+
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("targetSdkVersion"));
273+
if (refValue != null) {
274+
info.put("targetSdkVersion", refValue);
275+
}
276+
}
277+
if (info.get("maxSdkVersion") != null) {
278+
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("maxSdkVersion"));
279+
if (refValue != null) {
280+
info.put("maxSdkVersion", refValue);
281+
}
282+
}
283+
}
284+
285+
private PackageInfo getPackageInfo() throws AndrolibException {
286+
String renamed = getPackageRenamed();
287+
String original = getPackageOriginal();
288+
289+
int id = getPackageId();
290+
try {
291+
id = getPackage(renamed).getId();
292+
} catch (UndefinedResObjectException ignored) {}
293+
294+
if (Strings.isNullOrEmpty(original)) {
295+
return null;
296+
}
297+
298+
PackageInfo info = new PackageInfo();
299+
300+
// only put rename-manifest-package into apktool.yml, if the change will be required
301+
if (!renamed.equalsIgnoreCase(original)) {
302+
info.renameManifestPackage = renamed;
303+
}
304+
info.forcedPackageId = String.valueOf(id);
305+
return info;
306+
}
307+
308+
private VersionInfo getVersionInfoWithName(File outDir) {
309+
VersionInfo info = getVersionInfo();
310+
String refValue = ResXmlPatcher.pullValueFromStrings(outDir, info.versionName);
311+
if (refValue != null) {
312+
info.versionName = refValue;
313+
}
314+
return info;
315+
}
223316
}

0 commit comments

Comments
 (0)