c#調用aapt查看apk文件信息功能實現


第一篇隨筆就此開始。

 

1. 起源

思路源自於項目開發過程中。需要確認apk文件版本以驗證其功能差異以便於定位問題,於是度娘,得到APK信息查看器(APK-info)這個工具,其版本號為0.2。
它能顯示apk詳細的信息,如下圖示:

但它使用不夠方便,只能通過雙擊打開對話框找到apk文件然后顯示,或者拖放apk到其圖標上打開,不支持拖放至界面打開。它也沒有再打開入口,且對中文支持很不好,如右圖百度手機衛士apk信息。

 

2. 原理

析其原理,原來通過aapt.exe解開apk包中AndroidManifest.xml文件來實現信息展示。
而aapt.exe使用方法,網上諸多教程。apk信息盡存於AndroidManifest.xml中,它是加密的xml文件,用aapt之dump命令做個解析嘗試,其語法如下:

>aapt dump badging QQ_482.apk

似乎想要的信息都有了……慢着,中文呢?
>aapt dump badging QQ_482.apk

中文顯示亂碼。亂就亂吧,咱轉碼!
如何不自己寫個類似工具?好,整!

 

3. 實現

以此為思路,c#實現解析,獲取cmd管道輸出數據,核心代碼如下(為界面響流暢,我置解析入一線程中):

        private void Decoder(object state)
        {
            if (!File.Exists(this.apkPath))
                return;
            string aaptPath = Path.Combine(this.appPath, @"tools\aapt.exe");
            if (!File.Exists(aaptPath))
                aaptPath = Path.Combine(this.appPath, @"aapt.exe");
            if (!File.Exists(aaptPath))
            {
                var handler = AaptNotFoundEvent;
                if (handler != null)
                    handler();
                return;
            }

            var startInfo = new ProcessStartInfo(aaptPath);
            string args = string.Format("dump badging \"{0}\"", this.apkPath);
            startInfo.Arguments = args;
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.CreateNoWindow = true;
            using (var process = Process.Start(startInfo))
            {
                var sr = process.StandardOutput;
                while (!sr.EndOfStream)
                {
                    infos.Add(sr.ReadLine());
                }
                process.WaitForExit();
                //解析
                ParseInfo(sr.CurrentEncoding);
            }
        }
//application: label='MobileGo™' icon='r/l/icon.png'
if (info.IndexOf("application:") == 0)
{
    string appName = GetKeyValue(info, "label=");    
    this.AppName = Encoding.UTF8.GetString(currentEncoding.GetBytes(appName));
    this.IconPath = GetKeyValue(info, "icon=");
    GetAppIcon(this.IconPath);
}

其執行界面如下:

可以看得出,對中文支持,仍然不夠友好,即便通過utf-8到默認中文編碼轉換。
怎么辦呢?

 

4. 改進

而用其直接輸出於一外部文件中,中文顯示卻是正確的:
>aapt dump badging QQshurufa_1991.apk > info.txt

解析輸出文件吧!對這種方案,我一開始是抵觸的,因為不想額外成生文件;能截用內部cmd管道輸出,我就不願生成外部文件,說是情懷也好潔癖也罷,只是個人喜好。
但目前轉碼方案嘗試無效,就只得用吧,獲取輸出信息代碼如下:

        private void Decoder(object state)
        {
            if (!File.Exists(this.apkPath))
                return;
            string aaptPath = Path.Combine(this.appPath, @"tools\aapt.exe");
            if (!File.Exists(aaptPath))
                aaptPath = Path.Combine(this.appPath, @"aapt.exe");
            if (!File.Exists(aaptPath))
            {
                var handler = AaptNotFound;
                if (handler != null)
                    handler();
                return;
            }

            StringBuilder sb = new StringBuilder(255);
            int result = GetShortPathName(aaptPath, sb, 255);
            if (result != 0)
                aaptPath = sb.ToString();

            var startInfo = new ProcessStartInfo("cmd.exe");
            string dumpFile = Path.GetTempFileName();
            //如此費事做中轉,只為處理中文亂碼
            string args = string.Format("/k {0} dump badging \"{1}\" > \"{2}\" &exit", aaptPath, this.apkPath, dumpFile);
            startInfo.Arguments = args;
            startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            this.infos.Clear();
            using (var process = Process.Start(startInfo))
            {
                process.WaitForExit(2000);
            }
            if (File.Exists(dumpFile))
            {
                //解析
                using (var sr = new StreamReader(dumpFile, Encoding.UTF8))
                {
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        this.infos.Add(line);
                    }
                    ParseInfo();
                }
                try
                {
                    File.Delete(dumpFile);
                }
                catch
                {
                }
            }
        }

好吧,一切正常了……只是其中構建cmd管道腳本,頗為費些工夫。

看看下圖中文信息顯示,一切正常:

 

5. 后記

這是我第一篇博客,寫代碼十數年,雖時時想記錄經驗與心得,奈何懶惰,至此方忍不住,終於寫出來。

其實此例成完成已久,只是近來更做完善,查詢資料過程中看到Meteoric_cry的博文:windows下apk查看工具的原理,頗覺異曲同工之妙,而他也因此寫了APK Helper這一工具,簡單而易用。

本欲置源代碼入Github,奈何折騰半天,亦未成功,因此計划暫且擱置。

此工具我置於網上,亦根據需要作不定時更新,如有需要伙伴盡管拿去用,下載地址為:ApkInfo.zip。若小伙伴有其它需要,可留言以待

 

6. 追加

2017-03-14更新:費了許多工夫,終於傳代碼至GitHub,今夜可以安睡。項目址為:https://github.com/awei78/ApkInfo
希望有需要的朋友以做參考。或者,咱們一起更完善它,以適合實際需要。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM