【问题标题】:PHP: How to get version from android .apk file?PHP:如何从 android .apk 文件中获取版本?
【发布时间】:2010-06-10 12:39:57
【问题描述】:

我正在尝试创建一个 PHP 脚本来从 Android APK 文件中获取应用程序版本。 从 APK (zip) 文件中提取 XML 文件然后解析 XML 是一种方法,但我想它应该更简单。类似PHP Manual,例如#3。 任何想法如何创建脚本?

【问题讨论】:

  • 你有可能在服务器上安装Android SDK吗?
  • 您想获取相关信息的 zip 位于何处?
  • @Francesco: 没有 Android SDK @Kau-Boy: zip (apk) 文件位于带有 php 脚本的服务器上是否可以在我发布的链接中执行类似操作(示例 #3)?跨度>

标签: php xml android version apk


【解决方案1】:

如果您在服务器上安装了 Android SDK,则可以使用 PHP 的 exec(或类似工具)来执行 aapt 工具(在 $ANDROID_HOME/platforms/android-X/tools 中)。

$ aapt dump badging myapp.apk

并且输出应该包括:

包:name='com.example.myapp' versionCode='1530' versionName='1.5.3'

如果您出于某种原因无法安装 Android SDK,那么您将需要解析 Android 的二进制 XML 格式。 APK zip 结构中的AndroidManifest.xml 文件不是纯文本。

您需要将 utility like AXMLParser 从 Java 移植到 PHP。

【讨论】:

  • 服务器上没有 Android SDK,带有 PHP 脚本。我正在寻找我发布的链接中的解决方案(示例 #3)
  • @ChristopherOrr 你能提供一个关于第一种方式的例子吗,我无法通过我的 Windows Server 运行它!
  • @ChristopherOrr 我的代码exec("e:\\Develop files\\androidsdk\\platform-tools\\aapt.exe \\aapt dump badging bz.apk",$resultSet); print_r($resultSet);
【解决方案2】:

我创建了一组 PHP 函数,它们可以只查找 APK 的版本代码。这是基于 AndroidMainfest.xml 文件包含版本代码作为第一个标签的事实,并且基于 axml(二进制 Android XML 格式)作为 described here

    <?php
$APKLocation = "PATH TO APK GOES HERE";

$versionCode = getVersionCodeFromAPK($APKLocation);
echo $versionCode;

//Based on the fact that the Version Code is the first tag in the AndroidManifest.xml file, this will return its value
//PHP implementation based on the AXML format described here: https://stackoverflow.com/questions/2097813/how-to-parse-the-androidmanifest-xml-file-inside-an-apk-package/14814245#14814245
function getVersionCodeFromAPK($APKLocation) {

    $versionCode = "N/A";

    //AXML LEW 32-bit word (hex) for a start tag
    $XMLStartTag = "00100102";

    //APK is esentially a zip file, so open it
    $zip = zip_open($APKLocation);
    if ($zip) {
        while ($zip_entry = zip_read($zip)) {
            //Look for the AndroidManifest.xml file in the APK root directory
            if (zip_entry_name($zip_entry) == "AndroidManifest.xml") {
                //Get the contents of the file in hex format
                $axml = getHex($zip, $zip_entry);
                //Convert AXML hex file into an array of 32-bit words
                $axmlArr = convert2wordArray($axml);
                //Convert AXML 32-bit word array into Little Endian format 32-bit word array
                $axmlArr = convert2LEWwordArray($axmlArr);
                //Get first AXML open tag word index
                $firstStartTagword = findWord($axmlArr, $XMLStartTag);
                //The version code is 13 words after the first open tag word
                $versionCode = intval($axmlArr[$firstStartTagword + 13], 16);

                break;
            }
        }
    }
    zip_close($zip);

    return $versionCode;
}

//Get the contents of the file in hex format
function getHex($zip, $zip_entry) {
    if (zip_entry_open($zip, $zip_entry, 'r')) {
        $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
        $hex = unpack("H*", $buf);
        return current($hex);
    }
}

    //Given a hex byte stream, return an array of words
function convert2wordArray($hex) {
    $wordArr = array();
    $numwords = strlen($hex)/8;

    for ($i = 0; $i < $numwords; $i++)
        $wordArr[] = substr($hex, $i * 8, 8);

    return $wordArr;
}

//Given an array of words, convert them to Little Endian format (LSB first)
function convert2LEWwordArray($wordArr) {
    $LEWArr = array();

    foreach($wordArr as $word) {
        $LEWword = "";
        for ($i = 0; $i < strlen($word)/2; $i++)
            $LEWword .= substr($word, (strlen($word) - ($i*2) - 2), 2);
        $LEWArr[] = $LEWword;
    }

    return $LEWArr;
}

//Find a word in the word array and return its index value
function findWord($wordArr, $wordToFind) {
    $currentword = 0;
    foreach ($wordArr as $word) {
        if ($word == $wordToFind)
            return $currentword;
        else
            $currentword++;
    }
}
    ?>

【讨论】:

  • 嗨@CHeil402 如何获取版本名称
【解决方案3】:

在 CLI 中使用:

apktool if 1.apk
aapt dump badging 1.apk

您可以使用execshell_exec 在PHP 中使用这些命令。

【讨论】:

    【解决方案4】:
    aapt dump badging ./apkfile.apk | grep sdkVersion -i
    

    你会得到一个人类可读的表格。

    sdkVersion:'14'
    targetSdkVersion:'14'
    

    如果您安装了 Android SDK,只需在您的系统中查找 aapt。 我的在:

    <SDKPATH>/build-tools/19.0.3/aapt
    

    【讨论】:

      【解决方案5】:

      转储格式有点奇怪,而且不是最容易使用的。只是为了扩展其他一些答案,这是我用来从 APK 文件中解析名称和版本的 shell 脚本。

      aapt d badging PACKAGE | gawk $'match($0, /^application-label:\'([^\']*)\'/, a) { n = a[1] }
                                     match($0, /versionName=\'([^\']*)\'/, b) { v=b[1] }
                                     END { if ( length(n)>0 && length(v)>0 ) { print n, v } }'
      

      如果您只想要版本,那么显然它可以简单得多。

      aapt d badging PACKAGE | gawk $'match($0, /versionName=\'([^\']*)\'/, v) { print v[1] }'
      

      以下是适用于 gawk 和 mawk 的变体(在转储格式发生变化的情况下耐用性稍差,但应该没问题):

      aapt d badging PACKAGE | mawk -F\' '$1 ~ /^application-label:$/ { n=$2 }
                                          $5 ~ /^ versionName=$/ { v=$6 }
                                          END{ if ( length(n)>0 && length(v)>0 ) { print n, v } }'
      
      aapt d badging PACKAGE | mawk -F\' '$5 ~ /^ versionName=$/ { print $6 }'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-01
        • 1970-01-01
        • 2018-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        相关资源
        最近更新 更多