Skip to content

Commit

Permalink
Merge pull request #132 from REAndroid/more-info
Browse files Browse the repository at this point in the history
More `info` functions: locales, languages, configurations, strings
  • Loading branch information
REAndroid authored Sep 28, 2024
2 parents d783603 + 06ea40b commit 5c15e00
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 14 deletions.
80 changes: 70 additions & 10 deletions src/main/java/com/reandroid/apkeditor/info/Info.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,16 @@
import com.reandroid.arsc.coder.ReferenceString;
import com.reandroid.arsc.coder.ValueCoder;
import com.reandroid.arsc.model.ResourceEntry;
import com.reandroid.arsc.value.*;
import com.reandroid.dex.model.DexDirectory;
import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.HexUtil;
import com.reandroid.arsc.value.AttributeDataFormat;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResValue;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.utils.collection.CollectionUtil;
import com.reandroid.utils.collection.ComputeIterator;

import java.io.*;
import java.util.*;
import java.util.function.Function;

public class Info extends CommandExecutor<InfoOptions> {
private InfoWriter mInfoWriter;
Expand Down Expand Up @@ -100,8 +99,12 @@ private void print(ApkModule apkModule) throws IOException {

printXmlTree(apkModule);
printXmlStrings(apkModule);
printStrings(apkModule);
listFiles(apkModule);
listXmlFiles(apkModule);
printConfigurations(apkModule);
printLanguages(apkModule);
printLocales(apkModule);
}
private void printSourceFile() throws IOException {
InfoOptions options = getOptions();
Expand Down Expand Up @@ -357,15 +360,25 @@ private void printAppClass(ApkModule apkModule) throws IOException {
}
private void printXmlStrings(ApkModule apkModule) throws IOException {
InfoOptions options = getOptions();
String xmlStrings = options.xmlStrings;
if (xmlStrings == null) {
List<String> xmlStrings = options.xmlStrings;
if (xmlStrings.isEmpty()) {
return;
}
InfoWriter infoWriter = getInfoWriter();
ResXmlDocument document = apkModule.loadResXmlDocument(xmlStrings);
document.setApkFile(null);
document.setPackageBlock(null);
infoWriter.writeStringPool(xmlStrings, document.getStringPool());
for (String path : xmlStrings) {
ResXmlDocument document = apkModule.loadResXmlDocument(path);
document.setApkFile(null);
document.setPackageBlock(null);
infoWriter.writeStringPool(path, document.getStringPool());
}
}
private void printStrings(ApkModule apkModule) throws IOException {
InfoOptions options = getOptions();
if (!options.strings || !apkModule.hasTableBlock()) {
return;
}
InfoWriter infoWriter = getInfoWriter();
infoWriter.writeStringPool(TableBlock.FILE_NAME, apkModule.getTableBlock().getStringPool());
}
private void printXmlTree(ApkModule apkModule) throws IOException {
InfoOptions options = getOptions();
Expand Down Expand Up @@ -405,6 +418,53 @@ private void listXmlFiles(ApkModule apkModule) throws IOException {
}
getInfoWriter().writeArray("CompiledXmlFiles", names.toArray(new String[0]));
}
private void printConfigurations(ApkModule apkModule) throws IOException {
InfoOptions options = getOptions();
if (!options.configurations || !apkModule.hasTableBlock()) {
return;
}
Iterator<ResConfig> iterator = apkModule.getTableBlock().getResConfigs();
List<String> qualifiers = CollectionUtil.toUniqueList(
ComputeIterator.of(iterator, config -> {
String qualifier = config.getQualifiers();
if (qualifier.length() != 0) {
qualifier = qualifier.substring(1);
}
return qualifier;
}));

qualifiers.sort(CompareUtil.getComparableComparator());

getInfoWriter().writeArray("configurations", qualifiers.toArray(new String[0]));
}
private void printLanguages(ApkModule apkModule) throws IOException {
InfoOptions options = getOptions();
if (!options.languages || !apkModule.hasTableBlock()) {
return;
}
Iterator<ResConfig> iterator = apkModule.getTableBlock().getResConfigs();
List<String> languages = CollectionUtil.toUniqueList(
ComputeIterator.of(iterator, ResConfig::getLanguage));

languages.sort(CompareUtil.getComparableComparator());

getInfoWriter().writeArray("languages", languages.toArray(new String[0]));
}
private void printLocales(ApkModule apkModule) throws IOException {
InfoOptions options = getOptions();
if (!options.locales || !apkModule.hasTableBlock()) {
return;
}
Iterator<ResConfig> iterator = apkModule.getTableBlock().getResConfigs();
List<String> locales = CollectionUtil.toUniqueList(
ComputeIterator.of(iterator, ResConfig::getLocale));

locales.remove("");

locales.sort(CompareUtil.getComparableComparator());

getInfoWriter().writeArray("locales", locales.toArray(new String[0]));
}
private String getValueOfName(ResXmlElement element){
ResXmlAttribute attribute = element
.searchAttributeByResourceId(AndroidManifest.ID_name);
Expand Down
41 changes: 38 additions & 3 deletions src/main/java/com/reandroid/apkeditor/info/InfoOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,51 +37,85 @@ public class InfoOptions extends OptionsWithFramework {

@ChoiceArg(name = "-t", description = "info_print_types", values = {TYPE_TEXT, TYPE_JSON, TYPE_XML})
public String type = TYPE_TEXT;

@OptionArg(name = "-v", description = "info_verbose_mode", flag = true)
public boolean verbose = false;

@OptionArg(name = "-package", description = "info_package_name", flag = true)
public boolean packageName = false;

@OptionArg(name = "-version-code", description = "info_app_version_code", flag = true)
public boolean versionCode = false;

@OptionArg(name = "-version-name", description = "info_app_version_name", flag = true)
public boolean versionName = false;

@OptionArg(name = "-min-sdk-version", description = "info_min_sdk_version", flag = true)
public boolean minSdkVersion = false;

@OptionArg(name = "-target-sdk-version", description = "info_target_sdk_version", flag = true)
public boolean targetSdkVersion = false;

@OptionArg(name = "-app-name", description = "info_app_name", flag = true)
public boolean appName = false;

@OptionArg(name = "-app-icon", description = "info_app_icon", flag = true)
public boolean appIcon = false;

@OptionArg(name = "-app-round-icon", description = "info_app_icon_round", flag = true)
public boolean appRoundIcon = false;

@OptionArg(name = "-permissions", description = "info_permissions", flag = true)
public boolean permissions = false;

@OptionArg(name = "-app-class", description = "info_app_class_name", flag = true)
public boolean appClass = false;

@OptionArg(name = "-activities", description = "info_activities", flag = true)
public boolean activities = false;

@OptionArg(name = "-res", description = "info_res")
public final List<String> resList = new ArrayList<>();

@OptionArg(name = "-resources", description = "info_resources", flag = true)
public boolean resources = false;

@OptionArg(name = "-filter-type", description = "info_filter_type")
public final List<String> typeFilterList = new ArrayList<>();

@OptionArg(name = "-dex", description = "info_dex", flag = true)
public boolean dex = false;

@OptionArg(name = "-signatures", description = "info_signatures", flag = true)
public boolean signatures = false;

@OptionArg(name = "-signatures-base64", description = "info_signatures_base64", flag = true)
public boolean signatures_base64 = false;

@OptionArg(name = "-xmlstrings", description = "info_xml_strings")
public String xmlStrings;
public List<String> xmlStrings = new ArrayList<>();

@OptionArg(name = "-strings", description = "info_strings", flag = true)
public boolean strings = false;

@OptionArg(name = "-xmltree", description = "info_xml_tree")
public final List<String> xmlTree = new ArrayList<>();

@OptionArg(name = "-list-files", description = "info_list_files", flag = true)
public boolean listFiles = false;

@OptionArg(name = "-list-xml-files", description = "info_list_xml_files", flag = true)
public boolean listXmlFiles = false;

@OptionArg(name = "-configurations", description = "info_configurations", flag = true)
public boolean configurations = false;

@OptionArg(name = "-languages", description = "info_languages", flag = true)
public boolean languages = false;

@OptionArg(name = "-locales", description = "info_locales", flag = true)
public boolean locales = false;

public InfoOptions(){
super();
}
Expand Down Expand Up @@ -148,8 +182,9 @@ private boolean isDefault() {
boolean flagsChanged = activities || appClass || appIcon || appName || appRoundIcon ||
dex || minSdkVersion || packageName || permissions || targetSdkVersion ||
resources || signatures || signatures_base64 || versionCode || versionName ||
listFiles || listXmlFiles || xmlStrings != null;
listFiles || listXmlFiles || configurations || languages || locales || strings;

return !flagsChanged && resList.isEmpty() && typeFilterList.isEmpty() && xmlTree.isEmpty();
return !flagsChanged && resList.isEmpty() && typeFilterList.isEmpty() &&
xmlTree.isEmpty() && xmlStrings.isEmpty();
}
}
6 changes: 5 additions & 1 deletion src/main/resources/strings/strings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ info_example_2=[Specify output and type]\n java -jar APKEditor.jar info -i path
info_example_3=[Print only specific type]\n java -jar APKEditor.jar info -i path/input.apk -resources -filter-type drawable
info_filter_type=Prints only the specified resource type names\n *This applies only when flag '-resources' used.\n *Can be multiple.
info_invalid_output_extension=Invalid file extension! Expected '%s', '%s'
info_configurations=Print the configurations in the APK.
info_languages=Print the languages in the APK.
info_locales=Print the locales in the APK.
info_list_files=List files inside apk.
info_list_xml_files=List compiled xml files inside apk.
info_min_sdk_version=Minimum SDK version.
Expand All @@ -74,10 +77,11 @@ info_res=Prints resource entries specified by either of\:\n 1) Hex or decimal r
info_resources=Prints all resources
info_signatures=Prints signature information.
info_signatures_base64=Prints signature information with base64 certificates.
info_strings=Print the contents of the resource table string pool in the APK.
info_target_sdk_version=Target SDK version.
info_verbose_mode=Verbose mode.
info_xml_tree=Prints the compiled xmls in the given assets.\n *Can be multiple
info_xml_strings=Print the strings of the given compiled xml assets.
info_xml_strings=Print the strings of the given compiled xml assets.\n *Can be multiple
input_path=Input path.
invalid_sig_parameter_combination=Invalid parameter combination!\nSignatures directory provided but missing: -t sig
invalid_type_format=Invalid <%s> string '%s'
Expand Down

0 comments on commit 5c15e00

Please sign in to comment.