PHP:如何从Android .apk文件中获取版本?

19

我正在尝试创建一个PHP脚本,从Android APK文件中获取应用程序版本。从APK(zip)文件中提取XML文件,然后解析XML是一种方法,但我认为应该有更简单的方法。类似于PHP手册的第三个例子。 有什么想法可以创建这个脚本吗?


您是否有在服务器上安装Android SDK的可能性? - Francesco Laurita
你想获取哪个zip文件的信息? - 2ndkauboy
@Francesco:没有Android SDK @Kau-Boy:zip(apk)文件位于带有php脚本的服务器上 是否可以像我发布的链接中那样做(示例#3)? - Solata
5个回答

48
如果您在服务器上安装了Android SDK,您可以使用PHP的exec(或类似的功能)来执行aapt工具(位于$ANDROID_HOME/platforms/android-X/tools中)。
$ aapt dump badging myapp.apk
输出应包括:
package: name='com.example.myapp' versionCode='1530' versionName='1.5.3'
如果由于某种原因无法安装Android SDK,则需要解析Android的二进制XML格式。 APK zip结构内部的AndroidManifest.xml文件不是纯文本。
您需要将Java中类似于AXMLParser的实用程序移植到PHP中。

没有在服务器上安装Android SDK,使用PHP脚本。我正在寻找像我发布的链接中所示的解决方案(例如#3)。 - Solata
@ChristopherOrr 能否举个第一种方式的例子?我在我的Windows服务器上跑不起来! - iSun
@ChristopherOrr 我的代码 exec("e:\\Develop files\\androidsdk\\platform-tools\\aapt.exe \\aapt dump badging bz.apk",$resultSet); print_r($resultSet); - iSun

10

我已经创建了一组PHP函数,可以找到APK的Version Code。这基于AndroidMainfest.xml文件包含版本代码作为第一个标签,并基于axml(二进制Android XML格式),如此处所述

    <?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://dev59.com/u3I95IYBdhLWcg3w5iY4#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++;
    }
}
    ?>

1
嗨@CHeil402,如何获取版本名称? - Yanuar Lutfi

1
转储格式有点奇怪,不是很容易处理。仅为了扩展其他答案,这是我用来从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 }'

1
aapt dump badging ./apkfile.apk | grep sdkVersion -i

您将获得一个易于阅读的表单。

sdkVersion:'14'
targetSdkVersion:'14'

如果您已经安装了Android SDK,请在系统中查找aapt。我的路径是:
<SDKPATH>/build-tools/19.0.3/aapt

1

在CLI中使用:

apktool if 1.apk
aapt dump badging 1.apk

您可以使用PHP中的execshell_exec命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接