diff --git a/build.sh b/build.sh
index 1a4fc86..237dfed 100755
--- a/build.sh
+++ b/build.sh
@@ -1,4 +1,4 @@
#!/bin/bash
mvn clean compile assembly:single
-cp ./target/appium_apk_tools-0.0.2-SNAPSHOT-jar-with-all.jar ./appium_apk_tools.jar
\ No newline at end of file
+cp ./target/appium_apk_tools-0.0.3-SNAPSHOT-jar-with-all.jar ./appium_apk_tools.jar
\ No newline at end of file
diff --git a/lib/apktool-cli-2.2.2-SNAPSHOT.jar b/lib/apktool-cli-2.2.2-SNAPSHOT.jar
new file mode 100644
index 0000000..12aea5d
Binary files /dev/null and b/lib/apktool-cli-2.2.2-SNAPSHOT.jar differ
diff --git a/pom.xml b/pom.xml
index 0eb0e7b..76aba54 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
appium_apk_tools
appium_apk_tools
- 0.0.2-SNAPSHOT
+ 0.0.3-SNAPSHOT
appium_apk_tools
jar
@@ -25,8 +25,8 @@
maven-compiler-plugin
3.0
- 1.6
- 1.6
+ 1.7
+ 1.7
@@ -56,12 +56,12 @@
apktool.snapshot
apktool
- 1.5.3
+ 2.2.2
system
- ${project.basedir}/lib/apktool-cli-1.5.3-SNAPSHOT.jar
+ ${project.basedir}/lib/apktool-cli-2.2.2-SNAPSHOT.jar
diff --git a/src/io/appium/apktools/StringsXML.java b/src/io/appium/apktools/StringsXML.java
index 5ed2a67..6a877c7 100644
--- a/src/io/appium/apktools/StringsXML.java
+++ b/src/io/appium/apktools/StringsXML.java
@@ -12,6 +12,7 @@
import brut.androlib.res.data.ResResource;
import brut.androlib.res.data.ResTable;
import brut.androlib.res.data.ResValuesFile;
+import brut.androlib.res.data.value.ResPluralsValue;
import brut.androlib.res.data.value.ResScalarValue;
import brut.androlib.res.util.ExtFile;
import brut.androlib.res.util.ExtMXSerializer;
@@ -34,15 +35,16 @@ public static void p(final Object msg) {
}
}
- public static void toJSON(final ResValuesFile input,
- final File outputDirectory) throws Exception {
- String[] paths = input.getPath().split("/"); // always "/" even on Windows
+ public static void toJSON(final ResValuesFile stringValues,
+ final ResValuesFile pluralsValues,
+ final File outputDirectory) throws Exception {
+ String[] paths = stringValues.getPath().split("/"); // always "/" even on Windows
final String outName = paths[paths.length - 1].replaceFirst("\\.xml$",
- ".json");
+ ".json");
final File outFile = new File(outputDirectory, outName);
p("Saving to: " + outFile);
JsonGenerator generator = json.createGenerator(
- new FileOutputStream(outFile), JsonEncoding.UTF8);
+ new FileOutputStream(outFile), JsonEncoding.UTF8);
// Ensure output stream is auto closed when generator.close() is called.
generator.configure(Feature.AUTO_CLOSE_TARGET, true);
@@ -56,20 +58,48 @@ public static void toJSON(final ResValuesFile input,
generator.useDefaultPrettyPrinter();
// ResStringValue extends ResScalarValue which has field mRawValue
- final Field valueField = ResScalarValue.class.getDeclaredField("mRawValue");
- valueField.setAccessible(true);
+ final Field stringValueField = ResScalarValue.class.getDeclaredField("mRawValue");
+ stringValueField.setAccessible(true);
+ final Field pluralsValueField = ResPluralsValue.class.getDeclaredField("mItems");
+ pluralsValueField.setAccessible(true);
+ final Field pluralsQuantityField = ResPluralsValue.class.getDeclaredField("QUANTITY_MAP");
+ pluralsQuantityField.setAccessible(true);
+ final String[] pluralsQuantities = (String[]) pluralsQuantityField.get(String[].class);
generator.writeStartObject();
- for (ResResource resource : input.listResources()) {
- if (input.isSynthesized(resource)) {
+ for (ResResource resource : stringValues.listResources()) {
+ if (stringValues.isSynthesized(resource)) {
continue;
}
final String name = resource.getResSpec().getName();
// Get the value field from the ResStringValue object.
- final String value = (String) valueField.get(resource.getValue());
+ final String value = (String) stringValueField.get(resource.getValue());
generator.writeStringField(name, value);
}
+
+ if (pluralsValues != null)
+ {
+ for (ResResource resource : pluralsValues.listResources()) {
+ if (pluralsValues.isSynthesized(resource)) {
+ continue;
+ }
+
+ final String name = resource.getResSpec().getName();
+ generator.writeObjectFieldStart(name);
+ // Get the values field from the ResPluralsValue object.
+ ResScalarValue[] valuesArray = (ResScalarValue[]) pluralsValueField.get(resource.getValue());
+ for (int i = 0; i < valuesArray.length; i++)
+ {
+ ResScalarValue value = valuesArray[i];
+ if (value != null) {
+ generator.writeStringField(pluralsQuantities[i], value.encodeAsResXmlValue());
+ }
+ }
+ generator.writeEndObject();
+ }
+ }
+
generator.writeEndObject();
generator.flush();
generator.close();
@@ -83,19 +113,27 @@ public static void run(final File input, final File outputDirectory,
final ExtFile apkFile = new ExtFile(input);
ResTable table = res.getResTable(apkFile, true);
ResValuesFile stringsXML = null;
+ ResValuesFile pluralsXML = null;
+ final String stringsTargetPath = (localization + "/strings.xml").toLowerCase();
+ final String pluralsTargetPath = (localization + "/plurals.xml").toLowerCase();
for (ResPackage pkg : table.listMainPackages()) {
p(pkg);
for (ResValuesFile values : pkg.listValuesFiles()) {
// strings.xml is not case sensitive. xamarin will call it Strings.xml
final String path = values.getPath().toLowerCase();
- final String targetPath = (localization + "/strings.xml").toLowerCase();
p(path);
- if (path.endsWith(targetPath)) {
+ if (path.endsWith(stringsTargetPath)) {
stringsXML = values;
+ }
+ if (path.endsWith(pluralsTargetPath)) {
+ pluralsXML = values;
+ }
+ if (stringsXML != null && pluralsXML != null)
+ {
break;
}
}
- if (stringsXML != null) {
+ if (stringsXML != null && pluralsXML != null) {
break;
}
}
@@ -104,7 +142,8 @@ public static void run(final File input, final File outputDirectory,
e("Could not find the strings.xml file for localization: " + localization);
}
- toJSON(stringsXML, outputDirectory);
+ toJSON(stringsXML, pluralsXML, outputDirectory);
+
p("complete");
}