Pregunta

Estoy tratando de crear un script PHP para obtener la versión de la aplicación del archivo Android APK. Extraer el archivo XML del archivo APK (ZIP) y luego analizar XML es una forma, pero supongo que debería ser más simple. Algo como Manual de PHP, Ejemplo #3. ¿Alguna idea de cómo crear el guión?

¿Fue útil?

Solución

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.

Otros consejos

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++;
    }
}
    ?>

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.

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

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 $'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.

aapt d badging PACKAGE | gawk $'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):

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 }'
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top