Add support for Android App Bundle (.aab) files
Some checks are pending
MSBuild / build (push) Waiting to run
MSBuild / publish (push) Blocked by required conditions

This commit is contained in:
ema
2025-06-27 07:29:38 +08:00
parent 6943ed5cb4
commit 12046220c1
6 changed files with 184 additions and 23 deletions

View File

@@ -20,6 +20,7 @@ using QuickLook.Common.Helpers;
using QuickLook.Common.Plugin; using QuickLook.Common.Plugin;
using QuickLook.Plugin.AppViewer.PackageParsers.Apk; using QuickLook.Plugin.AppViewer.PackageParsers.Apk;
using System; using System;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
@@ -63,32 +64,45 @@ public partial class ApkInfoPanel : UserControl, IAppInfoPanel
if (File.Exists(path)) if (File.Exists(path))
{ {
var size = new FileInfo(path).Length; var size = new FileInfo(path).Length;
ApkInfo apkInfo = ApkParser.Parse(path); IApkInfo info = Path.GetExtension(path).ToLower() switch
{
".apk" => ApkParser.Parse(path),
".aab" => AabParser.Parse(path),
_ => throw new NotSupportedException("Extension is not supported."),
};
var last = File.GetLastWriteTime(path); var last = File.GetLastWriteTime(path);
Dispatcher.Invoke(() => Dispatcher.Invoke(() =>
{ {
applicationName.Text = apkInfo.Label; applicationName.Text = info.Label;
versionName.Text = apkInfo.VersionName; versionName.Text = info.VersionName;
versionCode.Text = apkInfo.VersionCode; versionCode.Text = info.VersionCode;
abis.Text = string.Join(", ", apkInfo.ABIs ?? []); abis.Text = string.Join(", ", info.ABIs ?? []);
packageName.Text = apkInfo.PackageName; packageName.Text = info.PackageName;
minSdkVersion.Text = apkInfo.MinSdkVersion; minSdkVersion.Text = info.MinSdkVersion;
targetSdkVersion.Text = apkInfo.TargetSdkVersion; targetSdkVersion.Text = info.TargetSdkVersion;
totalSize.Text = size.ToPrettySize(2); totalSize.Text = size.ToPrettySize(2);
modDate.Text = last.ToString(CultureInfo.CurrentCulture); modDate.Text = last.ToString(CultureInfo.CurrentCulture);
permissions.ItemsSource = apkInfo.Permissions; permissions.ItemsSource = info.Permissions;
if (apkInfo.HasIcon) if (info.HasIcon)
{ {
using var stream = new MemoryStream(apkInfo.Logo); try
var icon = new BitmapImage(); {
icon.BeginInit(); using var stream = new MemoryStream(info.Logo);
icon.CacheOption = BitmapCacheOption.OnLoad; var icon = new BitmapImage();
icon.StreamSource = stream; icon.BeginInit();
icon.EndInit(); icon.CacheOption = BitmapCacheOption.OnLoad;
icon.Freeze(); icon.StreamSource = stream;
image.Source = icon; icon.EndInit();
icon.Freeze();
image.Source = icon;
}
catch (Exception e)
{
Debug.WriteLine(e);
image.Source = new BitmapImage(new Uri("pack://application:,,,/QuickLook.Plugin.AppViewer;component/Resources/android.png"));
}
} }
else else
{ {

View File

@@ -0,0 +1,20 @@
// Copyright © 2017-2025 QL-Win Contributors
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace QuickLook.Plugin.AppViewer.PackageParsers.Apk;
public class AabInfo : ApkInfo;

View File

@@ -0,0 +1,72 @@
// Copyright © 2017-2025 QL-Win Contributors
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace QuickLook.Plugin.AppViewer.PackageParsers.Apk;
public static class AabParser
{
public static AabInfo Parse(string path)
{
try
{
using var zip = new ZipFile(path);
var aabReader = new ApkReader.AabReader();
ApkReader.AabInfo baseInfo = aabReader.Read(path);
AabInfo info = new()
{
VersionName = baseInfo.VersionName,
VersionCode = baseInfo.VersionCode,
TargetSdkVersion = ApiLevel.Create(baseInfo.TargetSdkVersion).ToString(),
Permissions = baseInfo.Permissions,
PackageName = baseInfo.PackageName,
MinSdkVersion = ApiLevel.Create(baseInfo.MinSdkVersion).ToString(),
Icon = baseInfo.Icon,
Icons = baseInfo.Icons,
Label = baseInfo.Label,
Labels = baseInfo.Labels,
Locales = baseInfo.Locales,
Densities = baseInfo.Densities,
ABIs = [.. baseInfo.Abis],
LaunchableActivity = baseInfo.LaunchableActivity,
};
if (baseInfo.HasIcon)
{
ZipEntry entry = zip.GetEntry(baseInfo.Icons.Values
.Where(icon => icon.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
.LastOrDefault());
using var s = new BinaryReader(zip.GetInputStream(entry));
info.Logo = s.ReadBytes((int)entry.Size);
}
return info;
}
catch (Exception e)
{
Debug.WriteLine(e);
}
return new AabInfo();
}
}

View File

@@ -19,7 +19,7 @@ using System.Collections.Generic;
namespace QuickLook.Plugin.AppViewer.PackageParsers.Apk; namespace QuickLook.Plugin.AppViewer.PackageParsers.Apk;
public class ApkInfo public class ApkInfo : IApkInfo
{ {
public string VersionName { get; set; } public string VersionName { get; set; }

View File

@@ -0,0 +1,55 @@
// Copyright © 2017-2025 QL-Win Contributors
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System.Collections.Generic;
namespace QuickLook.Plugin.AppViewer.PackageParsers.Apk;
public interface IApkInfo
{
public string VersionName { get; set; }
public string VersionCode { get; set; }
public string TargetSdkVersion { get; set; }
public List<string> Permissions { get; set; }
public string PackageName { get; set; }
public string MinSdkVersion { get; set; }
public string Icon { get; set; }
public Dictionary<string, string> Icons { get; set; }
public byte[] Logo { get; set; }
public string Label { get; set; }
public Dictionary<string, string> Labels { get; set; }
public bool HasIcon { get; }
public List<string> Locales { get; set; }
public List<string> Densities { get; set; }
public string LaunchableActivity { get; set; }
public string[] ABIs { get; set; }
}

View File

@@ -30,8 +30,8 @@ public class Plugin : IViewer
[ [
// Android // Android
".apk", ".apk.1", // Android Package ".apk", ".apk.1", // Android Package
".aab", // Android App Bundle
//".aar", // Android Archive //".aar", // Android Archive
//".aab", // Android App Bundle
// Windows // Windows
".appx", ".appxbundle", // Windows APPX installer ".appx", ".appxbundle", // Windows APPX installer
@@ -51,7 +51,7 @@ public class Plugin : IViewer
// Ubuntu // Ubuntu
".deb", // Debian Package ".deb", // Debian Package
".appimage", // AppImage Format ".appimage", // AppImage Format
".rpm", // Red Hat Package Manager ".rpm", // Red Hat Package Manager
// Others // Others
".wgt", ".wgtu", // UniApp Widget ".wgt", ".wgtu", // UniApp Widget
@@ -75,7 +75,7 @@ public class Plugin : IViewer
{ {
context.PreferredSize = Path.GetExtension(ConfirmPath(path)).ToLower() switch context.PreferredSize = Path.GetExtension(ConfirmPath(path)).ToLower() switch
{ {
".apk" => new Size { Width = 600, Height = 510 }, ".apk" or ".aab" => new Size { Width = 600, Height = 510 },
".ipa" => new Size { Width = 560, Height = 510 }, ".ipa" => new Size { Width = 560, Height = 510 },
".hap" => new Size { Width = 560, Height = 500 }, ".hap" => new Size { Width = 560, Height = 500 },
".msi" => new Size { Width = 560, Height = 230 }, ".msi" => new Size { Width = 560, Height = 230 },
@@ -99,7 +99,7 @@ public class Plugin : IViewer
_path = path; _path = path;
_ip = Path.GetExtension(ConfirmPath(path)).ToLower() switch _ip = Path.GetExtension(ConfirmPath(path)).ToLower() switch
{ {
".apk" => new ApkInfoPanel(context), ".apk" or ".aab" => new ApkInfoPanel(context),
".ipa" => new IpaInfoPanel(context), ".ipa" => new IpaInfoPanel(context),
".hap" => new HapInfoPanel(context), ".hap" => new HapInfoPanel(context),
".msi" => new MsiInfoPanel(context), ".msi" => new MsiInfoPanel(context),