Obtener Android .archivo apk VersionName o VersionCode SIN instalar apk

¿Cómo puedo obtener programación obtiene el código de la versión o nombre de la versión de mi apk de AndroidManifest.xml archivo después de descargarlo y sin la necesidad de instalarlo.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xxx.xx.xxx"
    android:versionCode="1"
    android:versionName="1.1" >

Por ejemplo yo quiero comprobar si una nueva versión está subido en mi servicio de IIS, después de instalarlo en el dispositivo, si no es una nueva versión no quiero instalarlo.

  • marque esta stackoverflow.com/a/4761689/1109425
  • Por CIERTO, espero que nadie piensa que una buena solución es descargar el archivo y, a continuación, compruebe si es necesario – que es lo Que la primera frase sugiere. Es de suponer que usted podría querer código que se ejecuta en el servidor, y responde con el número de versión que está disponible.
  • ./aapt d badging release.apk | grep -Po "(?<=\sversion(Code|Name)=')([0-9.]+)"
  • aapt tendrá un costo de alrededor 2.6M espacio en disco, también puede escribir un parser para analizar el archivo apk con AXMLResource que le acaba de costar alrededor de 52k. Consulte Java parseo del xml no declaradas espacio de nombres
InformationsquelleAutor Big.Child | 2012-11-20

