Parse_APK_with_NET

Parse APK Manifest with C# .NET

knowventBanner

During my development of the Iteedee.BetaDepot I was in need of the ability to Parse APK’s. The data I needed to glean from these packages was information like Package Name, Package Version, Icon, etc. Unfortunately there was no library written in .NET to read the manifest file and its related resources.

The packaging and construction of APK files is rather simple on the surface. APK’s are really just compressed zip files. However, the parsing the APK’s AndroidManifest.xml and Resources.arsc files are in a fairly complicated binary format. Simply unzipping the APK and reading the files as text is not going to work. You need additional binary parsing to read these files.

Iteedee.ApkReader

I have open sourced a .NET library written in C# for reading/parsing APK manifest (AndroidManifest.xml) and resource data (Resources.arsc). You can find the Iteedee.ApkReader project on Github

The primary goal of this library is to parse Android Application package meta-data. There are many scenarios where you might need to glean information about your android package, specifically in continuous integration setups.

To accomplish this task, I was required to port over the APK parsing tool code into C#/.NET. I based my logic on the APK-Parser tool which is written in Java. I also used c# code found here that parses the AndroidManifest.xml file into an XmlDocument object.

Using the ApkReader Library

The library handles everything after you have uncompressed/unzipped the APK using your choice tool or library. I have used the ICSharpCode.SharpZipLib library to uncompressed the APK in my example.

Below, I am uncompressing the AndroidManifest.xml and Resources.arsc files and passing the byte array data to the ApkReader library:

byte[] manifestData = null;
byte[] resourcesData = null;
using (ICSharpCode.SharpZipLib.Zip.ZipInputStream zip = new ICSharpCode.SharpZipLib.Zip.ZipInputStream(File.OpenRead(path)))
{
    using (var filestream = new FileStream(path, FileMode.Open, FileAccess.Read))
    {
        ICSharpCode.SharpZipLib.Zip.ZipFile zipfile = new ICSharpCode.SharpZipLib.Zip.ZipFile(filestream);
        ICSharpCode.SharpZipLib.Zip.ZipEntry item;
        while ((item = zip.GetNextEntry()) != null)
        {
            if (item.Name.ToLower() == "androidmanifest.xml")
            {
                manifestData = new byte[50 * 1024];
                using (Stream strm = zipfile.GetInputStream(item))
                {
                    strm.Read(manifestData, 0, manifestData.Length);
                }

            }
            if (item.Name.ToLower() == "resources.arsc")
            {
                using (Stream strm = zipfile.GetInputStream(item))
                {
                    using (BinaryReader s = new BinaryReader(strm))
                    {
                        resourcesData = s.ReadBytes((int)s.BaseStream.Length);

                    }
                }
            }
        }
    }
}

After you have uncompressed and extracted the necessary data, simply pass in the data objects and it returns an APKInfo object.

ApkReader apkReader = new ApkReader();
ApkInfo info = apkReader.extractInfo(manifestData, resourcesData);

APKInfo object contains all of the meta-data for that APK.

Console.WriteLine(string.Format("Package Name: {0}", info.packageName));
Console.WriteLine(string.Format("Version Name: {0}", info.versionName));
Console.WriteLine(string.Format("Version Code: {0}", info.versionCode));

Console.WriteLine(string.Format("App Has Icon: {0}", info.hasIcon));
if(info.iconFileName.Count > 0)
    Console.WriteLine(string.Format("App Icon: {0}", info.iconFileName[0]));
Console.WriteLine(string.Format("Min SDK Version: {0}", info.minSdkVersion));
Console.WriteLine(string.Format("Target SDK Version: {0}", info.targetSdkVersion));

if (info.Permissions != null && info.Permissions.Count > 0)
{
    Console.WriteLine("Permissions:");
    info.Permissions.ForEach(f =>
    {
        Console.WriteLine(string.Format("   {0}", f));
    });
}
else
    Console.WriteLine("No Permissions Found");

Console.WriteLine(string.Format("Supports Any Density: {0}", info.supportAnyDensity));
Console.WriteLine(string.Format("Supports Large Screens: {0}", info.supportLargeScreens));
Console.WriteLine(string.Format("Supports Normal Screens: {0}", info.supportNormalScreens));
Console.WriteLine(string.Format("Supports Small Screens: {0}", info.supportSmallScreens));
Posted in .NET, Android, Mobile and tagged .
  • INFINUM

    i have too many exceptions, such as “Unrecognized tag code ‘100104’ at offset 7260” in androidmanifest.

  • elsadany

    great project
    but what about update in manifest
    thanks

  • Justin Hyland

    Others have experienced this same issue. I haven’t had time to support this library beyond its conception. However, another developer has resolved such issue but hasn’t submitted a code fix to the repository for others to use. Perhaps his documentation of the fix will help you or you can reach out to him to. Here is the issue ticket:
    https://github.com/hylander0/Iteedee.ApkReader/issues/5