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

发布于 2024-09-05 06:41:53 字数 208 浏览 3 评论 0原文

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

I am trying to create a PHP script to get the app version from Android APK file.
Extracting XML file from the APK (zip) file and then parsing XML is one way, but I guess it should be simpler. Something like PHP Manual, example #3.
Any ideas how to create the script?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

淡写薰衣草的香 2024-09-12 06:41:53

如果服务器上安装了 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 文件不是纯文本。

您需要移植类似 AXMLParser 的实用程序 从 Java 到 PHP。

If you have the Android SDK installed on the server, you can use PHP's exec (or similar) to execute the aapt tool (in $ANDROID_HOME/platforms/android-X/tools).

$ aapt dump badging myapp.apk

And the output should include:

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

If you can't install the Android SDK, for whatever reason, then you will need to parse Android's binary XML format. The AndroidManifest.xml file inside the APK zip structure is not plain text.

You would need to port a utility like AXMLParser from Java to PHP.

亢潮 2024-09-12 06:41:53

我创建了一组 PHP 函数,可以仅查找 APK 的版本代码。这是基于以下事实: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://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++;
    }
}
    ?>

I've created a set of PHP functions that will find just the Version Code of an APK. This is based on the fact that the AndroidMainfest.xml file contains the version code as the first tag, and based on the axml (binary Android XML format) as 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++;
    }
}
    ?>
我是男神闪亮亮 2024-09-12 06:41:53

在 CLI 中使用它:

apktool if 1.apk
aapt dump badging 1.apk

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

Use this in the CLI:

apktool if 1.apk
aapt dump badging 1.apk

You can use these commands in PHP using exec or shell_exec.

笨笨の傻瓜 2024-09-12 06:41:53
aapt dump badging ./apkfile.apk | grep sdkVersion -i

您将获得人类可读的形式。

sdkVersion:'14'
targetSdkVersion:'14'

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

<SDKPATH>/build-tools/19.0.3/aapt
aapt dump badging ./apkfile.apk | grep sdkVersion -i

You will get a human readable form.

sdkVersion:'14'
targetSdkVersion:'14'

Just look for aapt in your system if you have Android SDK installed.
Mine is in:

<SDKPATH>/build-tools/19.0.3/aapt
薔薇婲 2024-09-12 06:41:53

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

aapt d badging PACKAGE | gawk 

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

aapt d badging PACKAGE | gawk 

以下是适用于 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 }'
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 } }'

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


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


match($0, /versionName=\'([^\']*)\'/, v) { print v[1] }'

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

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 } }'

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

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

The dump format is a little odd and not the easiest to work with. Just to expand on some of the other answers, this is a shell script that I am using to parse out name and version from APK files.

aapt d badging PACKAGE | gawk 

If you just want the version then obviously it can be much simpler.

aapt d badging PACKAGE | gawk 

Here are variations suitable for both gawk and mawk (a little less durable in case the dump format changes but should be fine):

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 }'
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 } }'

If you just want the version then obviously it can be much simpler.


Here are variations suitable for both gawk and mawk (a little less durable in case the dump format changes but should be fine):


match($0, /versionName=\'([^\']*)\'/, v) { print v[1] }'

Here are variations suitable for both gawk and mawk (a little less durable in case the dump format changes but should be fine):

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 } }'

If you just want the version then obviously it can be much simpler.

Here are variations suitable for both gawk and mawk (a little less durable in case the dump format changes but should be fine):

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文