本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《
1、apk解析除了使用客户端利用aapt.exe、unzip.exe开发客户端解析外,还可以直接利用服务进行解析
[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 = ReadAPK.ReadApkFromPath(fileName);
catch(Exception ex)
return ErrorResult("APP上传失败!--> APK解析失败,失败原因为:" + ex.Message, 111150);
return SuccessResult(apk, "APK解析成功");
return ErrorResult("APP上传失败!--> 从服务器获取APK文件失败,请联系网站管理员!", 111151);
2、ReadAPK APK解析帮助类
public class ReadAPK
public static ApkInfo ReadApkFromPath(string path)
byte[] manifestData = null;
byte[] resourcesData = null;
var manifest = "AndroidManifest.xml";
var resources = "resources.arsc";
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
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;
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();
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] = "";
XmlDocument doc = manifestXml;
if(doc == null) throw new Exception("Document initialize failed");
info.resourcesFileName = "resources.arsx";
info.resourcesFileBytes = resources_arsx;
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"));
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名称的代码暂时注释, 运行时间太卡顿
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];
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;
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
public string label
get;
set;
public string versionName
get;
set;
public string versionCode
get;
set;
public string minSdkVersion
get;
set;
public string targetSdkVersion
get;
set;
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;