Skip to content

Commit ea2c925

Browse files
committed
Support more Android package info
1 parent 7ff5b66 commit ea2c925

File tree

4 files changed

+132
-68
lines changed

4 files changed

+132
-68
lines changed

AAPTForNet/ApkExtractor.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ public static ApkInfo ExtractIcon(DumpModel model, ApkInfo apk) {
1515

1616
using(var archive = ZipFile.OpenRead(model.FilePath)) {
1717
ZipArchiveEntry entry;
18-
int max = archive.Entries.Count - 1;
18+
int i = archive.Entries.Count - 1;
1919

2020
// Loop from bottom of the collection.
2121
// The largest icon is usually position at the end of package
2222
// (sorting by alphabet)
23-
for(int i = max; i > 0; i--) {
23+
for(; i > 0; i--) {
2424
entry = archive.Entries[i];
2525

2626
if(entry.Name.Equals(apk.IconName)) {
@@ -34,14 +34,9 @@ public static ApkInfo ExtractIcon(DumpModel model, ApkInfo apk) {
3434
}
3535
}
3636

37-
return new ApkInfo(
38-
model.FilePath,
39-
apk.AppName,
40-
apk.PackageName,
41-
apk.Version,
42-
apk.MinSDK,
43-
hasIcon ? iconName : string.Empty
44-
);
37+
apk.IconName = hasIcon ? iconName : string.Empty;
38+
39+
return apk;
4540
}
4641
}
4742
}

AAPTForNet/ApkParser.cs

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,91 @@
22

33
namespace AAPTForNet {
44
/// <summary>
5-
/// Parse all messages from AAPTool
5+
/// Parse output messages from AAPTool
66
/// </summary>
77
internal class ApkParser {
88

9-
private static readonly string SDKPattern = @"sdkVersion:'[0-9]{0,1}[^']";
10-
private static readonly string IconPattern = @"icon='[\w-.\\\/]*[^']";
11-
private static readonly string AppNamePattern = @"label='[\w-.() \\\/\[\]]*[^']";
12-
private static readonly string PackagePattern = @"name='[\w.]*[^']";
13-
private static readonly string VersionPattern = @"versionName='[\w-.() \/]*[^']";
149
protected ApkParser() { }
1510

1611
public static ApkInfo Parse(DumpModel model) {
17-
if(!model.isSuccess)
18-
return new ApkInfo("", string.Join("\n", model.Messages), "", "", SDKInfo.Unknown, "");
12+
if (!model.isSuccess)
13+
return ApkInfo.Empty;
1914

20-
// Extract info from apk
21-
string name = "", package = "", ver = "", sdk = "", icon = "";
15+
var permissions = new System.Collections.Generic.List<string>();
16+
var supportScrs = new System.Collections.Generic.List<string>();
17+
18+
string ver = string.Empty,
19+
minSDK = string.Empty,
20+
targetSDK = string.Empty,
21+
icon = string.Empty,
22+
name = string.Empty,
23+
per = string.Empty,
24+
package = string.Empty;
25+
2226

2327
foreach(string msg in model.Messages) {
2428
if(msg.StartsWith("application:")) {
25-
icon = splitValueFromString(msg, IconPattern);
26-
name = splitValueFromString(msg, AppNamePattern);
29+
icon = splitValueFromString(msg, @"icon='[\w-.\\\/]*[^']");
30+
name = splitValueFromString(msg, @"label='[\w-.() \\\/\[\]]*[^']");
31+
continue;
32+
}
33+
34+
if (msg.StartsWith("package:")) {
35+
ver = splitValueFromString(msg, @"versionName='[\w-.() \/]*[^']");
36+
package = splitValueFromString(msg, @"name='[\w.]*[^']");
37+
continue;
2738
}
28-
else if(msg.StartsWith("package:")) {
29-
ver = splitValueFromString(msg, VersionPattern);
30-
package = splitValueFromString(msg, PackagePattern);
39+
40+
if (msg.StartsWith("sdkVersion:")) {
41+
minSDK = splitValueFromString(msg, @"sdkVersion:'[0-9]{0,1}[^']");
42+
continue;
3143
}
32-
else if(msg.StartsWith("sdkVersion:")) {
33-
sdk = splitValueFromString(msg, SDKPattern);
44+
45+
if (msg.StartsWith("targetSdkVersion:")) {
46+
targetSDK = splitValueFromString(msg, @"targetSdkVersion:'[0-9]{0,1}[^']");
47+
continue;
48+
}
49+
50+
if (msg.StartsWith("uses-permission:")) {
51+
per = splitValueFromString(msg, @"'([A-Z0-9._])*");
52+
permissions.Add(per);
53+
continue;
54+
}
55+
56+
if (msg.StartsWith("supports-screens:")) {
57+
if (msg.Contains(ApkInfo.SmallScreen)) {
58+
supportScrs.Add(ApkInfo.SmallScreen);
59+
}
60+
if (msg.Contains(ApkInfo.NormalScreen)) {
61+
supportScrs.Add(ApkInfo.NormalScreen);
62+
}
63+
if (msg.Contains(ApkInfo.LargeScreen)) {
64+
supportScrs.Add(ApkInfo.LargeScreen);
65+
}
66+
if (msg.Contains(ApkInfo.xLargeScreen)) {
67+
supportScrs.Add(ApkInfo.xLargeScreen);
68+
}
69+
continue;
3470
}
35-
else continue;
3671
}
3772

38-
return new ApkInfo(model.FilePath, name, package, ver, SDKInfo.GetInfo(sdk), icon);
73+
return new ApkInfo() {
74+
FullPath = model.FilePath,
75+
AppName = name,
76+
PackageName = package,
77+
Version = ver,
78+
MinSDK = SDKInfo.GetInfo(minSDK),
79+
TargetSDK = SDKInfo.GetInfo(targetSDK),
80+
IconName = icon,
81+
Permissions = permissions,
82+
SupportScreens = supportScrs
83+
};
3984
}
4085

4186
private static string splitValueFromString(string source, string pattern) {
42-
string temp = Regex.Match(source, pattern).Value;
87+
string temp = Regex.Match(source, pattern, RegexOptions.IgnoreCase).Value;
4388
return temp.Substring(temp.IndexOf("'") + 1);
4489
}
4590
}
4691
}
92+

AAPTForNet/Models/ApkInfo.cs

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,73 @@
1-
using System.IO;
1+
using System.Collections.Generic;
2+
using System.IO;
23

34
namespace AAPTForNet {
45
public class ApkInfo {
5-
private readonly string unknownInfo = "<Empty>";
6-
private readonly string defaultIconName = "ic_launcher.png";
76

8-
private string _name;
9-
private string _package;
10-
private string _ver;
11-
private string _icon;
7+
private static readonly string unknownInfo = "<Empty>";
8+
// Default icon name generated by Android Studio
9+
private static readonly string defaultIconName = "ic_launcher.png";
10+
11+
private string _iconName = defaultIconName;
12+
13+
public static readonly string SmallScreen = "small";
14+
public static readonly string NormalScreen = "normal";
15+
public static readonly string LargeScreen = "large";
16+
public static readonly string xLargeScreen = "xlarge";
1217

1318
public static readonly ApkInfo Empty = new ApkInfo();
1419

15-
public string AppName => _name.Length > 0 ? _name : unknownInfo;
16-
public string PackageName => _package.Length > 0 ? _package : unknownInfo;
17-
public string Version => _ver.Length > 0 ? _ver : unknownInfo;
18-
public SDKInfo MinSDK { get; }
19-
public string IconName => _icon.Length > 4 ? _icon : defaultIconName;
20-
public string FullPath { get; }
21-
public long PackageSize => File.Exists(FullPath) ?
22-
new FileInfo(FullPath).Length : 0;
23-
public string IconPath => (IconName != string.Empty && IconName != defaultIconName) ?
24-
AAPTool.TempPath + @"\" + IconName : string.Empty;
25-
public bool isEmpty { get; }
20+
public string AppName { get; set; }
21+
public string PackageName { get; set; }
22+
public string Version { get; set; }
23+
public string FullPath { get; set; }
24+
public SDKInfo MinSDK { get; set; }
25+
public SDKInfo TargetSDK { get; set; }
26+
public List<string> Permissions { get; set; }
27+
public List<string> SupportScreens { get; set; }
28+
29+
public string IconName {
30+
// IconName include name and extension
31+
get => _iconName.Length > 3 ? _iconName : defaultIconName;
32+
set {
33+
if (value == string.Empty || value.ToLower().EndsWith(".xml"))
34+
// Exclude markup icon only. Many packages do not use .png icon
35+
_iconName = defaultIconName;
36+
else
37+
_iconName = Path.GetFileName(value);
38+
}
39+
}
40+
public string IconPath {
41+
get {
42+
if (IconName == defaultIconName) return string.Empty;
2643

27-
internal ApkInfo() {
28-
isEmpty = true;
29-
MinSDK = SDKInfo.Unknown;
30-
_icon = FullPath = string.Empty;
31-
_ver = _package = _name = unknownInfo;
44+
return AAPTool.TempPath + @"\" + IconName;
45+
}
3246
}
47+
public long PackageSize {
48+
get {
49+
if (!File.Exists(FullPath))
50+
return 0;
3351

34-
internal ApkInfo(string path, string name, string package, string ver, SDKInfo sdk, string iconName) {
35-
this.isEmpty = false;
36-
this.MinSDK = sdk;
37-
this.FullPath = path;
38-
this._name = name;
39-
this._package = package;
40-
this._ver = ver;
41-
this._icon = iconName.Length > 4 ? // Include name and extension
42-
Path.GetFileNameWithoutExtension(iconName) + ".png" : defaultIconName;
52+
return new FileInfo(FullPath).Length;
53+
}
54+
}
55+
public bool IsEmpty {
56+
get {
57+
return (AppName == string.Empty || AppName == unknownInfo) &&
58+
(PackageName == string.Empty || PackageName == unknownInfo);
59+
}
4360
}
4461

45-
public override string ToString() {
46-
return string.Format("Name: {0};\nPackage: {1};\nVer: {2};\nMinSDK: {3};\nIcon: {4}\n",
47-
this.AppName, this.PackageName, this.Version, this.MinSDK.ToString(), this.IconPath);
62+
internal ApkInfo() {
63+
AppName = unknownInfo;
64+
PackageName = unknownInfo;
65+
Version = unknownInfo;
66+
FullPath = string.Empty;
67+
MinSDK = SDKInfo.Unknown;
68+
TargetSDK = SDKInfo.Unknown;
69+
Permissions = new List<string>();
70+
SupportScreens = new List<string>();
4871
}
4972
}
5073
}

Plugin.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class Plugin : IViewer {
1212

1313
public void Prepare(string path, ContextObject context) {
1414
context.Theme = Themes.Dark;
15-
context.PreferredSize = new Size { Width = 650, Height = 200 };
15+
context.PreferredSize = new Size { Width = 750, Height = 350 };
1616
context.Title = path;
1717
context.TitlebarOverlap = false;
1818
context.TitlebarBlurVisibility = false;
@@ -22,9 +22,9 @@ public void Prepare(string path, ContextObject context) {
2222

2323
public void View(string path, ContextObject context) {
2424
var apk = AAPTool.Decompile(path);
25-
if (apk.isEmpty) {
25+
if (apk.IsEmpty) {
2626
context.ViewerContent = new System.Windows.Controls.Label() {
27-
Content = "Can't not load package. Please change the file name and try again.",
27+
Content = "Can't not load package.",
2828
Foreground = System.Windows.Media.Brushes.White,
2929
FontSize = 16,
3030
VerticalAlignment = VerticalAlignment.Center,

0 commit comments

Comments
 (0)