diff --git a/README.md b/README.md
index 2f8e925..3e921c3 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Get apk-parser from maven central repo:
net.dongliu
apk-parser
- 2.5.3
+ 2.6.0
```
From version 2.0, apk-parser requires java7. The last version support java6 is 1.7.4.
diff --git a/pom.xml b/pom.xml
index 43d55ec..28524dc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
apk-parser
apk-parser
jar
- 2.5.3
+ 2.6.0
https://github.com/xiaxiaocao/apk-parser
@@ -141,7 +141,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.5
+ 1.6
sign-artifacts
@@ -149,6 +149,12 @@
sign
+
+
+ --pinentry-mode
+ loopback
+
+
diff --git a/src/main/java/net/dongliu/apk/parser/AbstractApkFile.java b/src/main/java/net/dongliu/apk/parser/AbstractApkFile.java
index fdb7633..aacf64e 100644
--- a/src/main/java/net/dongliu/apk/parser/AbstractApkFile.java
+++ b/src/main/java/net/dongliu/apk/parser/AbstractApkFile.java
@@ -241,9 +241,58 @@ private void transBinaryXml(byte[] data, XmlStreamer xmlStreamer) throws IOExcep
binaryXmlParser.parse();
}
+ /**
+ * This method return icons specified in android manifest file, application.
+ * The icons could be file icon, color icon, or adaptive icon, etc.
+ *
+ * @return icon files.
+ */
+ public List getAllIcons() throws IOException {
+ List iconPaths = getIconPaths();
+ if (iconPaths.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List iconFaces = new ArrayList<>(iconPaths.size());
+ for (IconPath iconPath : iconPaths) {
+ String filePath = iconPath.getPath();
+ if (filePath.endsWith(".xml")) {
+ // adaptive icon?
+ byte[] data = getFileData(filePath);
+ if (data == null) {
+ continue;
+ }
+ parseResourceTable();
+
+ AdaptiveIconParser iconParser = new AdaptiveIconParser();
+ transBinaryXml(data, iconParser);
+ Icon backgroundIcon = null;
+ if (iconParser.getBackground() != null) {
+ backgroundIcon = newFileIcon(iconParser.getBackground(), iconPath.getDensity());
+ }
+ Icon foregroundIcon = null;
+ if (iconParser.getForeground() != null) {
+ foregroundIcon = newFileIcon(iconParser.getForeground(), iconPath.getDensity());
+ }
+ AdaptiveIcon icon = new AdaptiveIcon(backgroundIcon, foregroundIcon);
+ iconFaces.add(icon);
+ } else {
+ Icon icon = newFileIcon(filePath, iconPath.getDensity());
+ iconFaces.add(icon);
+ }
+ }
+ return iconFaces;
+ }
+
+ private Icon newFileIcon(String filePath, int density) throws IOException {
+ return new Icon(filePath, density, getFileData(filePath));
+ }
+
/**
* Get the default apk icon file.
+ *
+ * @deprecated use {@link #getAllIcons()}
*/
+ @Deprecated
public Icon getIconFile() throws IOException {
ApkMeta apkMeta = getApkMeta();
String iconPath = apkMeta.getIcon();
@@ -255,7 +304,10 @@ public Icon getIconFile() throws IOException {
/**
* Get all the icon paths, for different densities.
+ *
+ * @deprecated using {@link #getAllIcons()} instead
*/
+ @Deprecated
public List getIconPaths() throws IOException {
parseManifest();
return this.iconPaths;
@@ -263,12 +315,15 @@ public List getIconPaths() throws IOException {
/**
* Get all the icons, for different densities.
+ *
+ * @deprecated using {@link #getAllIcons()} instead
*/
+ @Deprecated
public List getIconFiles() throws IOException {
List iconPaths = getIconPaths();
List icons = new ArrayList<>(iconPaths.size());
for (IconPath iconPath : iconPaths) {
- Icon icon = new Icon(iconPath.getPath(), iconPath.getDensity(), getFileData(iconPath.getPath()));
+ Icon icon = newFileIcon(iconPath.getPath(), iconPath.getDensity());
icons.add(icon);
}
return icons;
@@ -353,6 +408,9 @@ public void close() throws IOException {
this.iconPaths = null;
}
+ /**
+ * The local used to parse apk
+ */
public Locale getPreferredLocale() {
return preferredLocale;
}
diff --git a/src/main/java/net/dongliu/apk/parser/Main.java b/src/main/java/net/dongliu/apk/parser/Main.java
index d10116b..e8d7326 100644
--- a/src/main/java/net/dongliu/apk/parser/Main.java
+++ b/src/main/java/net/dongliu/apk/parser/Main.java
@@ -1,7 +1,9 @@
package net.dongliu.apk.parser;
+import net.dongliu.apk.parser.bean.IconFace;
+
import java.io.IOException;
-import java.security.cert.CertificateException;
+import java.util.List;
/**
* Main method for parser apk
@@ -9,9 +11,10 @@
* @author Liu Dong {@literal }
*/
public class Main {
- public static void main(String[] args) throws IOException, CertificateException {
+ public static void main(String[] args) throws IOException {
try (ApkFile apkFile = new ApkFile(args[0])) {
- System.out.println(apkFile.getApkSingers().get(0).getCertificateMetas());
+ List allIcons = apkFile.getAllIcons();
+ System.out.println(allIcons);
}
}
}
diff --git a/src/main/java/net/dongliu/apk/parser/bean/AdaptiveIcon.java b/src/main/java/net/dongliu/apk/parser/bean/AdaptiveIcon.java
new file mode 100644
index 0000000..7b258d6
--- /dev/null
+++ b/src/main/java/net/dongliu/apk/parser/bean/AdaptiveIcon.java
@@ -0,0 +1,55 @@
+package net.dongliu.apk.parser.bean;
+
+import java.io.Serializable;
+
+/**
+ * Android adaptive icon, from android 8.0
+ */
+public class AdaptiveIcon implements IconFace, Serializable {
+ private static final long serialVersionUID = 4185750290211529320L;
+ private final Icon foreground;
+ private final Icon background;
+
+ public AdaptiveIcon(Icon foreground, Icon background) {
+ this.foreground = foreground;
+ this.background = background;
+ }
+
+
+ /**
+ * The foreground icon
+ */
+ public Icon getForeground() {
+ return foreground;
+ }
+
+ /**
+ * The background icon
+ */
+ public Icon getBackground() {
+ return background;
+ }
+
+ @Override
+ public String toString() {
+ return "AdaptiveIcon{" +
+ "foreground=" + foreground +
+ ", background=" + background +
+ '}';
+ }
+
+ @Override
+ public boolean isFile() {
+ return foreground.isFile();
+ }
+
+ @Override
+ public byte[] getData() {
+ return foreground.getData();
+ }
+
+ @Override
+ public String getPath() {
+ return foreground.getPath();
+ }
+}
diff --git a/src/main/java/net/dongliu/apk/parser/bean/ApkMeta.java b/src/main/java/net/dongliu/apk/parser/bean/ApkMeta.java
index 033d0b5..6075801 100644
--- a/src/main/java/net/dongliu/apk/parser/bean/ApkMeta.java
+++ b/src/main/java/net/dongliu/apk/parser/bean/ApkMeta.java
@@ -1,5 +1,7 @@
package net.dongliu.apk.parser.bean;
+import net.dongliu.apk.parser.AbstractApkFile;
+
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -92,11 +94,14 @@ public void addUsesPermission(String permission) {
* the icon file path in apk
*
* @return null if not found
+ * @deprecated use {@link AbstractApkFile#getAllIcons()} instead.
*/
+ @Deprecated
public String getIcon() {
return icon;
}
+ @Deprecated
public void setIcon(String icon) {
this.icon = icon;
}
diff --git a/src/main/java/net/dongliu/apk/parser/bean/ColorIcon.java b/src/main/java/net/dongliu/apk/parser/bean/ColorIcon.java
new file mode 100644
index 0000000..a963588
--- /dev/null
+++ b/src/main/java/net/dongliu/apk/parser/bean/ColorIcon.java
@@ -0,0 +1,27 @@
+package net.dongliu.apk.parser.bean;
+
+import java.io.Serializable;
+
+/**
+ * The plain icon, using color drawable resource.
+ */
+//to be implemented
+public class ColorIcon implements IconFace, Serializable {
+ private static final long serialVersionUID = -7913024425268466186L;
+
+ @Override
+ public boolean isFile() {
+ return false;
+ }
+
+ @Override
+ public byte[] getData() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getPath() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/net/dongliu/apk/parser/bean/Icon.java b/src/main/java/net/dongliu/apk/parser/bean/Icon.java
index 0bb6e5b..41399d2 100644
--- a/src/main/java/net/dongliu/apk/parser/bean/Icon.java
+++ b/src/main/java/net/dongliu/apk/parser/bean/Icon.java
@@ -1,16 +1,18 @@
package net.dongliu.apk.parser.bean;
import javax.annotation.Nullable;
+import java.io.Serializable;
/**
- * The apk icon file path, and data
+ * The plain file apk icon.
*
* @author Liu Dong
*/
-public class Icon {
+public class Icon implements IconFace, Serializable {
+ private static final long serialVersionUID = 8680309892249769701L;
private final String path;
- private int density;
+ private final int density;
private final byte[] data;
public Icon(String path, int density, byte[] data) {
@@ -34,6 +36,11 @@ public int getDensity() {
return density;
}
+ @Override
+ public boolean isFile() {
+ return true;
+ }
+
/**
* Icon data may be null, due to some apk missing the icon file.
*/
diff --git a/src/main/java/net/dongliu/apk/parser/bean/IconFace.java b/src/main/java/net/dongliu/apk/parser/bean/IconFace.java
new file mode 100644
index 0000000..454a34c
--- /dev/null
+++ b/src/main/java/net/dongliu/apk/parser/bean/IconFace.java
@@ -0,0 +1,27 @@
+package net.dongliu.apk.parser.bean;
+
+import java.io.Serializable;
+
+/**
+ * The icon interface
+ */
+public interface IconFace extends Serializable {
+
+ /**
+ * If icon is file resource
+ */
+ boolean isFile();
+
+ /**
+ * Return the icon file as bytes. This method is valid only when {@link #isFile()} return true.
+ * Otherwise, {@link UnsupportedOperationException} should be thrown.
+ */
+ byte[] getData();
+
+
+ /**
+ * Return the icon file path in apk file. This method is valid only when {@link #isFile()} return true.
+ * Otherwise, {@link UnsupportedOperationException} should be thrown.
+ */
+ String getPath();
+}
diff --git a/src/main/java/net/dongliu/apk/parser/parser/AdaptiveIconParser.java b/src/main/java/net/dongliu/apk/parser/parser/AdaptiveIconParser.java
new file mode 100644
index 0000000..32ef7fa
--- /dev/null
+++ b/src/main/java/net/dongliu/apk/parser/parser/AdaptiveIconParser.java
@@ -0,0 +1,61 @@
+package net.dongliu.apk.parser.parser;
+
+import net.dongliu.apk.parser.struct.xml.*;
+
+/**
+ * Parse adaptive icon xml file.
+ *
+ * @author Liu Dong dongliu@live.cn
+ */
+public class AdaptiveIconParser implements XmlStreamer {
+
+ private String foreground;
+ private String background;
+
+ public String getForeground() {
+ return foreground;
+ }
+
+ public String getBackground() {
+ return background;
+ }
+
+ @Override
+ public void onStartTag(XmlNodeStartTag xmlNodeStartTag) {
+ if (xmlNodeStartTag.getName().equals("background")) {
+ background = getDrawable(xmlNodeStartTag);
+ } else if (xmlNodeStartTag.getName().equals("foreground")) {
+ foreground = getDrawable(xmlNodeStartTag);
+ }
+ }
+
+ private String getDrawable(XmlNodeStartTag xmlNodeStartTag) {
+ Attributes attributes = xmlNodeStartTag.getAttributes();
+ for (Attribute attribute : attributes.values()) {
+ if (attribute.getName().equals("drawable")) {
+ return attribute.getValue();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onEndTag(XmlNodeEndTag xmlNodeEndTag) {
+
+ }
+
+ @Override
+ public void onCData(XmlCData xmlCData) {
+
+ }
+
+ @Override
+ public void onNamespaceStart(XmlNamespaceStartTag tag) {
+
+ }
+
+ @Override
+ public void onNamespaceEnd(XmlNamespaceEndTag tag) {
+
+ }
+}