.net core 从(本地)服务器获取APK文件并解析APK信息

简介: ## 1、apk解析除了使用客户端利用aapt.exe、unzip.exe开发客户端解析外,还可以直接利用服务进行解析```csharp/// <summary>/// 从本地服务器获取APK文件并解析APK信息/// </summary>/// <param name="fileName">APK文件的完整路径</param>/// <returns></returns>[HttpPost, HttpGet, HttpOptions, CorsOptions]public IActionResult DecodeAPK(string fileName){ if(fi

1、apk解析除了使用客户端利用aapt.exe、unzip.exe开发客户端解析外,还可以直接利用服务进行解析

/// <summary>
/// 从本地服务器获取APK文件并解析APK信息
/// </summary>
/// <param name="fileName">APK文件的完整路径</param>
/// <returns></returns>
[HttpPost, HttpGet, HttpOptions, CorsOptions]
public IActionResult DecodeAPK(string fileName)
{
   
   
    if(fileName.IndexOf(".apk") == -1 && fileName.IndexOf(".zip") == -1)
    {
   
   
        return ErrorResult("未获取到APP上传路径!", 111111);
    }
    // 从服务器取文件
    if(!string.IsNullOrWhiteSpace(fileName))
    {
   
   
        fileName = fileName.Replace(@"\", @" / ");
        ApkInfo apk = new ApkInfo();
        // 处理apk信息
        try
            apk = ReadAPK.ReadApkFromPath(fileName);
        catch(Exception ex)
            return ErrorResult("APP上传失败!--> APK解析失败,失败原因为:" + ex.Message, 111150);
        return SuccessResult(apk, "APK解析成功");
    }
    else
        return ErrorResult("APP上传失败!--> 从服务器获取APK文件失败,请联系网站管理员!", 111151);
}

2、ReadAPK APK解析帮助类

/// <summary>
/// 读取APK信息
/// </summary>
public class ReadAPK
{
   
   
    /// <summary>
    /// 从上传apk的路径读取并解析apk信息
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static ApkInfo ReadApkFromPath(string path)
    {
   
   
        byte[] manifestData = null;
        byte[] resourcesData = null;
        var manifest = "AndroidManifest.xml";
        var resources = "resources.arsc";
        //读取apk,通过解压的方式读取
        using(var zip = ZipFile.Read(path))
        {
   
   
            using(Stream zipstream = zip[manifest].OpenReader())
            {
   
   
                //将解压出来的文件保存到一个路径(必须这样)
                using(var fileStream = File.Create(manifest, (int) zipstream.Length))
                {
   
   
                    manifestData = new byte[zipstream.Length];
                    zipstream.Read(manifestData, 0, manifestData.Length);
                    fileStream.Write(manifestData, 0, manifestData.Length);
                }
            }
            using(Stream zipstream = zip[resources].OpenReader())
            {
   
   
                //将解压出来的文件保存到一个路径(必须这样)
                using(var fileStream = File.Create(resources, (int) zipstream.Length))
                {
   
   
                    resourcesData = new byte[zipstream.Length];
                    zipstream.Read(resourcesData, 0, resourcesData.Length);
                    fileStream.Write(resourcesData, 0, resourcesData.Length);
                }
            }
        }
        ApkReader apkReader = new ApkReader();
        ApkInfo info = apkReader.extractInfo(manifestData, resourcesData);
        return info;
    }
}

3、APK解析类

注:此段代码解析APK时,若APK包含中文会极其的卡顿,建议上传前先用Npinyin重命名再次上传,至于原因已提交GitHub,暂未得到回复,所以先自己重命名再上传吧
Wrong Local header signature: 0xFF8
image.png

public class ApkReader
{
   
   
    private static int VER_ID = 0;
    private static int ICN_ID = 1;
    private static int LABEL_ID = 2;
    String[] VER_ICN = new String[3];
    String[] TAGS = {
   
   
        "manifest", "application", "activity"
    };
    String[] ATTRS = {
   
   
        "android:", "a:", "activity:", "_:"
    };
    Dictionary < String, object > entryList = new Dictionary < String, object > ();
    List < String > tmpFiles = new List < String > ();
    public String fuzzFindInDocument(XmlDocument doc, String tag, String attr)
    {
   
   
        foreach(String t in TAGS)
        {
   
   
            XmlNodeList nodelist = doc.GetElementsByTagName(t);
            for(int i = 0; i < nodelist.Count; i++)
            {
   
   
                XmlNode element = (XmlNode) nodelist.Item(i);
                if(element.NodeType == XmlNodeType.Element)
                {
   
   
                    XmlAttributeCollection map = element.Attributes;
                    for(int j = 0; j < map.Count; j++)
                    {
   
   
                        XmlNode element2 = map.Item(j);
                        if(element2.Name.EndsWith(attr))
                        {
   
   
                            return element2.Value;
                        }
                    }
                }
            }
        }
        return null;
    }
    private XmlDocument initDoc(String xml)
    {
   
   
        XmlDocument retval = new XmlDocument();
        retval.LoadXml(xml);
        retval.DocumentElement.Normalize();
        return retval;
    }
    private void extractPermissions(ApkInfo info, XmlDocument doc)
    {
   
   
        ExtractPermission(info, doc, "uses-permission", "name");
        ExtractPermission(info, doc, "permission-group", "name");
        ExtractPermission(info, doc, "service", "permission");
        ExtractPermission(info, doc, "provider", "permission");
        ExtractPermission(info, doc, "activity", "permission");
    }
    private bool readBoolean(XmlDocument doc, String tag, String attribute)
    {
   
   
        String str = FindInDocument(doc, tag, attribute);
        bool ret = false;
        try
        {
   
   
            ret = Convert.ToBoolean(str);
        }
        catch
        {
   
   
            ret = false;
        }
        return ret;
    }
    private void extractSupportScreens(ApkInfo info, XmlDocument doc)
    {
   
   
        info.supportSmallScreens = readBoolean(doc, "supports-screens", "android:smallScreens");
        info.supportNormalScreens = readBoolean(doc, "supports-screens", "android:normalScreens");
        info.supportLargeScreens = readBoolean(doc, "supports-screens", "android:largeScreens");
        if(info.supportSmallScreens || info.supportNormalScreens || info.supportLargeScreens) info.supportAnyDensity = false;
    }
    public ApkInfo extractInfo(byte[] manifest_xml, byte[] resources_arsx)
    {
   
   
        string manifestXml = string.Empty;
        APKManifest manifest = new APKManifest();
        try
        {
   
   
            manifestXml = manifest.ReadManifestFileIntoXml(manifest_xml);
        }
        catch(Exception ex)
        {
   
   
            throw ex;
        }
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(manifestXml);
        return extractInfo(doc, resources_arsx);
    }
    public ApkInfo extractInfo(XmlDocument manifestXml, byte[] resources_arsx)
    {
   
   
        ApkInfo info = new ApkInfo();
        VER_ICN[VER_ID] = "";
        VER_ICN[ICN_ID] = "";
        VER_ICN[LABEL_ID] = "";
        try
        {
   
   
            XmlDocument doc = manifestXml;
            if(doc == null) throw new Exception("Document initialize failed");
            info.resourcesFileName = "resources.arsx";
            info.resourcesFileBytes = resources_arsx;
            // Fill up the permission field  不需要返回,注释
            //extractPermissions(info, doc);
            // Fill up some basic fields
            info.minSdkVersion = FindInDocument(doc, "uses-sdk", "minSdkVersion");
            info.targetSdkVersion = FindInDocument(doc, "uses-sdk", "targetSdkVersion");
            info.versionCode = FindInDocument(doc, "manifest", "versionCode");
            info.versionName = FindInDocument(doc, "manifest", "versionName");
            info.packageName = FindInDocument(doc, "manifest", "package");
            int labelID;
            info.label = FindInDocument(doc, "application", "label");
            if(info.label.StartsWith("@")) VER_ICN[LABEL_ID] = info.label;
            else if(int.TryParse(info.label, out labelID)) VER_ICN[LABEL_ID] = String.Format("@{
   
   0}", labelID.ToString("X4"));
            // Fill up the support screen field  不需要返回,注释
            //extractSupportScreens(info, doc);
            if(info.versionCode == null) info.versionCode = fuzzFindInDocument(doc, "manifest", "versionCode");
            if(info.versionName == null) info.versionName = fuzzFindInDocument(doc, "manifest", "versionName");
            else if(info.versionName.StartsWith("@")) VER_ICN[VER_ID] = info.versionName;
            String id = FindInDocument(doc, "application", "android:icon");
            if(null == id)
            {
   
   
                id = fuzzFindInDocument(doc, "manifest", "icon");
            }
            if(null == id)
            {
   
   
                Debug.WriteLine("icon resId Not Found!");
                return info;
            }#
            region 获取APK名称的代码暂时注释, 运行时间太卡顿
            // Find real strings
            if(!info.hasIcon && id != null)
            {
   
   
                if(id.StartsWith("@android:")) VER_ICN[ICN_ID] = "@" + (id.Substring("@android:".Length));
                else VER_ICN[ICN_ID] = String.Format("@{0}", Convert.ToInt32(id).ToString("X4"));
                List < String > resId = new List < String > ();
                for(int i = 0; i < VER_ICN.Length; i++)
                {
   
   
                    if(VER_ICN[i].StartsWith("@")) resId.Add(VER_ICN[i]);
                }
                ApkResourceFinder finder = new ApkResourceFinder();
                info.resStrings = finder.processResourceTable(info.resourcesFileBytes, resId);
                if(!VER_ICN[VER_ID].Equals(""))
                {
                    List < String > versions = null;
                    if(info.resStrings.ContainsKey(VER_ICN[VER_ID].ToUpper())) versions = info.resStrings[VER_ICN[VER_ID].ToUpper()];
                    if(versions != null)
                    {
                        if(versions.Count > 0) info.versionName = versions[0];
                    }
                    else
                    {
                        throw new Exception("VersionName Cant Find in resource with id " + VER_ICN[VER_ID]);
                    }
                }
                List < String > iconPaths = null;
                if(info.resStrings.ContainsKey(VER_ICN[ICN_ID].ToUpper())) iconPaths = info.resStrings[VER_ICN[ICN_ID].ToUpper()];
                if(iconPaths != null && iconPaths.Count > 0)
                {
   
   
                    info.iconFileNameToGet = new List < String > ();
                    info.iconFileName = new List < string > ();
                    foreach(String iconFileName in iconPaths)
                    {
   
   
                        if(iconFileName != null)
                        {
   
   
                            if(iconFileName.Contains(@"/"))
                            {
   
   
                                info.iconFileNameToGet.Add(iconFileName);
                                info.iconFileName.Add(iconFileName);
                                info.hasIcon = true;
                            }
                        }
                    }
                }
                else
                {
   
   
                    throw new Exception("Icon Cant Find in resource with id " + VER_ICN[ICN_ID]);
                }
                if(!VER_ICN[LABEL_ID].Equals(""))
                {
   
   
                    List < String > labels = null;
                    if(info.resStrings.ContainsKey(VER_ICN[LABEL_ID])) labels = info.resStrings[VER_ICN[LABEL_ID]];
                    if(labels.Count > 0)
                    {
   
   
                        info.label = labels[0];
                    }
                }
            }#
            endregion
        }
        catch(Exception e)
        {
   
   
            throw e;
        }
        return info;
    }
    private void ExtractPermission(ApkInfo info, XmlDocument doc, String keyName, String attribName)
    {
   
   
        XmlNodeList usesPermissions = doc.GetElementsByTagName(keyName);
        if(usesPermissions != null)
        {
   
   
            for(int s = 0; s < usesPermissions.Count; s++)
            {
   
   
                XmlNode permissionNode = usesPermissions.Item(s);
                if(permissionNode.NodeType == XmlNodeType.Element)
                {
   
   
                    XmlNode node = permissionNode.Attributes.GetNamedItem(attribName);
                    if(node != null) info.Permissions.Add(node.Value);
                }
            }
        }
    }
    private String FindInDocument(XmlDocument doc, String keyName, String attribName)
    {
   
   
        XmlNodeList usesPermissions = doc.GetElementsByTagName(keyName);
        if(usesPermissions != null)
        {
   
   
            for(int s = 0; s < usesPermissions.Count; s++)
            {
   
   
                XmlNode permissionNode = usesPermissions.Item(s);
                if(permissionNode.NodeType == XmlNodeType.Element)
                {
   
   
                    XmlNode node = permissionNode.Attributes.GetNamedItem(attribName);
                    if(node != null) return node.Value;
                }
            }
        }
        return null;
    }
}

4、APK解析返回类

public class ApkInfo
{
   
   
    /// <summary>
    /// APK名称
    /// </summary>
    public string label
    {
   
   
        get;
        set;
    }
    /// <summary>
    /// APK版本号
    /// </summary>
    public string versionName
    {
   
   
        get;
        set;
    }
    /// <summary>
    /// APK版本编号
    /// </summary>
    public string versionCode
    {
   
   
        get;
        set;
    }
    /// <summary>
    /// APK支持的最小SDK版本
    /// </summary>
    public string minSdkVersion
    {
   
   
        get;
        set;
    }
    /// <summary>
    /// APK的目标SDK版本
    /// </summary>
    public string targetSdkVersion
    {
   
   
        get;
        set;
    }
    /// <summary>
    /// APK包名称
    /// </summary>
    public string packageName
    {
   
   
        get;
        set;
    }
    public static int FINE = 0;
    public static int NULL_VERSION_CODE = 1;
    public static int NULL_VERSION_NAME = 2;
    public static int NULL_PERMISSION = 3;
    public static int NULL_ICON = 4;
    public static int NULL_CERT_FILE = 5;
    public static int BAD_CERT = 6;
    public static int NULL_SF_FILE = 7;
    public static int BAD_SF = 8;
    public static int NULL_MANIFEST = 9;
    public static int NULL_RESOURCES = 10;
    public static int NULL_DEX = 13;
    public static int NULL_METAINFO = 14;
    public static int BAD_JAR = 11;
    public static int BAD_READ_INFO = 12;
    public static int NULL_FILE = 15;
    public static int HAS_REF = 16;
    // 其他不返回属性权限、其他资源文件等等
    public List < String > Permissions;
    public List < String > iconFileName;
    public List < String > iconFileNameToGet;
    public List < String > iconHash;
    public String resourcesFileName;
    public byte[] resourcesFileBytes;
    public bool hasIcon;
    public bool supportSmallScreens;
    public bool supportNormalScreens;
    public bool supportLargeScreens;
    public bool supportAnyDensity;
    public Dictionary < String, List < String >> resStrings;
    public Dictionary < String, String > layoutStrings;
    public static bool supportSmallScreen(byte[] dpi)
    {
   
   
        if(dpi[0] == 1) return true;
        return false;
    }
    public static bool supportNormalScreen(byte[] dpi)
    {
   
   
        if(dpi[1] == 1) return true;
        return false;
    }
    public static bool supportLargeScreen(byte[] dpi)
        {
   
   
            if(dpi[2] == 1) return true;
            return false;
        }
        //public byte[] getDPI()
        //{
   
   
        //    byte[] dpi = new byte[3];
        //    if (this.supportAnyDensity)
        //    {
   
   
        //        dpi[0] = 1;
        //        dpi[1] = 1;
        //        dpi[2] = 1;
        //    }
        //    else
        //    {
   
   
        //        if (this.supportSmallScreens)
        //            dpi[0] = 1;
        //        if (this.supportNormalScreens)
        //            dpi[1] = 1;
        //        if (this.supportLargeScreens)
        //            dpi[2] = 1;
        //    }
        //    return dpi;
        //}
    public ApkInfo()
    {
   
   
        hasIcon = false;
        supportSmallScreens = false;
        supportNormalScreens = false;
        supportLargeScreens = false;
        supportAnyDensity = true;
        versionCode = null;
        versionName = null;
        iconFileName = null;
        iconFileNameToGet = null;
        Permissions = new List < String > ();
    }
    private bool isReference(List < String > strs)
    {
   
   
        try
        {
   
   
            foreach(String str in strs)
            {
   
   
                if(isReference(str)) return true;
            }
        }
        catch(Exception e)
        {
   
   
            throw e;
        }
        return false;
    }
    private bool isReference(String str)
    {
   
   
        try
        {
   
   
            if(str != null && str.StartsWith("@"))
            {
   
   
                int.Parse(str, System.Globalization.NumberStyles.HexNumber);
                return true;
            }
        }
        catch(Exception e)
        {
   
   
            throw e;
        }
        return false;
    }
}

以上就是.net core 从(本地)服务器获取APK文件并解析APK信息的介绍,做此记录,如有帮助,欢迎点赞关注收藏!

目录
相关文章
|
9月前
|
C++ Windows
.NET Framework安装不成功,下载`NET Framework 3.5`文件,Microsoft Visual C++
.NET Framework常见问题及解决方案汇总,涵盖缺失组件、安装失败、错误代码等,提供多种修复方法,包括全能王DLL修复工具、微软官方运行库及命令行安装等,适用于Windows系统,解决应用程序无法运行问题。
1280 3
|
6月前
|
开发框架 .NET C#
ASP.NET Core Blazor 路由配置和导航
大家好,我是码农刚子。本文系统介绍Blazor单页应用的路由机制,涵盖基础配置、路由参数、编程式导航及高级功能。通过@page指令定义路由,支持参数约束、可选参数与通配符捕获,结合NavigationManager实现页面跳转与参数传递,并演示用户管理、产品展示等典型场景,全面掌握Blazor路由从入门到实战的完整方案。
536 6
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
507 5
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
3583 65
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
10月前
|
存储 缓存
.NET 6中Startup.cs文件注入本地缓存策略与服务生命周期管理实践:AddTransient, AddScoped, AddSingleton。
记住,选择正确的服务生命周期并妥善管理它们是至关重要的,因为它们直接影响你的应用程序的性能和行为。就像一个成功的建筑工地,工具箱如果整理得当,工具选择和使用得当,工地的整体效率将会大大提高。
343 0
|
Java API 数据处理
深潜数据海洋:Java文件读写全面解析与实战指南
通过本文的详细解析与实战示例,您可以系统地掌握Java中各种文件读写操作,从基本的读写到高效的NIO操作,再到文件复制、移动和删除。希望这些内容能够帮助您在实际项目中处理文件数据,提高开发效率和代码质量。
593 4
|
Serverless 对象存储 人工智能
智能文件解析:体验阿里云多模态信息提取解决方案
在当今数据驱动的时代,信息的获取和处理效率直接影响着企业决策的速度和质量。然而,面对日益多样化的文件格式(文本、图像、音频、视频),传统的处理方法显然已经无法满足需求。
525 4
智能文件解析:体验阿里云多模态信息提取解决方案
|
Linux C# Windows
.NET使用MiniWord高效生成Word文件
.NET使用MiniWord高效生成Word文件
533 12
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
368 1
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
431 3

热门文章

最新文章

  • 1
    为什么微信发送的APP安装不了,.apk转化为.apk.1
    1203
  • 2
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
    862
  • 3
    Android历史版本与APK文件结构
    1533
  • 4
    Cocos2d-x 游戏开发-打包apk被默认自带了很多不必要的权限导致apk被报毒,如何在Cocos 2d-x中强制去掉不必要的权限-优雅草卓伊凡
    295
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    456
  • 6
    【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
    1370
  • 7
    【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    505
  • 8
    apk安装包EXE,mis程序打包后报毒的正确处理方式-千万不要再人傻钱多被骗-真正的合法途径的处理方式才是正确的-apk安装包EXE,mis程序如何处理-优雅草央千澈
    475
  • 9
    使用Kivy创建“Hello World”应用并打包成APK
    2331
  • 10
    使用keytool查看Android APK签名
    2442
  • 推荐镜像

    更多
  • DNS