8 Kommentare

  1. 397

    Siguientes trabajó para mí desde la línea de comandos:

    aapt dump badging myapp.apk

    NOTA: aapt.exe se encuentra en una build-tools sub-carpeta de SDK. Por ejemplo:

    <sdk_path>/build-tools/23.0.2/aapt.exe
    • Funciona bien, este debe marcar la respuesta correcta, para obtener información, aapt es en build-tools/XX en el sdk.
    • Me encontré con «<sdk_path>/build-tools/21.1.2»
    • Usando Xamarin en un Mac, fue en ~/Library/Developer/Xamarin/android-sdk-macosx/build-tools/{version}
    • ¿Qué es platformBuildVersionName que se imprime cuando se utiliza este comando y por qué es vacío?
    • usted puede crear el archivo bat aapt dump badging %1 pause para arrastrar y soltar cualquier apk
    • Todavía funciona en 2019 con aapt en construir herramientas 28.0.3
    • Esta probado en Mac con herramientas de generación de 28.0.3. /Library/Android/android-sdk/build-tools/28.0.3/aapt dump badging foo.apk. Las grandes obras. @Big.Niño, este debe marcar la respuesta correcta.

  2. 81
    final PackageManager pm = getPackageManager();
    String apkName = "example.apk";
    String fullPath = Environment.getExternalStorageDirectory() + "/" + apkName;        
    PackageInfo info = pm.getPackageArchiveInfo(fullPath, 0);
    Toast.makeText(this, "VersionCode : " + info.versionCode + ", VersionName : " + info.versionName , Toast.LENGTH_LONG).show();
    • ¿cómo puedo leer apk contenido de sin necesidad de instalar de la aplicación? @PatrickCho
    • Esto sí funciona. Y no es necesario instalarlo. Usted apenas tiene un apk en algún lugar de la de su dispositivo de almacenamiento y suministro de la ruta de acceso para el administrador de paquetes. De hecho, devolver el paquete de información.
  3. 43

    Si usted está usando de la versión 2.2 y superior de Android Studio, a continuación, en Android Studio, Crear Analizar APK a continuación, seleccione AndroidManifest.xml archivo.

    • OP preguntó cómo conseguirlo programmatically
    • Porque él no sabía que una herramienta como esta es construido en Android Studio. También pidió a sin necesidad de instalar el apk.
    • Por supuesto que él no sabía es que, debido a que Android Studio no existía cuando esta pregunta se la hicieron. Además, incluso si lo hiciera, esto no resuelve su problema, él quiere que su dispositivo programación comprobar actualizaciones a partir de su servidor IIS, como se señaló en la pregunta. Patrick Cho respuesta explica cómo hacerlo mediante programación sin necesidad de instalar.
  4. 7
    aapt dump badging test.apk | grep "VersionName" | sed -e "s/.*versionName='//" -e "s/' .*//"

    Esto responde a la pregunta por solo devuelve el número de versión como resultado.
    Sin embargo……

    El objetivo, como dicho anteriormente, se debe averiguar si la apk en el servidor es más reciente que la instalada ANTES de intentar descargar o instalar. La forma más sencilla de hacerlo es incluir el número de versión en el nombre de archivo de la apk alojada en el servidor por ejemplo myapp_1.01.apk

    Usted tendrá que establecer el nombre y número de versión de las aplicaciones ya instaladas (si está instalado) con el fin de hacer la comparación. Usted necesitará un dispositivo de raíces o un medio de la instalación de la aapt binario y busybox si no están ya incluidos en la rom.

    Esta secuencia de comandos aparecerá el listado de apps de tu servidor y comparar con cualquiera de las aplicaciones instaladas. El resultado es una lista de marcado para la actualización/instalación.

    #/system/bin/sh
    SERVER_LIST=$(wget -qO- "http://demo.server.com/apk/" | grep 'href' | grep '\.apk' | sed 's/.*href="//' | \
                  sed 's/".*//' | grep -v '\/' | sed -E "s/%/\\\\x/g" | sed -e "s/x20//g" -e "s/\\\\//g")
    LOCAL_LIST=$(for APP in $(pm list packages -f | sed -e 's/package://' -e 's/=.*//' | sort -u); do \
                  INFO=$(echo -n $(aapt dump badging $APP | grep -e 'package: name=' -e 'application: label=')) 2>/dev/null; \
                  PACKAGE=$(echo $INFO | sed "s/.*package: name='//" | sed "s/'.*$//"); \
                  LABEL=$(echo $INFO | sed "s/.*application: label='//" | sed "s/'.*$//"); if [ -z "$LABEL" ]; then LABEL="$PACKAGE"; fi; \
                  VERSION=$(echo $INFO | sed -e "s/.*versionName='//" -e "s/' .*//"); \
                  NAME=$LABEL"_"$VERSION".apk"; echo "$NAME"; \
                  done;)
    OFS=$IFS; IFS=$'\t\n'
    for REMOTE in $SERVER_LIST; do
        INSTALLED=0
        REMOTE_NAME=$(echo $REMOTE | sed 's/_.*//'); REMOTE_VER=$(echo $REMOTE | sed 's/^[^_]*_//g' | sed 's/[^0-9]*//g')
        for LOCAL in $LOCAL_LIST; do
            LOCAL_NAME=$(echo $LOCAL | sed 's/_.*//'); LOCAL_VER=$(echo $LOCAL | sed 's/^[^_]*_//g' | sed 's/[^0-9]*//g')
            if [ "$REMOTE_NAME" == "$LOCAL_NAME" ]; then INSTALLED=1; fi
            if [ "$REMOTE_NAME" == "$LOCAL_NAME" ] && [ ! "$REMOTE_VER" == "$LOCAL_VER" ]; then echo remote=$REMOTE ver=$REMOTE_VER local=$LOCAL ver=$LOCAL_VER; fi
        done
        if [ "$INSTALLED" == "0" ]; then echo "$REMOTE"; fi
    done
    IFS=$OFS

    Como alguien preguntó cómo hacerlo sin el uso de aapt.
    También es posible extraer el apk de información con apktool y un poco de scripting. De esta manera es más lento y no es sencillo en android pero funciona en windows/mac o linux siempre tiene trabajo apktool la instalación.

    #!/bin/sh
    APK=/path/to/your.apk
    TMPDIR=/tmp/apktool
    rm -f -R $TMPDIR
    apktool d -q -f -s --force-manifest -o $TMPDIR $APK
    APK=$(basename $APK)
    VERSION=$(cat $TMPDIR/apktool.yml | grep "versionName" | sed -e "s/versionName: //")
    LABEL=$(cat $TMPDIR/res/values/strings.xml | grep 'string name="title"' | sed -e 's/.*">//' -e 's/<.*//')
    rm -f -R $TMPDIR
    echo ${LABEL}_$(echo $V).apk

    Considerar también la posibilidad de una carpeta de buzón en el servidor. Subir los archivos apk y una tarea cron cambia el nombre y se mueve a su carpeta de actualización.

    #!/bin/sh
    # Drop Folder script for renaming APKs
    # Read apk file from SRC folder and move it to TGT folder while changing filename to APKLABEL_APKVERSION.apk
    # If an existing version of the APK exists in the target folder then script will remove it
    # Define METHOD as "aapt" or "apktool" depending upon what is available on server 
    
    # Variables
    METHOD="aapt"
    SRC="/home/user/public_html/dropfolders/apk"
    TGT="/home/user/public_html/apk"
    if [ -d "$SRC" ];then mkdir -p $SRC
    if [ -d "$TGT" ]then mkdir -p $TGT
    
    # Functions
    get_apk_filename () {
        if [ "$1" = "" ]; then return 1; fi
        local A="$1"
        case $METHOD in
            "apktool")
                local D=/tmp/apktool
                rm -f -R $D
                apktool d -q -f -s --force-manifest -o $D $A
                local A=$(basename $A)
                local V=$(cat $D/apktool.yml | grep "versionName" | sed -e "s/versionName: //")
                local T=$(cat $D/res/values/strings.xml | grep 'string name="title"' | sed -e 's/.*">//' -e 's/<.*//')
                rm -f -R $D<commands>
                ;;
            "aapt")
                local A=$(aapt dump badging $A | grep -e "application-label:" -e "VersionName")
                local V=$(echo $A | sed -e "s/.*versionName='//" -e "s/' .*//")
                local T=$(echo $A | sed -e "s/.*application-label:'//" -e "s/'.*//")
                ;;
            esac
        echo ${T}_$(echo $V).apk
    }
    
    # Begin script
    for APK in $(ls "$SRC"/*.apk); do
        APKNAME=$(get_apk_filename "$APK")
        rm -f $TGT/$(echo APKNAME | sed "s/_.*//")_*.apk
        mv "$APK" "$TGT"/$APKNAME
    done
  5. 5

    Ahora puedo recuperar correctamente la versión de un archivo APK desde su binario de datos XML.

    Este tema es donde tengo la llave de mi respuesta (también he añadido mi versión de Ribo del código):
    Cómo analizar la AndroidManifest.xml archivo dentro de una .paquete apk

    Además, aquí está el análisis de XML de código que escribí, específicamente para obtener la versión:

    Análisis de XML

    /**
     * Verifies at Conductor APK path if package version if newer 
     * 
     * @return True if package found is newer, false otherwise
     */
    public static boolean checkIsNewVersion(String conductorApkPath) {
    
        boolean newVersionExists = false;
    
        //Decompress found APK's Manifest XML
        //Source: https://stackoverflow.com/questions/2097813/how-to-parse-the-androidmanifest-xml-file-inside-an-apk-package/4761689#4761689
        try {
    
            if ((new File(conductorApkPath).exists())) {
    
                JarFile jf = new JarFile(conductorApkPath);
                InputStream is = jf.getInputStream(jf.getEntry("AndroidManifest.xml"));
                byte[] xml = new byte[is.available()];
                int br = is.read(xml);
    
                //Tree tr = TrunkFactory.newTree();
                String xmlResult = SystemPackageTools.decompressXML(xml);
                //prt("XML\n"+tr.list());
    
                if (!xmlResult.isEmpty()) {
    
                    InputStream in = new ByteArrayInputStream(xmlResult.getBytes());
    
                    //Source: http://developer.android.com/training/basics/network-ops/xml.html
                    XmlPullParser parser = Xml.newPullParser();
                    parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
    
                    parser.setInput(in, null);
                    parser.nextTag();
    
                    String name = parser.getName();
                    if (name.equalsIgnoreCase("Manifest")) {
    
                        String pakVersion = parser.getAttributeValue(null, "versionName");
                                //NOTE: This is specific to my project. Replace with whatever is relevant on your side to fetch your project's version
                        String curVersion = SharedData.getPlayerVersion();
    
                        int isNewer = SystemPackageTools.compareVersions(pakVersion, curVersion); 
    
                        newVersionExists = (isNewer == 1); 
                    }
    
                }
            }
    
        } catch (Exception ex) {
            android.util.Log.e(TAG, "getIntents, ex: "+ex);
            ex.printStackTrace();
        }
    
        return newVersionExists;
    }

    Comparación de versiones (visto como SystemPackageTools.compareVersions en el fragmento de código anterior)
    NOTA: Este código está inspirado en el tema siguiente: Eficiente para comparar cadenas de versión en Java

    /**
     * Compare 2 version strings and tell if the first is higher, equal or lower
     * Source: https://stackoverflow.com/questions/6701948/efficient-way-to-compare-version-strings-in-java
     * 
     * @param ver1 Reference version
     * @param ver2 Comparison version
     * 
     * @return 1 if ver1 is higher, 0 if equal, -1 if ver1 is lower
     */
    public static final int compareVersions(String ver1, String ver2) {
    
        String[] vals1 = ver1.split("\\.");
        String[] vals2 = ver2.split("\\.");
        int i=0;
        while(i<vals1.length&&i<vals2.length&&vals1[i].equals(vals2[i])) {
          i++;
        }
    
        if (i<vals1.length&&i<vals2.length) {
            int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i]));
            return diff<0?-1:diff==0?0:1;
        }
    
        return vals1.length<vals2.length?-1:vals1.length==vals2.length?0:1;
    }

    Espero que esto ayude.

    • Se ha actualizado a la nueva Gradle o Android Studio? ¿Todavía funciona? El Robio código no funciona para descomprimir el XML para mí más.
  6. 4

    Para el escenario de actualización, específicamente, un enfoque alternativo podría ser tener un servicio web que proporciona el número de versión actual y comprobar que en lugar de descargar todo el apk solo para comprobar su versión. Podría ahorrar ancho de banda, ser un poco más eficientes (mucho más rápido que la descarga sea un apk si todo el apk que no se necesita la mayoría del tiempo) y de mucho más sencillo de implementar.

    En la forma más simple podría tener un archivo de texto simple en su servidor… http://some-place.com/current-app-version.txt

    Dentro de ese archivo de texto tiene algo como

    3.1.4

    y, a continuación, descargar el archivo y comprobar la versión instalada actualmente.

    La construcción de una más avanzada solución a eso sería implementar un adecuado servicio web y tener una llamada a la api en el lanzamiento que podría regresar algunos json, es decir,http://api.some-place.com/versionCheck:

    {
        "current_version": "3.1.4"
    }
    • Usted está en el camino correcto – no debe descargar el archivo, sólo para obtener su versión. Sólo quiero mencionar que yo no recomendaría crear el archivo de texto de forma MANUAL – demasiado fácil, o que no coincida con el real archivo apk. En su lugar, escribir un script (que utiliza una de las otras respuestas) para mirar dentro de la apk para ver lo que su versión es, almacenando que en el archivo o base de datos, para ser recuperado por los medios que discutir.
    • Sí, en este escenario, el caso es que no se que es necesario para que coincida con la APK en todo, sólo que la versión más reciente está en algún lugar de acceso público.
  7. 4

    Por el momento, esto se puede hacer de la siguiente manera

    $ANDROID_HOME/build-tools/28.0.3/aapt dump badging /<path to>/<app name>.apk

    En General, será:

    $ANDROID_HOME/build-tools/<version_of_build_tools>/aapt dump badging /<path to>/<app name>.apk
  8. 2
        EditText ET1 = (EditText) findViewById(R.id.editText1);
    
        PackageInfo pinfo;
        try {
            pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            String versionName = pinfo.versionName;
            ET1.setText(versionName);
            //ET2.setText(versionNumber);
        } catch (NameNotFoundException e) {
            //TODO Auto-generated catch block
            e.printStackTrace();
        }
    • Esto no es una respuesta a la pregunta. Este es el código que, dentro de una aplicación en ejecución, tiene un poco de información de la versión, y la muestra. La pregunta es cómo obtener esta información de un archivo APK, sin necesidad de instalar la aplicación.
    • Esto es sólo una aplicación ya instalada, no para una .archivo apk.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea