133 lines
4.9 KiB
C#
133 lines
4.9 KiB
C#
|
|
using System;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace CompanyManagment.Application.Helpers
|
|
{
|
|
public class ApkInfo
|
|
{
|
|
public string VersionName { get; set; } = string.Empty;
|
|
public string VersionCode { get; set; } = string.Empty;
|
|
public string PackageName { get; set; } = string.Empty;
|
|
public string ApplicationLabel { get; set; } = string.Empty;
|
|
}
|
|
|
|
public static class ApkHelper
|
|
{
|
|
public static ApkInfo ReadApkInfo(Stream apkStream)
|
|
{
|
|
var apkInfo = new ApkInfo();
|
|
|
|
try
|
|
{
|
|
using var archive = new ZipArchive(apkStream, ZipArchiveMode.Read, true);
|
|
var manifestEntry = archive.GetEntry("AndroidManifest.xml");
|
|
|
|
if (manifestEntry == null)
|
|
{
|
|
throw new InvalidOperationException("AndroidManifest.xml not found in APK file");
|
|
}
|
|
|
|
using var manifestStream = manifestEntry.Open();
|
|
using var memoryStream = new MemoryStream();
|
|
manifestStream.CopyTo(memoryStream);
|
|
var manifestBytes = memoryStream.ToArray();
|
|
|
|
// Parse the binary AndroidManifest.xml
|
|
apkInfo = ParseBinaryManifest(manifestBytes);
|
|
|
|
// Validate that we found at least version information
|
|
if (string.IsNullOrEmpty(apkInfo.VersionCode) && string.IsNullOrEmpty(apkInfo.VersionName))
|
|
{
|
|
throw new InvalidOperationException("Could not extract version information from APK");
|
|
}
|
|
|
|
return apkInfo;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InvalidOperationException($"Error reading APK file: {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
private static ApkInfo ParseBinaryManifest(byte[] manifestBytes)
|
|
{
|
|
var apkInfo = new ApkInfo();
|
|
|
|
try
|
|
{
|
|
// Convert bytes to string for regex parsing
|
|
var text = System.Text.Encoding.UTF8.GetString(manifestBytes);
|
|
|
|
// Extract package name
|
|
var packageMatch = Regex.Match(text, @"package[^a-zA-Z]+([a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)+)", RegexOptions.IgnoreCase);
|
|
if (packageMatch.Success)
|
|
{
|
|
apkInfo.PackageName = packageMatch.Groups[1].Value;
|
|
}
|
|
|
|
// Extract version code - look for numeric values that could be version codes
|
|
var versionCodeMatch = Regex.Match(text, @"versionCode[^\d]*(\d+)", RegexOptions.IgnoreCase);
|
|
if (versionCodeMatch.Success)
|
|
{
|
|
apkInfo.VersionCode = versionCodeMatch.Groups[1].Value;
|
|
}
|
|
else
|
|
{
|
|
// Fallback: try to find reasonable numeric values
|
|
var numbers = Regex.Matches(text, @"\b(\d{1,8})\b");
|
|
foreach (Match numMatch in numbers)
|
|
{
|
|
if (int.TryParse(numMatch.Groups[1].Value, out int num) && num > 0 && num < 99999999)
|
|
{
|
|
apkInfo.VersionCode = num.ToString();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Extract version name
|
|
var versionNameMatch = Regex.Match(text, @"versionName[^\d]*(\d+(?:\.\d+)*(?:\.\d+)*)", RegexOptions.IgnoreCase);
|
|
if (versionNameMatch.Success)
|
|
{
|
|
apkInfo.VersionName = versionNameMatch.Groups[1].Value;
|
|
}
|
|
else
|
|
{
|
|
// Fallback: look for version-like patterns
|
|
var versionMatch = Regex.Match(text, @"\b(\d+\.\d+(?:\.\d+)*)\b");
|
|
if (versionMatch.Success)
|
|
{
|
|
apkInfo.VersionName = versionMatch.Groups[1].Value;
|
|
}
|
|
}
|
|
|
|
// Set defaults if nothing found
|
|
if (string.IsNullOrEmpty(apkInfo.VersionCode))
|
|
apkInfo.VersionCode = "1";
|
|
|
|
if (string.IsNullOrEmpty(apkInfo.VersionName))
|
|
apkInfo.VersionName = "1.0";
|
|
|
|
if (string.IsNullOrEmpty(apkInfo.PackageName))
|
|
apkInfo.PackageName = "unknown.package";
|
|
|
|
return apkInfo;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// Return default values if parsing fails
|
|
return new ApkInfo
|
|
{
|
|
VersionCode = "1",
|
|
VersionName = "1.0",
|
|
PackageName = "unknown.package"
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|